case DLT_FDDI:
/*
- * XXX - check for asynchronous frames, as per RFC 1103.
+ * XXX - check for LLC frames.
*/
return gen_llc_linktype(proto);
/*NOTREACHED*/
return gen_bcmp(OR_MACPL, 0, 8, snapblock);
}
+/*
+ * Generate code to match frames with an LLC header.
+ */
+struct block *
+gen_llc(void)
+{
+ struct block *b0, *b1;
+
+ switch (linktype) {
+
+ case DLT_EN10MB:
+ /*
+ * We check for an Ethernet type field less than
+ * 1500, which means it's an 802.3 length field.
+ */
+ b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
+ gen_not(b0);
+
+ /*
+ * Now check for the purported DSAP and SSAP not being
+ * 0xFF, to rule out NetWare-over-802.3.
+ */
+ b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)0xFFFF);
+ gen_not(b1);
+ gen_and(b0, b1);
+ return b1;
+
+ case DLT_SUNATM:
+ /*
+ * We check for LLC traffic.
+ */
+ b0 = gen_atmtype_abbrev(A_LLC);
+ return b0;
+
+ case DLT_IEEE802: /* Token Ring */
+ /*
+ * XXX - check for LLC frames.
+ */
+ return gen_true();
+
+ case DLT_FDDI:
+ /*
+ * XXX - check for LLC frames.
+ */
+ return gen_true();
+
+ case DLT_ATM_RFC1483:
+ /*
+ * For LLC encapsulation, these are defined to have an
+ * 802.2 LLC header.
+ *
+ * For VC encapsulation, they don't, but there's no
+ * way to check for that; the protocol used on the VC
+ * is negotiated out of band.
+ */
+ return gen_true();
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_PPI:
+ /*
+ * Check that we have a data frame.
+ */
+ b0 = gen_check_802_11_data_frame();
+ return b0;
+
+ default:
+ bpf_error("'llc' not supported for linktype %d", linktype);
+ /* NOTREACHED */
+ }
+}
+
+struct block *
+gen_llc_i(void)
+{
+ struct block *b0, *b1;
+ struct slist *s;
+
+ /*
+ * Check whether this is an LLC frame.
+ */
+ b0 = gen_llc();
+
+ /*
+ * Load the control byte and test the low-order bit; it must
+ * be clear for I frames.
+ */
+ s = gen_load_a(OR_MACPL, 2, BPF_B);
+ b1 = new_block(JMP(BPF_JSET));
+ b1->s.k = 0x01;
+ b1->stmts = s;
+ gen_not(b1);
+ gen_and(b0, b1);
+ return b1;
+}
+
+struct block *
+gen_llc_s(void)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Check whether this is an LLC frame.
+ */
+ b0 = gen_llc();
+
+ /*
+ * Now compare the low-order 2 bit of the control byte against
+ * the appropriate value for S frames.
+ */
+ b1 = gen_mcmp(OR_MACPL, 2, BPF_B, LLC_S_FMT, 0x03);
+ gen_and(b0, b1);
+ return b1;
+}
+
+struct block *
+gen_llc_u(void)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Check whether this is an LLC frame.
+ */
+ b0 = gen_llc();
+
+ /*
+ * Now compare the low-order 2 bit of the control byte against
+ * the appropriate value for U frames.
+ */
+ b1 = gen_mcmp(OR_MACPL, 2, BPF_B, LLC_U_FMT, 0x03);
+ gen_and(b0, b1);
+ return b1;
+}
+
+struct block *
+gen_llc_s_subtype(bpf_u_int32 subtype)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Check whether this is an LLC frame.
+ */
+ b0 = gen_llc();
+
+ /*
+ * Now check for an S frame with the appropriate type.
+ */
+ b1 = gen_mcmp(OR_MACPL, 2, BPF_B, subtype, LLC_S_CMD_MASK);
+ gen_and(b0, b1);
+ return b1;
+}
+
+struct block *
+gen_llc_u_subtype(bpf_u_int32 subtype)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Check whether this is an LLC frame.
+ */
+ b0 = gen_llc();
+
+ /*
+ * Now check for a U frame with the appropriate type.
+ */
+ b1 = gen_mcmp(OR_MACPL, 2, BPF_B, subtype, LLC_U_CMD_MASK);
+ gen_and(b0, b1);
+ return b1;
+}
+
/*
* Generate code to match a particular packet type, for link-layer types
* using 802.2 LLC headers.
struct block *gen_multicast(int);
struct block *gen_inbound(int);
+struct block *gen_llc(void);
+struct block *gen_llc_i(void);
+struct block *gen_llc_s(void);
+struct block *gen_llc_u(void);
+struct block *gen_llc_s_subtype(bpf_u_int32);
+struct block *gen_llc_u_subtype(bpf_u_int32);
+
struct block *gen_vlan(int);
struct block *gen_mpls(int);
#include <net/pfvar.h>
#include <net/if_pflog.h>
#endif
+#include "llc.h"
#include "ieee80211.h"
#include <pcap/namedb.h>
{ IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "qos-cf-ack-poll" },
{ 0, NULL }
};
+static const struct tok llc_s_subtypes[] = {
+ { LLC_RR, "rr" },
+ { LLC_RNR, "rnr" },
+ { LLC_REJ, "rej" },
+ { 0, NULL }
+};
+static const struct tok llc_u_subtypes[] = {
+ { LLC_UI, "ui" },
+ { LLC_UA, "ua" },
+ { LLC_DISC, "disc" },
+ { LLC_DM, "dm" },
+ { LLC_SABME, "sabme" },
+ { LLC_TEST, "test" },
+ { LLC_XID, "xid" },
+ { LLC_FRMR, "frmr" },
+ { 0, NULL }
+};
struct type2tok {
int type;
const struct tok *tok;
%type <a> arth narth
%type <i> byteop pname pnum relop irelop
%type <blk> and or paren not null prog
-%type <rblk> other pfvar p80211
+%type <rblk> other pfvar p80211 pllc
%type <i> atmtype atmmultitype
%type <blk> atmfield
%type <blk> atmfieldvalue atmvalue atmlistvalue
| PPPOES { $$ = gen_pppoes(-1); }
| pfvar { $$ = $1; }
| pqual p80211 { $$ = $2; }
+ | pllc { $$ = $1; }
;
pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); }
}
;
+pllc: LLC { $$ = gen_llc(); }
+ | LLC ID { if (pcap_strcasecmp($2, "i") == 0)
+ $$ = gen_llc_i();
+ else if (pcap_strcasecmp($2, "s") == 0)
+ $$ = gen_llc_s();
+ else if (pcap_strcasecmp($2, "u") == 0)
+ $$ = gen_llc_u();
+ else {
+ u_int subtype;
+
+ subtype = str2tok($2, llc_s_subtypes);
+ if (subtype != -1)
+ $$ = gen_llc_s_subtype(subtype);
+ else {
+ subtype = str2tok($2, llc_u_subtypes);
+ if (subtype == -1)
+ bpf_error("unknown LLC type name \"%s\"", $2);
+ $$ = gen_llc_u_subtype(subtype);
+ }
+ }
+ }
+ /* sigh, "rnr" is already a keyword for PF */
+ | LLC PF_RNR { $$ = gen_llc_s_subtype(LLC_RNR); }
+ ;
+
dir: NUM
| ID { if (pcap_strcasecmp($1, "nods") == 0)
$$ = IEEE80211_FC1_DIR_NODS;
| paren pnum ')' { $$ = $2; }
;
atmtype: LANE { $$ = A_LANE; }
- | LLC { $$ = A_LLC; }
| METAC { $$ = A_METAC; }
| BCC { $$ = A_BCC; }
| OAMF4EC { $$ = A_OAMF4EC; }
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
+/*
+ * Definitions for information in the LLC header.
+ */
+
+#define LLC_U_FMT 3
+#define LLC_GSAP 1
+#define LLC_IG 1 /* Individual / Group */
+#define LLC_S_FMT 1
+
+#define LLC_U_POLL 0x10
+#define LLC_IS_POLL 0x0100
+#define LLC_XID_FI 0x81
+
+#define LLC_U_CMD_MASK 0xef
+#define LLC_UI 0x03
+#define LLC_UA 0x63
+#define LLC_DISC 0x43
+#define LLC_DM 0x0f
+#define LLC_SABME 0x6f
+#define LLC_TEST 0xe3
+#define LLC_XID 0xaf
+#define LLC_FRMR 0x87
+
+#define LLC_S_CMD_MASK 0x0f
+#define LLC_RR 0x0001
+#define LLC_RNR 0x0005
+#define LLC_REJ 0x0009
+
+#define LLC_IS_NR(is) (((is) >> 9) & 0x7f)
+#define LLC_I_NS(is) (((is) >> 1) & 0x7f)
+
/*
* 802.2 LLC SAP values.
*/
#ifndef LLCSAP_GLOBAL
#define LLCSAP_GLOBAL 0xff
#endif
-#ifndef LLCSAP_8021B
+#ifndef LLCSAP_8021B_I
#define LLCSAP_8021B_I 0x02
#endif
-#ifndef LLCSAP_8021B
+#ifndef LLCSAP_8021B_G
#define LLCSAP_8021B_G 0x03
#endif
#ifndef LLCSAP_IP
.IP "\fBdecnet host \fIhost\fR"
True if either the DECNET source or destination address is
.IR host .
+.IP \fBllc\fP
+True if the packet has an 802.2 LLC header. This includes:
+.IP
+Ethernet packets with a length field rather than a type field that
+aren't raw NetWare-over-802.3 packets;
+.IP
+IEEE 802.11 data packets;
+.IP
+Token Ring packets (no check is done for LLC frames);
+.IP
+FDDI packets (no check is done for LLC frames);
+.IP
+LLC-encapsulated ATM packets, for SunATM on Solaris.
+.IP
+
+.IP "\fBllc\fP \Fitype\fR"
+True if the packet has an 802.2 LLC header and has the specified
+.IR type .
+.I type
+can be one of:
+.RS
+.TP
+\fBi\fR
+Information (I) PDUs
+.TP
+\fBs\fR
+Supervisory (S) PDUs
+.TP
+\fBu\fR
+Unnumbered (U) PDUs
+.TP
+\fBrr\fR
+Receiver Ready (RR) S PDUs
+.TP
+\fBrnr\fR
+Receiver Not Ready (RNR) S PDUs
+.TP
+\fBrej\fR
+Reject (REJ) S PDUs
+.TP
+\fBui\fR
+Unnumbered Information (UI) U PDUs
+.TP
+\fBua\fR
+Unnumbered Acknowledgment (UA) U PDUs
+.TP
+\fBdisc\fR
+Disconnect (DISC) U PDUs
+.TP
+\fBsabme\fR
+Set Asynchronous Balanced Mode Extended (SABME) U PDUs
+.TP
+\fBtest\fR
+Test (TEST) U PDUs
+.TP
+\fBxid\fR
+Exchange Identification (XID) U PDUs
+.TP
+\fBfrmr\fR
+Frame Reject (FRMR) U PDUs
+.RE
.IP "\fBifname \fIinterface\fR"
True if the packet was logged as coming from the specified interface (applies
only to packets logged by OpenBSD's or FreeBSD's
packet or a LANE LE Control packet. If \fBlane\fR isn't specified, the
tests are done under the assumption that the packet is an
LLC-encapsulated packet.
-.IP \fBllc\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-an LLC-encapsulated packet.
.IP \fBoamf4s\fP
True if the packet is an ATM packet, for SunATM on Solaris, and is
a segment OAM F4 flow cell (VPI=0 & VCI=3).