📄 gencode.c
字号:
break;
case DLT_NULL:
case DLT_LOOP:
case DLT_ENC:
/*
* For DLT_NULL, the link-layer header is a 32-bit
* word containing an AF_ value in *host* byte order,
* and for DLT_ENC, the link-layer header begins
* with a 32-bit work containing an AF_ value in
* host byte order.
*
* In addition, if we're reading a saved capture file,
* the host byte order in the capture may not be the
* same as the host byte order on this machine.
*
* For DLT_LOOP, the link-layer header is a 32-bit
* word containing an AF_ value in *network* byte order.
*
* XXX - AF_ values may, unfortunately, be platform-
* dependent; for example, FreeBSD's AF_INET6 is 24
* whilst NetBSD's and OpenBSD's is 26.
*
* This means that, when reading a capture file, just
* checking for our AF_INET6 value won't work if the
* capture file came from another OS.
*/
switch (proto) {
case ETHERTYPE_IP:
proto = AF_INET;
break;
#ifdef INET6
case ETHERTYPE_IPV6:
proto = AF_INET6;
break;
#endif
default:
/*
* Not a type on which we support filtering.
* XXX - support those that have AF_ values
* #defined on this platform, at least?
*/
return gen_false();
}
if (linktype == DLT_NULL || linktype == DLT_ENC) {
/*
* The AF_ value is in host byte order, but
* the BPF interpreter will convert it to
* network byte order.
*
* If this is a save file, and it's from a
* machine with the opposite byte order to
* ours, we byte-swap the AF_ value.
*
* Then we run it through "htonl()", and
* generate code to compare against the result.
*/
if (bpf_pcap->sf.rfile != NULL &&
bpf_pcap->sf.swapped)
proto = SWAPLONG(proto);
proto = htonl(proto);
}
return (gen_cmp(0, BPF_W, (bpf_int32)proto));
case DLT_PFLOG:
/*
* af field is host byte order in contrast to the rest of
* the packet.
*/
if (proto == ETHERTYPE_IP)
return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B,
(bpf_int32)AF_INET));
#ifdef INET6
else if (proto == ETHERTYPE_IPV6)
return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B,
(bpf_int32)AF_INET6));
#endif /* INET6 */
else
return gen_false();
break;
case DLT_ARCNET:
case DLT_ARCNET_LINUX:
/*
* XXX should we check for first fragment if the protocol
* uses PHDS?
*/
switch (proto) {
default:
return gen_false();
#ifdef INET6
case ETHERTYPE_IPV6:
return (gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_INET6));
#endif /* INET6 */
case ETHERTYPE_IP:
b0 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_IP);
b1 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_IP_OLD);
gen_or(b0, b1);
return (b1);
case ETHERTYPE_ARP:
b0 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_ARP);
b1 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_ARP_OLD);
gen_or(b0, b1);
return (b1);
case ETHERTYPE_REVARP:
return (gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_REVARP));
case ETHERTYPE_ATALK:
return (gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_ATALK));
}
break;
case DLT_LTALK:
switch (proto) {
case ETHERTYPE_ATALK:
return gen_true();
default:
return gen_false();
}
break;
case DLT_FRELAY:
/*
* XXX - assumes a 2-byte Frame Relay header with
* DLCI and flags. What if the address is longer?
*/
switch (proto) {
case ETHERTYPE_IP:
/*
* Check for the special NLPID for IP.
*/
return gen_cmp(2, BPF_H, (0x03<<8) | 0xcc);
#ifdef INET6
case ETHERTYPE_IPV6:
/*
* Check for the special NLPID for IPv6.
*/
return gen_cmp(2, BPF_H, (0x03<<8) | 0x8e);
#endif
case LLCSAP_ISONS:
/*
* Check for several OSI protocols.
*
* Frame Relay packets typically have an OSI
* NLPID at the beginning; we check for each
* of them.
*
* What we check for is the NLPID and a frame
* control field of UI, i.e. 0x03 followed
* by the NLPID.
*/
b0 = gen_cmp(2, BPF_H, (0x03<<8) | ISO8473_CLNP);
b1 = gen_cmp(2, BPF_H, (0x03<<8) | ISO9542_ESIS);
b2 = gen_cmp(2, BPF_H, (0x03<<8) | ISO10589_ISIS);
gen_or(b1, b2);
gen_or(b0, b2);
return b2;
default:
return gen_false();
}
break;
case DLT_LINUX_IRDA:
bpf_error("IrDA link-layer type filtering not implemented");
}
/*
* All the types that have no encapsulation should either be
* handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if
* all packets are IP packets, or should be handled in some
* special case, if none of them are (if some are and some
* aren't, the lack of encapsulation is a problem, as we'd
* have to find some other way of determining the packet type).
*
* Therefore, if "off_linktype" is -1, there's an error.
*/
if (off_linktype == (u_int)-1)
abort();
/*
* Any type not handled above should always have an Ethernet
* type at an offset of "off_linktype". (PPP is partially
* handled above - the protocol type is mapped from the
* Ethernet and LLC types we use internally to the corresponding
* PPP type - but the PPP type is always specified by a value
* at "off_linktype", so we don't have to do the code generation
* above.)
*/
return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
}
/*
* Check for an LLC SNAP packet with a given organization code and
* protocol type; we check the entire contents of the 802.2 LLC and
* snap headers, checking for DSAP and SSAP of SNAP and a control
* field of 0x03 in the LLC header, and for the specified organization
* code and protocol type in the SNAP header.
*/
static struct block *
gen_snap(orgcode, ptype, offset)
bpf_u_int32 orgcode;
bpf_u_int32 ptype;
u_int offset;
{
u_char snapblock[8];
snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */
snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */
snapblock[2] = 0x03; /* control = UI */
snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */
snapblock[4] = (orgcode >> 8); /* middle 8 bits of organization code */
snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */
snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */
snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */
return gen_bcmp(offset, 8, snapblock);
}
/*
* Check for a given protocol value assuming an 802.2 LLC header.
*/
static struct block *
gen_llc(proto)
int proto;
{
/*
* XXX - handle token-ring variable-length header.
*/
switch (proto) {
case LLCSAP_IP:
return gen_cmp(off_linktype, BPF_H, (long)
((LLCSAP_IP << 8) | LLCSAP_IP));
case LLCSAP_ISONS:
return gen_cmp(off_linktype, BPF_H, (long)
((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
case LLCSAP_NETBEUI:
return gen_cmp(off_linktype, BPF_H, (long)
((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
case LLCSAP_IPX:
/*
* XXX - are there ever SNAP frames for IPX on
* non-Ethernet 802.x networks?
*/
return gen_cmp(off_linktype, BPF_B, (bpf_int32)LLCSAP_IPX);
case ETHERTYPE_ATALK:
/*
* 802.2-encapsulated ETHERTYPE_ATALK packets are
* SNAP packets with an organization code of
* 0x080007 (Apple, for Appletalk) and a protocol
* type of ETHERTYPE_ATALK (Appletalk).
*
* XXX - check for an organization code of
* encapsulated Ethernet as well?
*/
return gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype);
default:
/*
* XXX - we don't have to check for IPX 802.3
* here, but should we check for the IPX Ethertype?
*/
if (proto <= ETHERMTU) {
/*
* This is an LLC SAP value, so check
* the DSAP.
*/
return gen_cmp(off_linktype, BPF_B, (bpf_int32)proto);
} else {
/*
* This is an Ethernet type; we assume that it's
* unlikely that it'll appear in the right place
* at random, and therefore check only the
* location that would hold the Ethernet type
* in a SNAP frame with an organization code of
* 0x000000 (encapsulated Ethernet).
*
* XXX - if we were to check for the SNAP DSAP and
* LSAP, as per XXX, and were also to check for an
* organization code of 0x000000 (encapsulated
* Ethernet), we'd do
*
* return gen_snap(0x000000, proto,
* off_linktype);
*
* here; for now, we don't, as per the above.
* I don't know whether it's worth the extra CPU
* time to do the right check or not.
*/
return gen_cmp(off_linktype+6, BPF_H, (bpf_int32)proto);
}
}
}
static struct block *
gen_hostop(addr, mask, dir, proto, src_off, dst_off)
bpf_u_int32 addr;
bpf_u_int32 mask;
int dir, proto;
u_int src_off, dst_off;
{
struct block *b0, *b1;
u_int offset;
switch (dir) {
case Q_SRC:
offset = src_off;
break;
case Q_DST:
offset = dst_off;
break;
case Q_AND:
b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
gen_and(b0, b1);
return b1;
case Q_OR:
case Q_DEFAULT:
b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
gen_or(b0, b1);
return b1;
default:
abort();
}
b0 = gen_linktype(proto);
b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask);
gen_and(b0, b1);
return b1;
}
#ifdef INET6
static struct block *
gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
struct in6_addr *addr;
struct in6_addr *mask;
int dir, proto;
u_int src_off, dst_off;
{
struct block *b0, *b1;
u_int offset;
u_int32_t *a, *m;
switch (dir) {
case Q_SRC:
offset = src_off;
break;
case Q_DST:
offset = dst_off;
break;
case Q_AND:
b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
gen_and(b0, b1);
return b1;
case Q_OR:
case Q_DEFAULT:
b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
gen_or(b0, b1);
return b1;
default:
abort();
}
/* this order is important */
a = (u_int32_t *)addr;
m = (u_int32_t *)mask;
b1 = gen_mcmp(offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
b0 = gen_mcmp(offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
gen_and(b0, b1);
b0 = gen_mcmp(offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
gen_and(b0, b1);
b0 = gen_mcmp(offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
gen_and(b0, b1);
b0 = gen_linktype(proto);
gen_and(b0, b1);
return b1;
}
#endif /*INET6*/
static struct block *
gen_ehostop(eaddr, dir)
register const u_char *eaddr;
register int dir;
{
register struct block *b0, *b1;
switch (dir) {
case Q_SRC:
return gen_bcmp(off_mac + 6, 6, eaddr);
case Q_DST:
return gen_bcmp(off_mac + 0, 6, eaddr);
case Q_AND:
b0 = gen_ehostop(eaddr, Q_SRC);
b1 = gen_ehostop(eaddr, Q_DST);
gen_and(b0, b1);
return b1;
case Q_DEFAULT:
case Q_OR:
b0 = gen_ehostop(eaddr, Q_SRC);
b1 = gen_ehostop(eaddr, Q_DST);
gen_or(b0, b1);
return b1;
}
abort();
/* NOTREACHED */
}
/*
* Like gen_ehostop, but for DLT_FDDI
*/
static struct block *
gen_fhostop(eaddr, dir)
register const u_char *eaddr;
register int dir;
{
struct block *b0, *b1;
switch (dir) {
case Q_SRC:
#ifdef PCAP_FDDIPAD
return gen_bcmp(6 + 1 + pcap_fddipad, 6, eaddr);
#else
return gen_bcmp(6 + 1, 6, eaddr);
#endif
case Q_DST:
#ifdef PCAP_FDDIPAD
return gen_bcmp(0 + 1 + pcap_fddipad, 6, eaddr);
#else
return gen_bcmp(0 + 1, 6, eaddr);
#endif
case Q_AND:
b0 = gen_fhostop(eaddr, Q_SRC);
b1 = gen_fhostop(eaddr, Q_DST);
gen_and(b0, b1);
return b1;
case Q_DEFAULT:
case Q_OR:
b0 = gen_fhostop(eaddr, Q_SRC);
b1 = gen_fhostop(eaddr, Q_DST);
gen_or(b0, b1);
return b1;
}
abort();
/* NOTREACHED */
}
/*
* Like gen_ehostop, but for DLT_IEEE802 (Token Ring)
*/
static struct block *
gen_thostop(eaddr, dir)
register const u_char *eaddr;
register int dir;
{
register struct block *b0, *b1;
switch (dir) {
case Q_SRC:
return gen_bcmp(8, 6, eaddr);
case Q_DST:
return gen_bcmp(2, 6, eaddr);
case Q_AND:
b0 = gen_thostop(eaddr, Q_SRC);
b1 = gen_thostop(eaddr, Q_DST);
gen_and(b0, b1);
return b1;
case Q_DEFAULT:
case Q_OR:
b0 = gen_thostop(eaddr, Q_SRC);
b1 = gen_thostop(eaddr, Q_DST);
gen_or(b0, b1);
return b1;
}
abort();
/* NOTREACHED */
}
/*
* Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN)
*/
static struct block *
gen_wlanhostop(eaddr, dir)
register const u_char *eaddr;
register int dir;
{
register struct block *b0, *b1, *b2;
register struct slist *s;
switch (dir) {
case Q_SRC:
/*
* Oh, yuk.
*
* For control frames, there is no SA.
*
* For management frames, SA is at an
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -