diff --git a/CHANGES b/CHANGES index a90530d7d5..8e0923bcdd 100644 --- a/CHANGES +++ b/CHANGES @@ -54,6 +54,7 @@ DayOfTheWeek, Month DD, YYYY / The Tcpdump Group In "gateway" negate the host(s), but not the protocol. Reject "gateway" within MPLS, VXLAN or Geneve. In "net mask " catch ENOMEM for the "m" too. + Implement new "ip flag" and "tcp flag" primitives. Capture file reading: Fix misaligned accesses in processing Linux USB captures (issue #1634, reported by FuzzAnything Organization diff --git a/gencode.c b/gencode.c index d3f17e513b..e6e6650ce1 100644 --- a/gencode.c +++ b/gencode.c @@ -327,6 +327,17 @@ struct addrinfo { #define MPLS_LABEL_MAX 0xfffffU #define MPLS_LABEL_SHIFT 12 +// Offsets of various protocol header flags. +#define IPV4_FLAGS_OFFSET 6 +#define TCP_FLAGS_OFFSET 12 + +struct proto_flag { + const char *tok; + uint8_t offset; + uint8_t bitmask; + struct block *(*testfunc)(compiler_state_t *, const uint32_t, struct slist *); +}; + #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif @@ -785,6 +796,7 @@ static struct block *gen_protochain(compiler_state_t *, bpf_u_int32, int); static struct block *gen_proto(compiler_state_t *, bpf_u_int32, int); static struct slist *xfer_to_x(compiler_state_t *, const struct arth *); static struct slist *xfer_to_a(compiler_state_t *, const struct arth *); +static struct block *gen_flag(compiler_state_t *, const char *, const uint8_t); static struct block *gen_mac_multicast(compiler_state_t *, int); static struct block *gen_len(compiler_state_t *, int, int); static struct block *gen_encap_ll_check(compiler_state_t *cstate); @@ -1040,6 +1052,7 @@ tqkw(const unsigned id) [Q_PROTO] = "proto", [Q_PROTOCHAIN] = "protochain", [Q_PORTRANGE] = "portrange", + [Q_FLAG] = "flag", }; return qual2kw("type", id, tokens, sizeof(tokens) / sizeof(tokens[0])); } @@ -6726,6 +6739,103 @@ gen_proto(compiler_state_t *cstate, bpf_u_int32 v, int proto) /*NOTREACHED*/ } +static struct block * +gen_ip_flag(compiler_state_t *cstate, const struct proto_flag *f) +{ + struct block *ipv4 = gen_proto_abbrev_internal(cstate, Q_IP); + struct block *flagstate = f->testfunc(cstate, f->bitmask, + gen_load_a(cstate, OR_LINKPL, IPV4_FLAGS_OFFSET + f->offset, BPF_B)); + return gen_and(ipv4, flagstate); +} + +static struct block * +gen_tcp_flag(compiler_state_t *cstate, const struct proto_flag *f) +{ + struct slist *s; + + /* + * gen_proto() alone would not be sufficient to match correctly: in + * this case the packet must be the first fragment for the offset to + * be in the TCP header. + */ + struct block *b4 = gen_proto_abbrev_internal(cstate, Q_IP); + b4 = gen_and(b4, gen_ip_proto(cstate, IPPROTO_TCP)); + b4 = gen_and(b4, gen_ipfrag(cstate)); + s = gen_load_a(cstate, OR_TRAN_IPV4, TCP_FLAGS_OFFSET + f->offset, BPF_B); + b4 = gen_and(b4, f->testfunc(cstate, f->bitmask, s)); + + /* + * gen_proto() would not match correctly because it also matches + * IPPROTO_FRAGMENT, in which case the offset below would not be in + * the TCP header. + */ + struct block *b6 = gen_proto_abbrev_internal(cstate, Q_IPV6); + b6 = gen_and(b6, gen_ip6_proto(cstate, IPPROTO_TCP)); + s = gen_load_a(cstate, OR_TRAN_IPV6, TCP_FLAGS_OFFSET + f->offset, BPF_B); + b6 = gen_and(b6, f->testfunc(cstate, f->bitmask, s)); + + return gen_or(b4, b6); +} + +static struct block * +gen_flag(compiler_state_t *cstate, const char *name, const uint8_t proto) +{ + // A 2-bit mask in one octet starting at IPV4_FLAGS_OFFSET. + static const struct proto_flag ip_flags[] = { + {"mf-set", 0, 1U << 5, gen_set}, + {"mf-cleared", 0, 1U << 5, gen_unset}, + {"df-set", 0, 1U << 6, gen_set}, + {"df-cleared", 0, 1U << 6, gen_unset}, + {NULL, 0, 0, NULL} + }; + + // A 9-bit mask in 2 octets starting at TCP_FLAGS_OFFSET. + static const struct proto_flag tcp_flags[] = { + {"fin-set", 1, 1U << 0, gen_set}, + {"fin-cleared", 1, 1U << 0, gen_unset}, + {"syn-set", 1, 1U << 1, gen_set}, + {"syn-cleared", 1, 1U << 1, gen_unset}, + {"rst-set", 1, 1U << 2, gen_set}, + {"rst-cleared", 1, 1U << 2, gen_unset}, + {"psh-set", 1, 1U << 3, gen_set}, + {"psh-cleared", 1, 1U << 3, gen_unset}, + {"ack-set", 1, 1U << 4, gen_set}, + {"ack-cleared", 1, 1U << 4, gen_unset}, + {"urg-set", 1, 1U << 5, gen_set}, + {"urg-cleared", 1, 1U << 5, gen_unset}, + {"ece-set", 1, 1U << 6, gen_set}, + {"ece-cleared", 1, 1U << 6, gen_unset}, + {"cwr-set", 1, 1U << 7, gen_set}, + {"cwr-cleared", 1, 1U << 7, gen_unset}, + {"ae-set", 0, 1U << 0, gen_set}, + {"ae-cleared", 0, 1U << 0, gen_unset}, + {NULL, 0, 0, NULL} + }; + + const struct proto_flag *flag; + struct block *(*genfunc)(compiler_state_t *, const struct proto_flag *); + switch (proto) { + case Q_IP: + flag = ip_flags; + genfunc = gen_ip_flag; + break; + case Q_TCP: + flag = tcp_flags; + genfunc = gen_tcp_flag; + break; + case Q_DEFAULT: + bpf_error(cstate, "'%s' must be proto-qualified", tqkw(Q_FLAG)); + default: + bpf_error(cstate, ERRSTR_INVALID_QUAL, pqkw(proto), tqkw(Q_FLAG)); + } + while (flag->tok) { + if (! strcmp(name, flag->tok)) + return genfunc(cstate, flag); + flag++; + } + bpf_error(cstate, "invalid '%s %s' ID '%s'", pqkw(proto), tqkw(Q_FLAG), name); +} + /* * Convert a non-numeric name to a port number. */ @@ -7158,6 +7268,10 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q) return gen_protochain(cstate, lookup_proto(cstate, name, q), proto); #endif /* !defined(NO_PROTOCHAIN) */ + case Q_FLAG: + // q.dir == Q_DEFAULT (non-directional in the grammar) + return gen_flag(cstate, name, q.proto); + case Q_UNDEF: syntax(cstate); /*NOTREACHED*/ diff --git a/gencode.h b/gencode.h index 6ef3023118..946a728324 100644 --- a/gencode.h +++ b/gencode.h @@ -76,6 +76,7 @@ #define Q_PROTO 5 #define Q_PROTOCHAIN 6 #define Q_PORTRANGE 7 +#define Q_FLAG 8 /* Protocol qualifiers. */ diff --git a/grammar.y.in b/grammar.y.in index 31f670c705..a1924056d5 100644 --- a/grammar.y.in +++ b/grammar.y.in @@ -375,6 +375,7 @@ DIAG_OFF_BISON_BYACC %token DST SRC HOST GATEWAY +%token FLAG %token NET NETMASK PORT PORTRANGE LESS GREATER PROTO PROTOCHAIN CBYTE %token ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP CARP %token ATALK AARP DECNET LAT SCA MOPRC MOPDL @@ -618,6 +619,7 @@ aqual: HOST { $$ = Q_HOST; } ; /* non-directional address type qualifiers */ ndaqual: GATEWAY { $$ = Q_GATEWAY; } + | FLAG { $$ = Q_FLAG; } ; pname: LINK { $$ = Q_LINK; } | IP { $$ = Q_IP; } diff --git a/pcap-filter.manmisc.in b/pcap-filter.manmisc.in index ff4bc1e500..cb4829eb49 100644 --- a/pcap-filter.manmisc.in +++ b/pcap-filter.manmisc.in @@ -18,7 +18,7 @@ .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" -.TH PCAP-FILTER @MAN_MISC_INFO@ "19 February 2026" +.TH PCAP-FILTER @MAN_MISC_INFO@ "20 February 2026" .SH NAME pcap-filter \- packet filter syntax .br @@ -519,6 +519,75 @@ can be specified in either order. If the two values are equal, this primitive has the same effect as the .B port primitive above. +.IP "\fBip flag \fIflagstate\fR" +True if the packet is an IPv4 packet and the IPv4 header flag (MF or DF) is +set (if +.I flagstate +is one of +.RB { mf\-set , +.BR df\-set }) +or cleared (if +.I flagstate +is one of +.RB { mf\-cleared , +.BR df\-cleared }). +The correct way to test for a cleared flag is by using the +.B -cleared +suffix; for example, +.in +.5i +.nf +.B ip flag df-cleared +.fi +.in -.5i +correctly does not match packets that are not IPv4 packets, but +.in +.5i +.nf +.B ip flag not df-set +.fi +.in -.5i +does (correctly from the grammar perspective, but usually incorrectly from the +use case perspective) match non-IPv4 packets because it means the same as +.in +.5i +.nf +.B not (ip and ip flag df-set) +.fi +.in -.5i +.IP "\fBtcp flag \fIflagstate\fR" +True if the packet is an IPv4/IPv6 TCP packet and the TCP header flag (FIN, +SYN, RST, PSH, ACK, URG, ECE, CWR or AE) is set (if +.I flagstate +is one of +.RB { fin\-set , +.BR syn\-set , +.BR rst\-set , +.BR psh\-set , +.BR ack\-set , +.BR urg\-set , +.BR ece\-set , +.BR cwr\-set , +.BR ae\-set }) +or cleared (if +.I flagstate +is one of +.RB { fin\-cleared , +.BR syn\-cleared , +.BR rst\-cleared , +.BR psh\-cleared , +.BR ack\-cleared , +.BR urg\-cleared , +.BR ece\-cleared , +.BR cwr\-cleared , +.BR ae\-cleared }). +For IPv4 this also verifies that the datagram is the first fragment or is not +fragmented. For the same reasons as the above, the correct way to test for a +cleared flag is by using the +.B -cleared +suffix, for example: +.in +.5i +.nf +.B tcp flag syn-cleared and ack-cleared +.fi +.in -.5i .IP "\fBless \fIlength\fR" True if the packet has a length less than or equal to \fIlength\fP. This is equivalent to: @@ -1688,7 +1757,11 @@ as numeric values. The following protocol header field offsets are available: \fBicmptype\fP (ICMP type field), \fBicmp6type\fP (ICMPv6 type field), \fBicmpcode\fP (ICMP code field), \fBicmp6code\fP (ICMPv6 code field) and -\fBtcpflags\fP (TCP flags field). +\fBtcpflags\fP (TCP flags field). For historic reasons the latter silently +ignores TCP flags that are allocated beyond the traditional 14th byte of the +TCP header, hence the +.B tcp flag +primitive would be a more reliable means to match TCP flags. .LP The following ICMP type field values are available: .BR \%icmp-echoreply , @@ -1742,6 +1815,10 @@ The following TCP flags field values are available: \fBtcp-fin\fP, \fBtcp-syn\fP, \fBtcp-rst\fP, \fBtcp-push\fP, \fBtcp-ack\fP, \fBtcp-urg\fP, \fBtcp-ece\fP, \fBtcp-cwr\fP. +Note that these values typically require a correct application of bitwise +arithmetic expressions to the packet data, unlike the +.B tcp flag +primitive; the latter also supports the AE flag. .SH COMPOUND EXPRESSIONS Primitives and relations may be combined using: .LP @@ -1904,6 +1981,14 @@ To select the start and end packets (the SYN and FIN packets) of each TCP conversation that involves a non-local host. .RS .nf +\fBtcp flag syn-set or fin-set and not src and dst net\fP localnet +.fi +.RE +.LP +The same, using arithmetic expressions: +.RS +.nf +.B \fBtcp[tcpflags] & (tcp-syn|tcp-fin) !=\fP 0 \fBand not src and dst net\fP localnet .fi .RE @@ -1914,6 +1999,14 @@ is "RST and ACK both set", match) .RS .nf .B +tcp flag rst-set and ack-set +.fi +.RE +.LP +The same, using arithmetic expressions: +.RS +.nf +.B tcp[tcpflags] & (tcp-rst|tcp-ack) == (tcp-rst|tcp-ack) .fi .RE @@ -1998,6 +2091,12 @@ The and .B slow protocols became available for "ether proto" in libpcap 1.11.0. +.PP +The +.B ip flag +and +.B tcp flag +primitives became available in libpcap 1.11.0. .SH SEE ALSO .BR pcap (3PCAP) .SH BUGS diff --git a/scanner.l b/scanner.l index 65ae69504c..7146511ce3 100644 --- a/scanner.l +++ b/scanner.l @@ -306,6 +306,7 @@ port return PORT; portrange return PORTRANGE; proto return PROTO; protochain return PROTOCHAIN; +flag return FLAG; gateway return GATEWAY; diff --git a/testprogs/TESTrun b/testprogs/TESTrun index d4af0c8630..7077936761 100755 --- a/testprogs/TESTrun +++ b/testprogs/TESTrun @@ -22985,6 +22985,816 @@ my @filter_accept_blocks = ( ', }, # offsets + { + name => 'ip_flag_mf_set', + DLT => 'EN10MB', + aliases => ['ip flag mf-set'], + optunopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 5 + (002) ldb [20] + (003) jset #0x20 jt 4 jf 5 + (004) ret #262144 + (005) ret #0 + ', + }, # ip_flag_mf_set + { + name => 'ip_flag_mf_cleared', + DLT => 'EN10MB', + aliases => ['ip flag mf-cleared'], + optunopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 5 + (002) ldb [20] + (003) jset #0x20 jt 5 jf 4 + (004) ret #262144 + (005) ret #0 + ', + }, # ip_flag_mf_cleared + { + name => 'ip_flag_df_set', + DLT => 'EN10MB', + aliases => ['ip flag df-set'], + optunopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 5 + (002) ldb [20] + (003) jset #0x40 jt 4 jf 5 + (004) ret #262144 + (005) ret #0 + ', + }, # ip_flag_df_set + { + name => 'ip_flag_df_cleared', + DLT => 'EN10MB', + aliases => ['ip flag df-cleared'], + optunopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 5 + (002) ldb [20] + (003) jset #0x40 jt 5 jf 4 + (004) ret #262144 + (005) ret #0 + ', + }, # ip_flag_df_cleared + + { + name => 'tcp_flag_fin_set', + DLT => 'EN10MB', + aliases => ['tcp flag fin-set'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x1 jt 14 jf 15 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x1 jt 14 jf 15 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x1 jt 15 jf 9 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x1 jt 15 jf 16 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_fin_set + { + name => 'tcp_flag_fin_cleared', + DLT => 'EN10MB', + aliases => ['tcp flag fin-cleared'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x1 jt 15 jf 14 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x1 jt 15 jf 14 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x1 jt 9 jf 15 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x1 jt 16 jf 15 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_fin_cleared + { + name => 'tcp_flag_syn_set', + DLT => 'EN10MB', + aliases => ['tcp flag syn-set'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x2 jt 14 jf 15 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x2 jt 14 jf 15 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x2 jt 15 jf 9 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x2 jt 15 jf 16 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_syn_set + { + name => 'tcp_flag_syn_cleared', + DLT => 'EN10MB', + aliases => ['tcp flag syn-cleared'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x2 jt 15 jf 14 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x2 jt 15 jf 14 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x2 jt 9 jf 15 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x2 jt 16 jf 15 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_syn_cleared + { + name => 'tcp_flag_rst_set', + DLT => 'EN10MB', + aliases => ['tcp flag rst-set'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x4 jt 14 jf 15 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x4 jt 14 jf 15 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x4 jt 15 jf 9 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x4 jt 15 jf 16 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_rst_set + { + name => 'tcp_flag_rst_cleared', + DLT => 'EN10MB', + aliases => ['tcp flag rst-cleared'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x4 jt 15 jf 14 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x4 jt 15 jf 14 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x4 jt 9 jf 15 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x4 jt 16 jf 15 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_rst_cleared + { + name => 'tcp_flag_psh_set', + DLT => 'EN10MB', + aliases => ['tcp flag psh-set'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x8 jt 14 jf 15 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x8 jt 14 jf 15 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x8 jt 15 jf 9 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x8 jt 15 jf 16 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_psh_set + { + name => 'tcp_flag_psh_cleared', + DLT => 'EN10MB', + aliases => ['tcp flag psh-cleared'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x8 jt 15 jf 14 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x8 jt 15 jf 14 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x8 jt 9 jf 15 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x8 jt 16 jf 15 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_psh_cleared + { + name => 'tcp_flag_ack_set', + DLT => 'EN10MB', + aliases => ['tcp flag ack-set'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x10 jt 14 jf 15 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x10 jt 14 jf 15 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x10 jt 15 jf 9 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x10 jt 15 jf 16 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_ack_set + { + name => 'tcp_flag_ack_cleared', + DLT => 'EN10MB', + aliases => ['tcp flag ack-cleared'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x10 jt 15 jf 14 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x10 jt 15 jf 14 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x10 jt 9 jf 15 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x10 jt 16 jf 15 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_ack_cleared + { + name => 'tcp_flag_urg_set', + DLT => 'EN10MB', + aliases => ['tcp flag urg-set'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x20 jt 14 jf 15 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x20 jt 14 jf 15 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x20 jt 15 jf 9 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x20 jt 15 jf 16 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_urg_set + { + name => 'tcp_flag_urg_cleared', + DLT => 'EN10MB', + aliases => ['tcp flag urg-cleared'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x20 jt 15 jf 14 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x20 jt 15 jf 14 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x20 jt 9 jf 15 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x20 jt 16 jf 15 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_urg_cleared + { + name => 'tcp_flag_ece_set', + DLT => 'EN10MB', + aliases => ['tcp flag ece-set'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x40 jt 14 jf 15 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x40 jt 14 jf 15 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x40 jt 15 jf 9 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x40 jt 15 jf 16 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_ece_set + { + name => 'tcp_flag_ece_cleared', + DLT => 'EN10MB', + aliases => ['tcp flag ece-cleared'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x40 jt 15 jf 14 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x40 jt 15 jf 14 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x40 jt 9 jf 15 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x40 jt 16 jf 15 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_ece_cleared + { + name => 'tcp_flag_cwr_set', + DLT => 'EN10MB', + aliases => ['tcp flag cwr-set'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x80 jt 14 jf 15 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x80 jt 14 jf 15 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x80 jt 15 jf 9 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x80 jt 15 jf 16 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_cwr_set + { + name => 'tcp_flag_cwr_cleared', + DLT => 'EN10MB', + aliases => ['tcp flag cwr-cleared'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x80 jt 15 jf 14 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [67] + (013) jset #0x80 jt 15 jf 14 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 27] + (008) jset #0x80 jt 9 jf 15 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [67] + (014) jset #0x80 jt 16 jf 15 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_cwr_cleared + { + name => 'tcp_flag_ae_set', + DLT => 'EN10MB', + aliases => ['tcp flag ae-set'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 26] + (008) jset #0x1 jt 14 jf 15 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [66] + (013) jset #0x1 jt 14 jf 15 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 26] + (008) jset #0x1 jt 15 jf 9 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [66] + (014) jset #0x1 jt 15 jf 16 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_ae_set + { + name => 'tcp_flag_ae_cleared', + DLT => 'EN10MB', + aliases => ['tcp flag ae-cleared'], + opt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 15 + (004) ldh [20] + (005) jset #0x1fff jt 15 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 26] + (008) jset #0x1 jt 15 jf 14 + (009) jeq #0x86dd jt 10 jf 15 + (010) ldb [20] + (011) jeq #0x6 jt 12 jf 15 + (012) ldb [66] + (013) jset #0x1 jt 15 jf 14 + (014) ret #262144 + (015) ret #0 + ', + unopt => ' + (000) ldh [12] + (001) jeq #0x800 jt 2 jf 9 + (002) ldb [23] + (003) jeq #0x6 jt 4 jf 9 + (004) ldh [20] + (005) jset #0x1fff jt 9 jf 6 + (006) ldxb 4*([14]&0xf) + (007) ldb [x + 26] + (008) jset #0x1 jt 9 jf 15 + (009) ldh [12] + (010) jeq #0x86dd jt 11 jf 16 + (011) ldb [20] + (012) jeq #0x6 jt 13 jf 16 + (013) ldb [66] + (014) jset #0x1 jt 16 jf 15 + (015) ret #262144 + (016) ret #0 + ', + }, # tcp_flag_ae_cleared + # In the tests below "smtp" depends on getaddrinfo(). { name => 'tcp_port', @@ -25039,6 +25849,48 @@ my @filter_apply_blocks = ( expr => 'udp[2:2] == 53', results => [0, 0, 0, 0, 0, 0, 0, 0, 65535, 0, 65535, 0, 0, 0, 0], }, + { + name => 'rfc1201_ip_flag_df_set', + savefile => 'arcnet-rfc1201-arp-icmp-http.pcap', + expr => 'ip flag df-set', + results => [0, 0, 65535, 0, 65535, 0, 0, 0, 65535, 65535, 65535, 65535, 65535, 65535, 65535], + }, + { + name => 'rfc1201_ip_flag_mf_cleared', + savefile => 'arcnet-rfc1201-arp-icmp-http.pcap', + expr => 'ip flag mf-cleared', + results => [0, 0, 65535, 65535, 65535, 65535, 0, 0, 65535, 65535, 65535, 65535, 65535, 65535, 65535], + }, + { + name => 'rfc1201_tcp_flag_syn_set', + savefile => 'arcnet-rfc1201-arp-icmp-http.pcap', + expr => 'tcp flag syn-set', + results => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65535, 65535, 0], + }, + { + name => 'rfc1201_tcp_flag_ack_set', + savefile => 'arcnet-rfc1201-arp-icmp-http.pcap', + expr => 'tcp flag ack-set', + results => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65535, 65535], + }, + { + name => 'rfc1201_tcp_flag_ack_cleared', + savefile => 'arcnet-rfc1201-arp-icmp-http.pcap', + expr => 'tcp flag ack-cleared', + results => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65535, 0, 0], + }, + { + name => 'rfc1201_tcp_flag_urg_set', + savefile => 'arcnet-rfc1201-arp-icmp-http.pcap', + expr => 'tcp flag urg-set', + results => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }, + { + name => 'rfc1201_tcp_flag_psh_cleared', + savefile => 'arcnet-rfc1201-arp-icmp-http.pcap', + expr => 'tcp flag psh-cleared', + results => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65535, 65535, 65535], + }, { name => 'mstp_link_host', savefile => 'mstp_20140225214217.pcap', @@ -25250,6 +26102,43 @@ my @filter_apply_blocks = ( expr => 'ip dst 192.168.1.4', results => [0, 262144, 0, 262144], }, + + # Protocol exchange for the packets in "afs.pcap": + # 1. 00:60:08:9f:b1:f3 > 00:e0:f9:cc:18:00, IPv4 flags [none], UDP, 131.151.32.21.7001 > 131.151.1.146.7000 + # 2. 00:e0:f9:cc:18:00 > 00:60:08:9f:b1:f3, IPv4 flags [+, DF], UDP, 131.151.1.146.7000 > 131.151.32.21.7001 + # 3. 00:e0:f9:cc:18:00 > 00:60:08:9f:b1:f3, IPv4 flags [+, DF], UDP, 131.151.1.146 > 131.151.32.21 + # 4. 00:e0:f9:cc:18:00 > 00:60:08:9f:b1:f3, IPv4 flags [+, DF], UDP, 131.151.1.146 > 131.151.32.21 + # 5. 00:e0:f9:cc:18:00 > 00:60:08:9f:b1:f3, IPv4 flags [DF], UDP, 131.151.1.146 > 131.151.32.21 + # 6. 00:e0:f9:cc:18:00 > 00:60:08:9f:b1:f3, IPv4 flags [+, DF], UDP, 131.151.1.146.7000 > 131.151.32.21.7001 + # 7. 00:e0:f9:cc:18:00 > 00:60:08:9f:b1:f3, IPv4 flags [+, DF], UDP, 131.151.1.146 > 131.151.32.21 + # 8. 00:e0:f9:cc:18:00 > 00:60:08:9f:b1:f3, IPv4 flags [+, DF], UDP, 131.151.1.146 > 131.151.32.21 + # 9. 00:e0:f9:cc:18:00 > 00:60:08:9f:b1:f3, IPv4 flags [DF], UDP, 131.151.1.146 > 131.151.32.21 + # 10. 00:60:08:9f:b1:f3 > 00:e0:f9:cc:18:00, IPv4 flags [none], UDP, 131.151.32.21.7001 > 131.151.1.146.7000 + { + name => 'afs_ip_flag_df_set', + savefile => 'afs.pcap', + expr => 'ip flag df-set', + results => [0, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 0], + }, + { + name => 'afs_ip_flag_mf_set', + savefile => 'afs.pcap', + expr => 'ip flag mf-set', + results => [0, 65535, 65535, 65535, 0, 65535, 65535, 65535, 0, 0], + }, + { + name => 'afs_ip_flag_mf_cleared', + savefile => 'afs.pcap', + expr => 'ip flag mf-cleared', + results => [65535, 0, 0, 0, 65535, 0, 0, 0, 65535, 65535], + }, + { + name => 'afs_ip_flag_df_set_and_mf_cleared', + savefile => 'afs.pcap', + expr => 'ip flag df-set and mf-cleared', + results => [0, 0, 0, 0, 65535, 0, 0, 0, 65535, 0], + }, + { name => 'ip6', savefile => 'vrrp.pcap', @@ -25877,6 +26766,30 @@ my @filter_apply_blocks = ( expr => 'ip[6] & 0x40 == 0x40', results => [0, 0, 262144, 0, 0, 262144, 262144, 262144, 0, 262144, 262144, 262144, 262144, 0, 0], }, + { + name => 'ip_flag_df_set_DSA_TAG_BRCM', + savefile => 'brcm-tag.pcap', + expr => 'ip flag df-set', + results => [0, 0, 262144, 0, 0, 262144, 262144, 262144, 0, 262144, 262144, 262144, 262144, 0, 0], + }, + { + name => 'ip_flag_df_cleared_DSA_TAG_BRCM', + savefile => 'brcm-tag.pcap', + expr => 'ip flag df-cleared', + results => [262144, 262144, 0, 262144, 262144, 0, 0, 0, 262144, 0, 0, 0, 0, 0, 0], + }, + { + name => 'ip_flag_mf_set_DSA_TAG_BRCM', + savefile => 'brcm-tag.pcap', + expr => 'ip flag mf-set', + results => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }, + { + name => 'ip_flag_mf_cleared_DSA_TAG_BRCM', + savefile => 'brcm-tag.pcap', + expr => 'ip flag mf-cleared', + results => [262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 0, 0], + }, # Protocol stack for the packets in brcm-tag-stp.pcap: # 1. EG, 802.1Q VLAN ID 8, LLC, STP # 2. IG, LLC, STP @@ -26018,6 +26931,11 @@ sub errstr_invqual { return sprintf ('\'%s\' is not a valid qualifier for \'%s\'', shift, shift); } +# gen_flag() +sub errstr_invvalue { + return sprintf 'invalid \'%s\' ID \'%s\'', shift, shift; +} + # gen_scode() case Q_NET sub errstr_nonet { return sprintf ('unknown network \'%s\'', shift); @@ -26444,6 +27362,78 @@ my @filter_reject_tests = ( expr => 'sctp portrange 70000-80000', errstr => errstr_invport (70000), }, + { + name => 'flag_1', + DLT => 'EN10MB', + expr => 'flag 1', + errstr => errstr_invqual('flag', '1'), + }, + { + name => 'flag_1_2', + DLT => 'EN10MB', + expr => 'flag 1.2', + errstr => errstr_invqual('flag', '1.2'), + }, + { + name => 'flag_1_2_3', + DLT => 'EN10MB', + expr => 'flag 1.2.3', + errstr => errstr_invqual('flag', '1.2.3'), + }, + { + name => 'flag_1_2_3_4', + DLT => 'EN10MB', + expr => 'flag 1.2.3.4', + errstr => errstr_invqual('flag', '1.2.3.4'), + }, + { + name => 'flag_ipv4cidr', + DLT => 'EN10MB', + expr => 'flag 1.2.3.0/24', + errstr => errstr_invqual('flag', '1.2.3.0/24'), + }, + { + name => 'flag_ipv6addr', + DLT => 'EN10MB', + expr => 'flag fe80::', + errstr => errstr_invqual('flag', 'fe80::'), + }, + { + name => 'flag_ipv6cidr', + DLT => 'EN10MB', + expr => 'flag fe80::/16', + errstr => errstr_invqual('flag', 'fe80::/16'), + }, + { + name => 'flag_mac48', + DLT => 'EN10MB', + expr => 'flag a:b:c:d:e:f', + errstr => errstr_mac48_noether, + }, + { + name => 'flag_mac8', + DLT => 'ARCNET', + expr => 'flag $ab', + errstr => errstr_invqual('flag', '$XX'), + }, + { + name => 'flag_nosuchflag', + DLT => 'EN10MB', + expr => 'flag nosuchflag', + errstr => '\'flag\' must be proto-qualified', + }, + { + name => 'ip_flag_syn', + DLT => 'EN10MB', + expr => 'ip flag syn-set', + errstr => errstr_invvalue('ip flag', 'syn-set'), + }, + { + name => 'tcp_flag_df', + DLT => 'EN10MB', + expr => 'tcp flag df-set', + errstr => errstr_invvalue('tcp flag', 'df-set'), + }, { name => 'pppoes_and_vlan', DLT => 'EN10MB', @@ -27251,6 +28241,7 @@ my %pqual_features = ( gateway => 1, protochain => 1, proto => 1, + flag => 1, }, ip6 => { abbrev => 1, @@ -27339,6 +28330,7 @@ my %pqual_features = ( index => 1, port => 1, portrange => 1, + flag => 1, }, udp => { abbrev => 1, @@ -27443,6 +28435,8 @@ my %tqual_features = ( }, portrange => { }, + flag => { + }, ); sub tquals_with { @@ -27992,6 +28986,13 @@ sub DLT_feature { return item_with_without $DLTfeatures{$name}, $feature, 1; } +sub to_ { + # In Perl 5.8.4 "tr///" does not have the "r" option. + my $ret = shift; + $ret =~ tr[ .:/][_]; + return $ret; +} + # gen_load_internal() -> default foreach (pquals_without 'index') { push @filter_reject_tests, { @@ -28195,12 +29196,12 @@ foreach my $pq (pquals_without '') { # HID -> gen_ncode() -> q.proto == Q_DECNET -> q.addr != Q_DEFAULT && q.addr != Q_HOST # HID -> gen_ncode() -> default push @filter_reject_tests, { - name => "${pq}_gateway_HID", + name => "${pq}_${_}_HID", DLT => 'EN10MB', - expr => "$pq gateway 11.12.13.14", - errstr => $pq eq 'decnet' ? errstr_invqual ($pq, 'gateway') : - errstr_invqual ('gateway', '11.12.13.14'), - }; + expr => "$pq $_ 11.12.13.14", + errstr => $pq eq 'decnet' ? errstr_invqual ($pq, $_) : + errstr_invqual ($_, '11.12.13.14'), + } foreach qw(gateway flag); # HID push @filter_reject_tests, { name => "${pq}_${_}_HID", @@ -28212,12 +29213,12 @@ foreach my $pq (pquals_without '') { # HID '/' NUM -> gen_mcode() -> q.proto == Q_DECNET # HID '/' NUM -> gen_mcode() -> default push @filter_reject_tests, { - name => "${pq}_gateway_HID_NUM", + name => "${pq}_${_}_HID_NUM", DLT => 'EN10MB', - expr => "$pq gateway 11.12.0.0/16", - errstr => $pq eq 'decnet' ? errstr_invqual ($pq, 'gateway') : - errstr_invqual ('gateway', '11.12.0.0/16'), - }; + expr => "$pq $_ 11.12.0.0/16", + errstr => $pq eq 'decnet' ? errstr_invqual ($pq, $_) : + errstr_invqual ($_, '11.12.0.0/16'), + } foreach qw(gateway flag); # HID '/' NUM push @filter_reject_tests, { name => "${pq}_${_}_HID_NUM", @@ -28229,12 +29230,12 @@ foreach my $pq (pquals_without '') { # HID NETMASK HID -> gen_mcode() -> q.proto == Q_DECNET # HID NETMASK HID -> gen_mcode() -> default push @filter_reject_tests, { - name => "${pq}_gateway_HID_mask_HID", + name => "${pq}_${_}_HID_mask_HID", DLT => 'EN10MB', - expr => "$pq gateway 11.12.0.0 mask 255.255.0.0", - errstr => $pq eq 'decnet' ? errstr_invqual ($pq, 'gateway') : - errstr_invqual ('gateway', '11.12.0.0 mask 255.255.0.0'), - }; + expr => "$pq $_ 11.12.0.0 mask 255.255.0.0", + errstr => $pq eq 'decnet' ? errstr_invqual ($pq, $_) : + errstr_invqual ($_, '11.12.0.0 mask 255.255.0.0'), + } foreach qw(gateway flag); # HID NETMASK HID push @filter_reject_tests, { name => "${pq}_${_}_HID_mask_HID", @@ -28245,11 +29246,11 @@ foreach my $pq (pquals_without '') { } foreach qw(port portrange proto protochain); # HID6 -> gen_mcode6() -> default push @filter_reject_tests, { - name => "${pq}_gateway_HID6", + name => "${pq}_${_}_HID6", DLT => 'EN10MB', - expr => "$pq gateway fe80::0", - errstr => errstr_invqual ('gateway', 'fe80::0'), - }; + expr => "$pq $_ fe80::0", + errstr => errstr_invqual ($_, 'fe80::0'), + } foreach qw(gateway flag); # HID6 push @filter_reject_tests, { name => "${pq}_${_}_HID6", @@ -28260,11 +29261,11 @@ foreach my $pq (pquals_without '') { } foreach qw(port portrange proto protochain); # HID6 '/' NUM -> gen_mcode6() -> default push @filter_reject_tests, { - name => "${pq}_gateway_HID6_NUM", + name => "${pq}_${_}_HID6_NUM", DLT => 'EN10MB', - expr => "$pq gateway fe80::0/64", - errstr => errstr_invqual ('gateway', 'fe80::0/64'), - }; + expr => "$pq $_ fe80::0/64", + errstr => errstr_invqual ($_, 'fe80::0/64'), + } foreach qw(gateway flag); # HID6 '/' NUM push @filter_reject_tests, { name => "${pq}_${_}_HID6_NUM", @@ -28374,6 +29375,46 @@ foreach (pquals_without 'abbrev') { }; } +# ndaqual +foreach my $dqual (dquals_without 'flag') { + my $dqual_ = to_ ($dqual); + push @filter_reject_tests, { + name => "${dqual_}_flag_nosuchflag", + DLT => 'RAW', + expr => "$dqual flag nosuchflag", + errstr => errstr_syntax(), + }; + foreach my $pqual (pquals_without '') { + push @filter_reject_tests, { + name => "${pqual}_${dqual_}_flag_nosuchflag", + DLT => 'EN10MB', + expr => "$pqual $dqual flag nosuchflag", + errstr => errstr_syntax(), + }; + } +} + +# gen_scode() -> gen_flag() -> default case +foreach my $pqual (pquals_without 'flag') { + push @filter_reject_tests, { + name => "${pqual}_flag_nosuchflag", + DLT => 'RAW', + expr => "$pqual flag nosuchflag", + errstr => errstr_invqual ($pqual, 'flag'), + }; +} + +# gen_scode() -> gen_flag() -> Q_IP -> bpf_error() +# gen_scode() -> gen_flag() -> Q_TCP -> bpf_error() +foreach my $pqual (pquals_with 'flag') { + push @filter_reject_tests, { + name => "${pqual}_flag_nosuchflag", + DLT => 'EN10MB', + expr => "$pqual flag nosuchflag", + errstr => errstr_invvalue("$pqual flag", 'nosuchflag'), + }; +} + # Use a separate foreach loop for each feature because different loops skip # different DLTs and can terminate early. diff --git a/tests/filter/afs.pcap b/tests/filter/afs.pcap new file mode 100644 index 0000000000..360e604c46 Binary files /dev/null and b/tests/filter/afs.pcap differ