+static unsigned char
+is_mac48_linktype(const int linktype)
+{
+ switch (linktype) {
+ case DLT_EN10MB:
+ case DLT_FDDI:
+ case DLT_IEEE802:
+ case DLT_IEEE802_11:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IP_OVER_FC:
+ case DLT_NETANALYZER:
+ case DLT_NETANALYZER_TRANSPARENT:
+ case DLT_PPI:
+ case DLT_PRISM_HEADER:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static struct block *
+gen_mac48host(compiler_state_t *cstate, const u_char *eaddr, const u_char dir,
+ const char *keyword)
+{
+ struct block *b1 = NULL;
+ u_int src_off, dst_off;
+
+ switch (cstate->linktype) {
+ case DLT_EN10MB:
+ case DLT_NETANALYZER:
+ case DLT_NETANALYZER_TRANSPARENT:
+ b1 = gen_prevlinkhdr_check(cstate);
+ src_off = 6;
+ dst_off = 0;
+ break;
+ case DLT_FDDI:
+ src_off = 6 + 1 + cstate->pcap_fddipad;
+ dst_off = 0 + 1 + cstate->pcap_fddipad;
+ break;
+ case DLT_IEEE802:
+ src_off = 8;
+ dst_off = 2;
+ break;
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ return gen_wlanhostop(cstate, eaddr, dir);
+ case DLT_IP_OVER_FC:
+ /*
+ * Assume that the addresses are IEEE 48-bit MAC addresses,
+ * as RFC 2625 states.
+ */
+ src_off = 10;
+ dst_off = 2;
+ break;
+ case DLT_SUNATM:
+ /*
+ * This is LLC-multiplexed traffic; if it were
+ * LANE, cstate->linktype would have been set to
+ * DLT_EN10MB.
+ */
+ /* FALLTHROUGH */
+ default:
+ fail_kw_on_dlt(cstate, keyword);
+ }
+
+ struct block *b0, *tmp;
+
+ switch (dir) {
+ case Q_SRC:
+ b0 = gen_bcmp(cstate, OR_LINKHDR, src_off, 6, eaddr);
+ break;
+ case Q_DST:
+ b0 = gen_bcmp(cstate, OR_LINKHDR, dst_off, 6, eaddr);
+ break;
+ case Q_AND:
+ tmp = gen_bcmp(cstate, OR_LINKHDR, src_off, 6, eaddr);
+ b0 = gen_bcmp(cstate, OR_LINKHDR, dst_off, 6, eaddr);
+ gen_and(tmp, b0);
+ break;
+ case Q_DEFAULT:
+ case Q_OR:
+ tmp = gen_bcmp(cstate, OR_LINKHDR, src_off, 6, eaddr);
+ b0 = gen_bcmp(cstate, OR_LINKHDR, dst_off, 6, eaddr);
+ gen_or(tmp, b0);
+ break;
+ default:
+ bpf_error(cstate, ERRSTR_802_11_ONLY_KW, dqkw(dir));
+ }
+
+ if (b1 != NULL)
+ gen_and(b1, b0);
+ return b0;
+}
+