Skip to content

Commit a26e995

Browse files
committed
Add support for B.A.T.M.A.N. Advanced
This adds support for the layer 2 mesh routing protocol B.A.T.M.A.N. Advanced. "batadv" can be used to filter on batman-adv packets. It also allows later filters to look at frames inside the tunnel when both "version" and "type" are specified. Documentation for the batman-adv protocol can be found at the following locations: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/networking/batman-adv.rst https://www.open-mesh.org/ Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
1 parent bcd6c3f commit a26e995

10 files changed

+1235
-3
lines changed

ethertype.h

+3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
#ifndef ETHERTYPE_TRAIL
5050
#define ETHERTYPE_TRAIL 0x1000
5151
#endif
52+
#ifndef ETHERTYPE_BATMAN
53+
#define ETHERTYPE_BATMAN 0x4305 /* B.A.T.M.A.N. Advanced */
54+
#endif
5255
#ifndef ETHERTYPE_MOPDL
5356
#define ETHERTYPE_MOPDL 0x6001
5457
#endif

gencode.c

+165
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
#include "atmuni31.h"
6161
#include "sunatmpos.h"
6262
#include "ppp.h"
63+
#include "pcap/batadv_packet.h"
64+
#include "pcap/batadv_legacy_packet.h"
6365
#include "pcap/sll.h"
6466
#include "pcap/ipnet.h"
6567
#include "arcnet.h"
@@ -9483,6 +9485,169 @@ gen_geneve(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni)
94839485
return b1;
94849486
}
94859487

9488+
struct block *
9489+
gen_batadv_check_version(compiler_state_t *cstate, struct block *b0, bpf_u_int32 version)
9490+
{
9491+
struct block *b1;
9492+
9493+
if (version > UINT8_MAX)
9494+
bpf_error(cstate,
9495+
"batman-adv compatibility version number %u unsupported",
9496+
version);
9497+
9498+
b1 = gen_cmp(cstate, OR_LINKPL, 1, BPF_B, version);
9499+
gen_and(b0, b1);
9500+
9501+
return b1;
9502+
}
9503+
9504+
struct block *
9505+
gen_batadv_check_type(compiler_state_t *cstate, struct block *b0,
9506+
bpf_u_int32 version, bpf_u_int32 type)
9507+
{
9508+
struct block *b1;
9509+
9510+
switch (version) {
9511+
case 14:
9512+
case 15:
9513+
if (type > UINT8_MAX)
9514+
bpf_error(cstate,
9515+
"batman-adv packet type %u unsupported for compatibility version %u",
9516+
type, version);
9517+
9518+
b1 = gen_cmp(cstate, OR_LINKPL, 0, BPF_B, type);
9519+
gen_and(b0, b1);
9520+
b0 = b1;
9521+
9522+
break;
9523+
default:
9524+
bpf_error(cstate,
9525+
"batman-adv compatibility version number %u unsupported",
9526+
version);
9527+
}
9528+
9529+
return b0;
9530+
}
9531+
9532+
9533+
static void gen_batadv_push_offset(compiler_state_t *cstate, size_t offset)
9534+
{
9535+
PUSH_LINKHDR(cstate, DLT_EN10MB, cstate->off_linkpl.is_variable,
9536+
cstate->off_linkpl.constant_part + cstate->off_nl + offset,
9537+
cstate->off_linkpl.reg);
9538+
9539+
cstate->off_linktype.constant_part += cstate->off_linkhdr.constant_part;
9540+
cstate->off_linkpl.constant_part += cstate->off_linkhdr.constant_part;
9541+
9542+
cstate->off_nl = 0;
9543+
cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
9544+
}
9545+
9546+
static void
9547+
gen_batadv_offsets_v14(compiler_state_t *cstate, bpf_u_int32 type)
9548+
{
9549+
size_t offset;
9550+
9551+
switch (type) {
9552+
case BATADV_LEGACY_UNICAST: /* 0x03 */
9553+
offset = sizeof(struct batadv_legacy_unicast_packet);
9554+
break;
9555+
case BATADV_LEGACY_BCAST: /* 0x04 */
9556+
offset = sizeof(struct batadv_legacy_bcast_packet);
9557+
break;
9558+
case BATADV_LEGACY_UNICAST_FRAG: /* 0x06 */
9559+
offset = sizeof(struct batadv_legacy_unicast_frag_packet);
9560+
break;
9561+
case BATADV_LEGACY_UNICAST_4ADDR: /* 0x09 */
9562+
offset = sizeof(struct batadv_legacy_unicast_4addr_packet);
9563+
break;
9564+
case BATADV_LEGACY_CODED: /* 0x0a */
9565+
offset = sizeof(struct batadv_legacy_coded_packet);
9566+
break;
9567+
default:
9568+
offset = 0;
9569+
}
9570+
9571+
if (offset)
9572+
gen_batadv_push_offset(cstate, offset);
9573+
}
9574+
9575+
static void
9576+
gen_batadv_offsets_v15(compiler_state_t *cstate, bpf_u_int32 type)
9577+
{
9578+
size_t offset;
9579+
9580+
switch (type) {
9581+
case BATADV_BCAST: /* 0x01 */
9582+
offset = sizeof(struct batadv_bcast_packet);
9583+
break;
9584+
case BATADV_CODED: /* 0x02 */
9585+
offset = sizeof(struct batadv_coded_packet);
9586+
break;
9587+
case BATADV_UNICAST: /* 0x40 */
9588+
offset = sizeof(struct batadv_unicast_packet);
9589+
break;
9590+
case BATADV_UNICAST_FRAG: /* 0x41 */
9591+
offset = sizeof(struct batadv_frag_packet);
9592+
break;
9593+
case BATADV_UNICAST_4ADDR: /* 0x42 */
9594+
offset = sizeof(struct batadv_unicast_4addr_packet);
9595+
break;
9596+
case BATADV_UNICAST_TVLV:
9597+
/* unsupported for now, needs variable offset to
9598+
* take tvlv_len into account
9599+
*/
9600+
/* fall through */
9601+
default:
9602+
offset = 0;
9603+
}
9604+
9605+
if (offset)
9606+
gen_batadv_push_offset(cstate, offset);
9607+
}
9608+
9609+
static void
9610+
gen_batadv_offsets(compiler_state_t *cstate, bpf_u_int32 version, bpf_u_int32 type)
9611+
{
9612+
switch (version) {
9613+
case 14:
9614+
gen_batadv_offsets_v14(cstate, type);
9615+
break;
9616+
case 15:
9617+
gen_batadv_offsets_v15(cstate, type);
9618+
break;
9619+
default:
9620+
break;
9621+
}
9622+
}
9623+
9624+
struct block *
9625+
gen_batadv(compiler_state_t *cstate, bpf_u_int32 version, int has_version,
9626+
bpf_u_int32 type, int has_type)
9627+
{
9628+
struct block *b0, *b1;
9629+
struct slist *s;
9630+
9631+
/*
9632+
* Catch errors reported by us and routines below us, and return NULL
9633+
* on an error.
9634+
*/
9635+
if (setjmp(cstate->top_ctx))
9636+
return (NULL);
9637+
9638+
b0 = gen_linktype(cstate, ETHERTYPE_BATMAN);
9639+
9640+
if (has_version)
9641+
b0 = gen_batadv_check_version(cstate, b0, version);
9642+
9643+
if (has_type) {
9644+
b0 = gen_batadv_check_type(cstate, b0, version, type);
9645+
gen_batadv_offsets(cstate, version, type);
9646+
}
9647+
9648+
return b0;
9649+
}
9650+
94869651
/* Check that the encapsulated frame has a link layer header
94879652
* for Ethernet filters. */
94889653
static struct block *

gencode.h

+3
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@ struct block *gen_pppoes(compiler_state_t *, bpf_u_int32, int);
346346

347347
struct block *gen_geneve(compiler_state_t *, bpf_u_int32, int);
348348

349+
struct block *gen_batadv(compiler_state_t *, bpf_u_int32, int,
350+
bpf_u_int32, int);
351+
349352
struct block *gen_atmfield_code(compiler_state_t *, int, bpf_u_int32,
350353
int, int);
351354
struct block *gen_atmtype_abbrev(compiler_state_t *, int);

grammar.y.in

+32-1
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ DIAG_OFF_BISON_BYACC
347347
%type <i> mtp2type
348348
%type <blk> mtp3field
349349
%type <blk> mtp3fieldvalue mtp3value mtp3listvalue
350+
%type <rblk> pbatadv
350351

351352

352353
%token DST SRC HOST GATEWAY
@@ -365,7 +366,7 @@ DIAG_OFF_BISON_BYACC
365366
%token LEN
366367
%token IPV6 ICMPV6 AH ESP
367368
%token VLAN MPLS
368-
%token PPPOED PPPOES GENEVE
369+
%token PPPOED PPPOES GENEVE BATADV
369370
%token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP
370371
%token STP
371372
%token IPX
@@ -592,11 +593,41 @@ other: pqual TK_BROADCAST { CHECK_PTR_VAL(($$ = gen_broadcast(cstate, $1))); }
592593
| PPPOES { CHECK_PTR_VAL(($$ = gen_pppoes(cstate, 0, 0))); }
593594
| GENEVE pnum { CHECK_PTR_VAL(($$ = gen_geneve(cstate, $2, 1))); }
594595
| GENEVE { CHECK_PTR_VAL(($$ = gen_geneve(cstate, 0, 0))); }
596+
| BATADV pbatadv { $$ = $2; }
595597
| pfvar { $$ = $1; }
596598
| pqual p80211 { $$ = $2; }
597599
| pllc { $$ = $1; }
598600
;
599601

602+
pbatadv: { CHECK_PTR_VAL(($$ = gen_batadv(cstate, 0, 0, 0, 0))); }
603+
| pnum { CHECK_PTR_VAL(($$ = gen_batadv(cstate, $1, 1, 0, 0))); }
604+
| pnum pnum { CHECK_PTR_VAL(($$ = gen_batadv(cstate, $1, 1, $2, 1))); }
605+
| pnum ID
606+
{
607+
int type;
608+
CHECK_INT_VAL($1);
609+
CHECK_PTR_VAL($2);
610+
611+
switch ($1) {
612+
case 14:
613+
type = pcap_nametobatadvtype_v14($2);
614+
break;
615+
case 15:
616+
type = pcap_nametobatadvtype_v15($2);
617+
break;
618+
default:
619+
YYABORT;
620+
}
621+
622+
if (type == PROTO_UNDEF) {
623+
bpf_set_error(cstate, "invalid batman-adv packet type value \"%s\"", $2);
624+
YYABORT;
625+
}
626+
627+
CHECK_PTR_VAL(($$ = gen_batadv(cstate, $1, 1, type, 1)));
628+
}
629+
;
630+
600631
pfvar: PF_IFNAME ID { CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ifname(cstate, $2))); }
601632
| PF_RSET ID { CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ruleset(cstate, $2))); }
602633
| PF_RNR NUM { CHECK_PTR_VAL(($$ = gen_pf_rnr(cstate, $2))); }

nametoaddr.c

+58
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,10 @@
137137
#include "diag-control.h"
138138

139139
#include "gencode.h"
140+
#include <pcap/batadv_packet.h>
141+
#include <pcap/batadv_legacy_packet.h>
140142
#include <pcap/namedb.h>
143+
141144
#include "nametoaddr.h"
142145

143146
#ifdef HAVE_OS_PROTO_H
@@ -604,6 +607,7 @@ PCAP_API_DEF struct eproto eproto_db[] = {
604607
{ "moprc", ETHERTYPE_MOPRC },
605608
{ "rarp", ETHERTYPE_REVARP },
606609
{ "sca", ETHERTYPE_SCA },
610+
{ "batadv", ETHERTYPE_BATMAN },
607611
{ (char *)0, 0 }
608612
};
609613

@@ -644,6 +648,60 @@ pcap_nametollc(const char *s)
644648
return PROTO_UNDEF;
645649
}
646650

651+
/* Static data base of batman-adv v14 packet type values. */
652+
static struct eproto batadv_type_db_v14[] = {
653+
{ "iv_ogm", BATADV_LEGACY_IV_OGM },
654+
{ "icmp", BATADV_LEGACY_ICMP },
655+
{ "unicast", BATADV_LEGACY_UNICAST },
656+
{ "bcast", BATADV_LEGACY_BCAST },
657+
{ "vis", BATADV_LEGACY_VIS },
658+
{ "unicast_frag", BATADV_LEGACY_UNICAST_FRAG },
659+
{ "tt_query", BATADV_LEGACY_TT_QUERY },
660+
{ "roam_adv", BATADV_LEGACY_ROAM_ADV },
661+
{ "unicast_4addr", BATADV_LEGACY_UNICAST_4ADDR },
662+
{ "coded", BATADV_LEGACY_CODED },
663+
{ (char *)0, 0 }
664+
};
665+
666+
int pcap_nametobatadvtype_v14(const char *s)
667+
{
668+
struct eproto *p = batadv_type_db_v14;
669+
670+
while (p->s != 0) {
671+
if (strcmp(p->s, s) == 0)
672+
return p->p;
673+
p += 1;
674+
}
675+
return PROTO_UNDEF;
676+
}
677+
678+
/* Static data base of batman-adv v15 packet type values. */
679+
static struct eproto batadv_type_db_v15[] = {
680+
{ "iv_ogm", BATADV_IV_OGM },
681+
{ "bcast", BATADV_BCAST },
682+
{ "coded", BATADV_CODED },
683+
{ "elp", BATADV_ELP },
684+
{ "ogm2", BATADV_OGM2 },
685+
{ "unicast", BATADV_UNICAST },
686+
{ "unicast_frag", BATADV_UNICAST_FRAG },
687+
{ "unicast_4addr", BATADV_UNICAST_4ADDR },
688+
{ "icmp", BATADV_ICMP },
689+
{ "unicast_tvlv", BATADV_UNICAST_TVLV },
690+
{ (char *)0, 0 }
691+
};
692+
693+
int pcap_nametobatadvtype_v15(const char *s)
694+
{
695+
struct eproto *p = batadv_type_db_v15;
696+
697+
while (p->s != 0) {
698+
if (strcmp(p->s, s) == 0)
699+
return p->p;
700+
p += 1;
701+
}
702+
return PROTO_UNDEF;
703+
}
704+
647705
/* Hex digit to 8-bit unsigned integer. */
648706
static inline u_char
649707
xdtoi(u_char c)

0 commit comments

Comments
 (0)