diff --git a/Makefile.in b/Makefile.in index 711136e4c7..d65803819c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -121,6 +121,8 @@ PUBHDR = \ HDR = $(PUBHDR) \ arcnet.h \ atmuni31.h \ + batadv_legacy_packet.h \ + batadv_packet.h \ diag-control.h \ ethertype.h \ extract.h \ diff --git a/batadv_legacy_packet.h b/batadv_legacy_packet.h new file mode 100644 index 0000000000..ff2715c240 --- /dev/null +++ b/batadv_legacy_packet.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-3 */ +/* Copyright (C) 2020 Linus Lüssing */ + +#ifndef _BATADV_LEGACY_PACKET_H_ +#define _BATADV_LEGACY_PACKET_H_ + +enum batadv_legacy_packettype { + BATADV_LEGACY_IV_OGM = 0x01, + BATADV_LEGACY_ICMP = 0x02, + BATADV_LEGACY_UNICAST = 0x03, + BATADV_LEGACY_BCAST = 0x04, + BATADV_LEGACY_VIS = 0x05, + BATADV_LEGACY_UNICAST_FRAG = 0x06, + BATADV_LEGACY_TT_QUERY = 0x07, + BATADV_LEGACY_ROAM_ADV = 0x08, + BATADV_LEGACY_UNICAST_4ADDR = 0x09, + BATADV_LEGACY_CODED = 0x0a, +}; + +#define ETH_ALEN 6 + +struct batadv_legacy_unicast_packet { + uint8_t packet_type; + uint8_t version; + uint8_t ttl; + uint8_t ttvn; + uint8_t dest[ETH_ALEN]; +}; + +struct batadv_legacy_unicast_4addr_packet { + uint8_t packet_type; + uint8_t version; + uint8_t ttl; + uint8_t src[ETH_ALEN]; + uint8_t subtype; + uint8_t reserved; +}; + +struct batadv_legacy_unicast_frag_packet { + uint8_t packet_type; + uint8_t version; + uint8_t ttl; + uint8_t ttvn; + uint8_t dest[ETH_ALEN]; + uint8_t flags; + uint8_t align; + uint8_t orig[ETH_ALEN]; + uint8_t seqno[2]; /* 2-byte integral value */ +}; + +struct batadv_legacy_bcast_packet { + uint8_t packet_type; + uint8_t version; + uint8_t ttl; + uint8_t reserved; + uint8_t seqno[4]; /* 4-byte integral value */ + uint8_t orig[ETH_ALEN]; +}; + +struct batadv_legacy_coded_packet { + uint8_t packet_type; + uint8_t version; + uint8_t ttl; + uint8_t first_ttvn; + uint8_t first_source[ETH_ALEN]; + uint8_t first_orig_dest[ETH_ALEN]; + uint8_t first_crc[4]; /* 4-byte integral value */ + uint8_t second_ttl; + uint8_t second_ttvn; + uint8_t second_dest[ETH_ALEN]; + uint8_t second_source[ETH_ALEN]; + uint8_t second_orig_dest[ETH_ALEN]; + uint8_t second_crc[4]; /* 4-byte integral value */ + uint8_t coded_len[2]; /* 2-byte integral value */ +}; + +#endif /* _BATADV_LEGACY_PACKET_H_ */ diff --git a/batadv_packet.h b/batadv_packet.h new file mode 100644 index 0000000000..06c0b65974 --- /dev/null +++ b/batadv_packet.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: BSD-3 */ +/* Copyright (C) 2024 Linus Lüssing */ + +#ifndef _BATADV_PACKET_H_ +#define _BATADV_PACKET_H_ + +/* For the definitive and most recent packet format definition, + * see the batadv_packet.h in the Linux kernel. + */ + +enum batadv_packettype { + BATADV_IV_OGM = 0x00, + BATADV_BCAST = 0x01, + BATADV_CODED = 0x02, + BATADV_ELP = 0x03, + BATADV_OGM2 = 0x04, + BATADV_MCAST = 0x05, + BATADV_UNICAST = 0x40, + BATADV_UNICAST_FRAG = 0x41, + BATADV_UNICAST_4ADDR = 0x42, + BATADV_ICMP = 0x43, + BATADV_UNICAST_TVLV = 0x44, +}; + +#define ETH_ALEN 6 + +struct batadv_unicast_packet { + uint8_t packet_type; + uint8_t version; + uint8_t ttl; + uint8_t ttvn; + uint8_t dest[ETH_ALEN]; +}; + +struct batadv_unicast_4addr_packet { + struct batadv_unicast_packet u; + uint8_t src[ETH_ALEN]; + uint8_t subtype; + uint8_t reserved; +}; + +struct batadv_frag_packet { + uint8_t packet_type; + uint8_t version; + uint8_t ttl; + uint8_t num_pri; /* number and priority */ + uint8_t dest[ETH_ALEN]; + uint8_t orig[ETH_ALEN]; + uint8_t seqno[2]; /* 2-byte integral value */ + uint8_t total_size[2]; /* 2-byte integral value */ +}; + +struct batadv_bcast_packet { + uint8_t packet_type; + uint8_t version; + uint8_t ttl; + uint8_t reserved; + uint8_t seqno[4]; /* 4-byte integral value */ + uint8_t orig[ETH_ALEN]; +}; + +struct batadv_mcast_packet { + uint8_t packet_type; + uint8_t version; + uint8_t ttl; + uint8_t reserved; + uint8_t tvlv_len[2]; /* 2-byte integral value */ +}; + +struct batadv_coded_packet { + uint8_t packet_type; + uint8_t version; + uint8_t ttl; + uint8_t first_ttvn; + uint8_t first_source[ETH_ALEN]; + uint8_t first_orig_dest[ETH_ALEN]; + uint8_t first_crc[4]; /* 4-byte integral value */ + uint8_t second_ttl; + uint8_t second_ttvn; + uint8_t second_dest[ETH_ALEN]; + uint8_t second_source[ETH_ALEN]; + uint8_t second_orig_dest[ETH_ALEN]; + uint8_t second_crc[4]; /* 4-byte integral value */ + uint8_t coded_len[2]; /* 2-byte integral value */ +}; + +#endif /* _BATADV_PACKET_H_ */ diff --git a/ethertype.h b/ethertype.h index e34e07b98d..d8e87e4f55 100644 --- a/ethertype.h +++ b/ethertype.h @@ -49,6 +49,9 @@ #ifndef ETHERTYPE_TRAIL #define ETHERTYPE_TRAIL 0x1000 #endif +#ifndef ETHERTYPE_BATMAN +#define ETHERTYPE_BATMAN 0x4305 /* B.A.T.M.A.N. Advanced */ +#endif #ifndef ETHERTYPE_MOPDL #define ETHERTYPE_MOPDL 0x6001 #endif diff --git a/gencode.c b/gencode.c index ac6681e29a..d8b98147c9 100644 --- a/gencode.c +++ b/gencode.c @@ -54,6 +54,8 @@ #include "sunatmpos.h" #include "pflog.h" #include "ppp.h" +#include "batadv_packet.h" +#include "batadv_legacy_packet.h" #include "pcap/sll.h" #include "pcap/ipnet.h" #include "arcnet.h" @@ -9951,6 +9953,330 @@ gen_vxlan(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni) return b1; } +static struct block * +gen_batadv_check_version(compiler_state_t *cstate, struct block *b0, bpf_u_int32 version) +{ + struct block *b1; + + if (version > UINT8_MAX) + bpf_error(cstate, + "batman-adv compatibility version number %u unsupported", + version); + + b1 = gen_cmp(cstate, OR_LINKPL, 1, BPF_B, version); + gen_and(b0, b1); + + return b1; +} + +static struct block * +gen_batadv_check_type(compiler_state_t *cstate, struct block *b0, + bpf_u_int32 version, bpf_u_int32 type) +{ + struct block *b1; + + switch (version) { + case 14: + case 15: + if (type > UINT8_MAX) + bpf_error(cstate, + "batman-adv packet type %u unsupported for compatibility version %u", + type, version); + + b1 = gen_cmp(cstate, OR_LINKPL, 0, BPF_B, type); + gen_and(b0, b1); + b0 = b1; + + break; + default: + bpf_error(cstate, + "batman-adv compatibility version number %u unsupported", + version); + } + + return b0; +} + + +static void gen_batadv_push_offset(compiler_state_t *cstate, u_int offset) +{ + PUSH_LINKHDR(cstate, DLT_EN10MB, cstate->off_linkpl.is_variable, + cstate->off_linkpl.constant_part + cstate->off_nl + offset, + cstate->off_linkpl.reg); + + cstate->off_linktype.constant_part += cstate->off_linkhdr.constant_part; + cstate->off_linkpl.constant_part += cstate->off_linkhdr.constant_part; + + cstate->off_nl = 0; + cstate->off_nl_nosnap = 0; /* no 802.2 LLC */ +} + +static void +gen_batadv_offsets_v14(compiler_state_t *cstate, bpf_u_int32 type) +{ + size_t offset; + + switch (type) { + case BATADV_LEGACY_UNICAST: /* 0x03 */ + offset = sizeof(struct batadv_legacy_unicast_packet); + break; + case BATADV_LEGACY_BCAST: /* 0x04 */ + offset = sizeof(struct batadv_legacy_bcast_packet); + break; + case BATADV_LEGACY_UNICAST_FRAG: /* 0x06 */ + offset = sizeof(struct batadv_legacy_unicast_frag_packet); + break; + case BATADV_LEGACY_UNICAST_4ADDR: /* 0x09 */ + offset = sizeof(struct batadv_legacy_unicast_4addr_packet); + break; + case BATADV_LEGACY_CODED: /* 0x0a */ + offset = sizeof(struct batadv_legacy_coded_packet); + break; + default: + offset = 0; + } + + if (offset) + gen_batadv_push_offset(cstate, (u_int)offset); +} + +static void +gen_prepare_var_offset(compiler_state_t *cstate, bpf_abs_offset *off, struct slist *s) +{ + struct slist *s2; + + if (!off->is_variable) + off->is_variable = 1; + if (off->reg == -1) { + off->reg = alloc_reg(cstate); + + s2 = new_stmt(cstate, BPF_ALU|BPF_AND); + s2->s.k = 0; + s2 = new_stmt(cstate, BPF_ST); + s2->s.k = off->reg; + sappend(s, s2); + } +} + +/** + * gen_batadv_loadx_tvlv_len_offset() - load offset to tvlv_len into X + * @cstate: our compiler state + * @bat_offset: our offset to the start of the batman-adv packet header + * @field_offset: offset of tvlv_len field within the batman-adv packet header + * @s: instructions list to append to + * + * Will load: X = bat_offset + field_offset. So that [X] in the packet will + * point to the most-significant byte of the tvlv_len in a batman-adv packet. + */ +static void +gen_batadv_loadx_tvlv_len_offset(compiler_state_t *cstate, + bpf_abs_offset *bat_offset, + bpf_u_int32 field_offset, struct slist *s) +{ + struct slist *s2; + + s2 = new_stmt(cstate, BPF_LD|BPF_MEM); + s2->s.k = bat_offset->reg; + sappend(s, s2); + + s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K); + s2->s.k = bat_offset->constant_part + field_offset; + sappend(s, s2); + + s2 = new_stmt(cstate, BPF_MISC|BPF_TAX); + s2->s.k = 0; + sappend(s, s2); +} + +/** + * gen_batadv_loadx_tvlv_len() - load tvlv_len value into X + * @cstate: our compiler state + * @bat_offset: our offset to the start of the batman-adv packet header + * @field_offset: offset of tvlv_len field within the batman-adv packet header + * @s: instructions list to append to + * + * Loads the value of the 2 byte tvlv_len field in a given batman-adv packet + * header into the X register. + */ +static void +gen_batadv_loadx_tvlv_len(compiler_state_t *cstate, bpf_abs_offset *bat_offset, + bpf_u_int32 field_offset, struct slist *s) +{ + struct slist *s2; + + /* load offset to tvlv_len field into X register */ + gen_batadv_loadx_tvlv_len_offset(cstate, bat_offset, field_offset, s); + + /* clear A register */ + s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K); + s2->s.k = 0; + sappend(s, s2); + + /* load most significant byte of tvlv_len */ + s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B); + s2->s.k = 0; + sappend(s, s2); + + /* multiply by 2^8 for real value of MSB, make room for LSB */ + s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K); + s2->s.k = 8; + sappend(s, s2); + + /* load least significant byte of tvlv_len */ + s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B); + s2->s.k = 1; + sappend(s, s2); + + s2 = new_stmt(cstate, BPF_MISC|BPF_TAX); + s2->s.k = 0; + sappend(s, s2); +} + +/** + * gen_batadv_offset_addx() - add X register to a variable offset + * @cstate: our compiler state + * @off: the (variable) offset to add to + * @s: instructions list to append to + * + * Adds the value from the X register to the given variable offset. + */ +static void +gen_batadv_offset_addx(compiler_state_t *cstate, bpf_abs_offset *off, + struct slist *s) +{ + struct slist *s2; + + s2 = new_stmt(cstate, BPF_LD|BPF_MEM); + s2->s.k = off->reg; + sappend(s, s2); + + s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X); + s2->s.k = 0; + sappend(s, s2); + + s2 = new_stmt(cstate, BPF_ST); + s2->s.k = off->reg; + sappend(s, s2); +} + +/** + * gen_batadv_offsets_add_tvlv_len() - add tvlv_len to payload offsets + * @cstate: our compiler state + * @b0: instructions block to add to + * @field_offset: offset of tvlv_len field within the batman-adv packet header + * + * Adds the tvlv_len value from/in a batman-adv packet header to the offsets + * of cstate->off_linkpl and cstate->off_linktype. + * + * Return: The updated instructions block. + */ +static struct block * +gen_batadv_offsets_add_tvlv_len(compiler_state_t *cstate, struct block *b0, + bpf_u_int32 field_offset) +{ + struct slist s; + + s.next = NULL; + + /* turn constant-only offsets into variable offsets as we need to add + * variable offset values (tvlv_len) to them later */ + gen_prepare_var_offset(cstate, &cstate->off_linkpl, &s); + gen_prepare_var_offset(cstate, &cstate->off_linktype, &s); + + /* load tvlv_len into X register */ + gen_batadv_loadx_tvlv_len(cstate, &cstate->off_linkpl, field_offset, &s); + + gen_batadv_offset_addx(cstate, &cstate->off_linkpl, &s); + gen_batadv_offset_addx(cstate, &cstate->off_linktype, &s); + + sappend(s.next, b0->head->stmts); + b0->head->stmts = s.next; + + return b0; +} + +static struct block * +gen_batadv_offsets_v15(compiler_state_t *cstate, struct block *b0, bpf_u_int32 type) +{ + size_t offset; + bpf_u_int32 field_offset; + + switch (type) { + case BATADV_BCAST: /* 0x01 */ + offset = sizeof(struct batadv_bcast_packet); + break; + case BATADV_CODED: /* 0x02 */ + offset = sizeof(struct batadv_coded_packet); + break; + case BATADV_MCAST: /* 0x05 */ + offset = sizeof(struct batadv_mcast_packet); + field_offset = (bpf_u_int32)offsetof(struct batadv_mcast_packet, + tvlv_len); + + b0 = gen_batadv_offsets_add_tvlv_len(cstate, b0, field_offset); + break; + case BATADV_UNICAST: /* 0x40 */ + offset = sizeof(struct batadv_unicast_packet); + break; + case BATADV_UNICAST_FRAG: /* 0x41 */ + offset = sizeof(struct batadv_frag_packet); + break; + case BATADV_UNICAST_4ADDR: /* 0x42 */ + offset = sizeof(struct batadv_unicast_4addr_packet); + break; + default: + offset = 0; + } + + if (offset) + gen_batadv_push_offset(cstate, (u_int)offset); + + return b0; +} + +static struct block * +gen_batadv_offsets(compiler_state_t *cstate, struct block *b0, bpf_u_int32 version, bpf_u_int32 type) +{ + switch (version) { + case 14: + gen_batadv_offsets_v14(cstate, type); + break; + case 15: + b0 = gen_batadv_offsets_v15(cstate, b0, type); + break; + default: + break; + } + + return b0; +} + +struct block * +gen_batadv(compiler_state_t *cstate, bpf_u_int32 version, int has_version, + bpf_u_int32 type, int has_type) +{ + struct block *b0; + + /* + * Catch errors reported by us and routines below us, and return NULL + * on an error. + */ + if (setjmp(cstate->top_ctx)) + return (NULL); + + b0 = gen_linktype(cstate, ETHERTYPE_BATMAN); + + if (has_version) + b0 = gen_batadv_check_version(cstate, b0, version); + + if (has_type) { + b0 = gen_batadv_check_type(cstate, b0, version, type); + b0 = gen_batadv_offsets(cstate, b0, version, type); + } + + return b0; +} + /* Check that the encapsulated frame has a link layer header * for Ethernet filters. */ static struct block * diff --git a/gencode.h b/gencode.h index cf9baafed1..d8dfe77855 100644 --- a/gencode.h +++ b/gencode.h @@ -359,6 +359,9 @@ struct block *gen_pppoes(compiler_state_t *, bpf_u_int32, int); struct block *gen_geneve(compiler_state_t *, bpf_u_int32, int); struct block *gen_vxlan(compiler_state_t *, bpf_u_int32, int); +struct block *gen_batadv(compiler_state_t *, bpf_u_int32, int, + bpf_u_int32, int); + struct block *gen_atmfield_code(compiler_state_t *, int, bpf_u_int32, int, int); struct block *gen_atmtype_abbrev(compiler_state_t *, int); diff --git a/grammar.y.in b/grammar.y.in index 0182ae0c14..cf99e81535 100644 --- a/grammar.y.in +++ b/grammar.y.in @@ -385,6 +385,7 @@ DIAG_OFF_BISON_BYACC %type mtp2type %type mtp3field %type mtp3fieldvalue mtp3value mtp3listvalue +%type pbatadv %token DST SRC HOST GATEWAY @@ -403,7 +404,7 @@ DIAG_OFF_BISON_BYACC %token LEN %token IPV6 ICMPV6 AH ESP %token VLAN MPLS -%token PPPOED PPPOES GENEVE VXLAN +%token PPPOED PPPOES GENEVE VXLAN BATADV %token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP %token STP %token IPX @@ -702,11 +703,40 @@ other: pqual TK_BROADCAST { CHECK_PTR_VAL(($$ = gen_broadcast(cstate, $1))); } | GENEVE { CHECK_PTR_VAL(($$ = gen_geneve(cstate, 0, 0))); } | VXLAN pnum { CHECK_PTR_VAL(($$ = gen_vxlan(cstate, $2, 1))); } | VXLAN { CHECK_PTR_VAL(($$ = gen_vxlan(cstate, 0, 0))); } + | BATADV pbatadv { $$ = $2; } | pfvar { $$ = $1; } | pqual p80211 { $$ = $2; } | pllc { $$ = $1; } ; +pbatadv: { CHECK_PTR_VAL(($$ = gen_batadv(cstate, 0, 0, 0, 0))); } + | pnum { CHECK_PTR_VAL(($$ = gen_batadv(cstate, $1, 1, 0, 0))); } + | pnum pnum { CHECK_PTR_VAL(($$ = gen_batadv(cstate, $1, 1, $2, 1))); } + | pnum ID + { + int type; + + switch ($1) { + case 14: + type = pcap_nametobatadvtype_v14($2); + break; + case 15: + type = pcap_nametobatadvtype_v15($2); + break; + default: + bpf_set_error(cstate, "batman-adv compatibility version number %u unsupported", $1); + YYABORT; + } + + if (type == PROTO_UNDEF) { + bpf_set_error(cstate, "invalid batman-adv packet type value \"%s\"", $2); + YYABORT; + } + + CHECK_PTR_VAL(($$ = gen_batadv(cstate, $1, 1, type, 1))); + } + ; + pfvar: PF_IFNAME ID { CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ifname(cstate, $2))); } | PF_RSET ID { CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ruleset(cstate, $2))); } | PF_RNR NUM { CHECK_PTR_VAL(($$ = gen_pf_rnr(cstate, $2))); } diff --git a/nametoaddr.c b/nametoaddr.c index 0b2922880d..734b02b1dd 100644 --- a/nametoaddr.c +++ b/nametoaddr.c @@ -129,8 +129,12 @@ #include "diag-control.h" +#include "batadv_packet.h" +#include "batadv_legacy_packet.h" + #include "gencode.h" #include + #include "nametoaddr.h" #include "thread-local.h" @@ -584,6 +588,7 @@ PCAP_API_DEF struct eproto eproto_db[] = { { "moprc", ETHERTYPE_MOPRC }, { "rarp", ETHERTYPE_REVARP }, { "sca", ETHERTYPE_SCA }, + { "batadv", ETHERTYPE_BATMAN }, { (char *)0, 0 } }; @@ -624,6 +629,61 @@ pcap_nametollc(const char *s) return PROTO_UNDEF; } +/* Static data base of batman-adv v14 packet type values. */ +static struct eproto batadv_type_db_v14[] = { + { "iv-ogm", BATADV_LEGACY_IV_OGM }, + { "icmp", BATADV_LEGACY_ICMP }, + { "unicast", BATADV_LEGACY_UNICAST }, + { "bcast", BATADV_LEGACY_BCAST }, + { "vis", BATADV_LEGACY_VIS }, + { "unicast-frag", BATADV_LEGACY_UNICAST_FRAG }, + { "tt-query", BATADV_LEGACY_TT_QUERY }, + { "roam-adv", BATADV_LEGACY_ROAM_ADV }, + { "unicast-4addr", BATADV_LEGACY_UNICAST_4ADDR }, + { "coded", BATADV_LEGACY_CODED }, + { (char *)0, 0 } +}; + +int pcap_nametobatadvtype_v14(const char *s) +{ + struct eproto *p = batadv_type_db_v14; + + while (p->s != 0) { + if (strcmp(p->s, s) == 0) + return p->p; + p += 1; + } + return PROTO_UNDEF; +} + +/* Static data base of batman-adv v15 packet type values. */ +static struct eproto batadv_type_db_v15[] = { + { "iv-ogm", BATADV_IV_OGM }, + { "bcast", BATADV_BCAST }, + { "coded", BATADV_CODED }, + { "elp", BATADV_ELP }, + { "ogm2", BATADV_OGM2 }, + { "mcast", BATADV_MCAST }, + { "unicast", BATADV_UNICAST }, + { "unicast-frag", BATADV_UNICAST_FRAG }, + { "unicast-4addr", BATADV_UNICAST_4ADDR }, + { "icmp", BATADV_ICMP }, + { "unicast-tvlv", BATADV_UNICAST_TVLV }, + { (char *)0, 0 } +}; + +int pcap_nametobatadvtype_v15(const char *s) +{ + struct eproto *p = batadv_type_db_v15; + + while (p->s != 0) { + if (strcmp(p->s, s) == 0) + return p->p; + p += 1; + } + return PROTO_UNDEF; +} + /* Hex digit to 8-bit unsigned integer. */ static inline u_char xdtoi(u_char c) diff --git a/pcap-filter.manmisc.in b/pcap-filter.manmisc.in index 3a4619266a..35d9daedc3 100644 --- a/pcap-filter.manmisc.in +++ b/pcap-filter.manmisc.in @@ -98,6 +98,7 @@ protocols are: .BR arp , .BR rarp , .BR decnet , +.BR batadv , .BR sctp , .B tcp and @@ -400,7 +401,7 @@ True if the packet is an IPv6 multicast packet. .IP "\fBether proto \fIprotocol\fR" True if the packet is of ether type \fIprotocol\fR. \fIProtocol\fP can be a number or one of the names -\fBaarp\fP, \fBarp\fP, \fBatalk\fP, \fBdecnet\fP, \fBip\fP, \fBip6\fP, +\fBaarp\fP, \fBarp\fP, \fBatalk\fP, \fBbatadv\fP, \fBdecnet\fP, \fBip\fP, \fBip6\fP, \fBipx\fP, \fBiso\fP, \fBlat\fP, \fBloopback\fP, \fBmopdl\fP, \fBmoprc\fP, \fBnetbeui\fP, \fBrarp\fP, \fBsca\fP or \fBstp\fP. Note these identifiers (except \fBloopback\fP) are also keywords @@ -454,7 +455,7 @@ the filter checks for the IPX etype in an Ethernet frame, the IPX DSAP in the LLC header, the 802.3-with-no-LLC-header encapsulation of IPX, and the IPX etype in a SNAP frame. .RE -.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP" +.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP, \fBbatadv\fP" Abbreviations for: .in +.5i .nf @@ -812,6 +813,37 @@ For example: .fi .in -.5i filters IPv6 protocol encapsulated in VXLAN with VNI 0x7. +.IP "\fBbatadv \fI[version] \fI[type]\fR" +True if the packet is a B.A.T.M.A.N. Advanced packet (Ethernet type 0x4305). +If the optional \fIversion\fR is specified, only true if the packet has the +specified batman-adv compatibility \fIversion\fR. If the optional \fIversion\fR +and \fItype\fR are specified, only true if the packet has both the specified +batman-adv compatibility \fIversion\fR and batman-adv packet \fItype\fR. +.IP +\fIversion\fR may be a number from 0 to 255, though only compatibility version +14 and 15 were actually deployed in the wild. Version 15 is the current version, +14 is considered deprecated. +.IP +\fItype\fR is currently only defined for compatibility \fIversion\fR 14 and 15. +\fItype\fR may be a number from 0 to 255 for compatibility \fIversion\fR 14 and 15. +.IP +The following packet \fItype\fR aliases are available for compat \fIversion\fR 14: +\fBiv-ogm\fP, \fBicmp\fP, \fBunicast\fP, \fBbcast\fP, \fBvis\fP, \fBunicast-frag\fP, +\fBtt-query\fP, \fBroam-adv\fP, \fBunicast-4addr\fP, \fPcoded\fP. +.IP +The following packet \fItype\fR aliases are available for compat \fIversion\fR 15: +\fBiv-ogm\fP, \fBbcast\fP, \fBcoded\fP, \fBelp\fP, \fBogm2\fP, \fBmcast\fP, +\fBunicast\fP, \fBunicast-frag\fP, \fBunicast-4addr\fP, \fBicmp\fP, +\fPunicast-tvlv\fP. +.IP +Note that when the \fBbatadv\fR keyword is encountered in an expression and +a batman-adv packet \fItype\fR is provided which specifies an encapsulating +packet type then it changes the decoding offsets for the remainder of the +expression on the assumption that the packet is a batman-adv packet. For compat +\fIversion\fR 14 these are packet \fItype\fRs \fBunicast\fP, \fBbcast\fP, +\fBunicast-frag\fP, \fBunicast-4addr\fP and \fBcoded\fP. For compat \fIversion\fR +15 these are currently packet \fItype\fRs \fBbcast\fP, \fBcoded\fP, \fBmcast\fP, +\fBunicast\fP, \fBunicast-frag\fP and \fBunicast-4addr\fP. .IP "\fBiso proto \fIprotocol\fR" True if the packet is an OSI packet of protocol type \fIprotocol\fP. \fIProtocol\fP can be a number or one of the names diff --git a/pcap/namedb.h b/pcap/namedb.h index 28a60a4c71..1a81406dfa 100644 --- a/pcap/namedb.h +++ b/pcap/namedb.h @@ -95,6 +95,11 @@ PCAP_API int pcap_nametoeproto(const char *); PCAP_AVAILABLE_0_9 PCAP_API int pcap_nametollc(const char *); +PCAP_AVAILABLE_1_11 +PCAP_API int pcap_nametobatadvtype_v14(const char *); + +PCAP_AVAILABLE_1_11 +PCAP_API int pcap_nametobatadvtype_v15(const char *); /* * If a protocol is unknown, PROTO_UNDEF is returned. * Also, pcap_nametoport() returns the protocol along with the port number. diff --git a/scanner.l b/scanner.l index 357fc4d968..641f0001db 100644 --- a/scanner.l +++ b/scanner.l @@ -361,6 +361,7 @@ pppoed return PPPOED; pppoes return PPPOES; geneve return GENEVE; vxlan return VXLAN; +batadv return BATADV; lane return LANE; llc return LLC;