Skip to content

Commit 62133cb

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 09230c1 commit 62133cb

File tree

11 files changed

+459
-3
lines changed

11 files changed

+459
-3
lines changed

Makefile.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ PUBHDR = \
121121
HDR = $(PUBHDR) \
122122
arcnet.h \
123123
atmuni31.h \
124+
batadv_legacy_packet.h \
125+
batadv_packet.h \
124126
diag-control.h \
125127
ethertype.h \
126128
extract.h \

batadv_legacy_packet.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/* SPDX-License-Identifier: BSD-3 */
2+
/* Copyright (C) 2020 Linus Lüssing */
3+
4+
#ifndef _BATADV_LEGACY_PACKET_H_
5+
#define _BATADV_LEGACY_PACKET_H_
6+
7+
enum batadv_legacy_packettype {
8+
BATADV_LEGACY_IV_OGM = 0x01,
9+
BATADV_LEGACY_ICMP = 0x02,
10+
BATADV_LEGACY_UNICAST = 0x03,
11+
BATADV_LEGACY_BCAST = 0x04,
12+
BATADV_LEGACY_VIS = 0x05,
13+
BATADV_LEGACY_UNICAST_FRAG = 0x06,
14+
BATADV_LEGACY_TT_QUERY = 0x07,
15+
BATADV_LEGACY_ROAM_ADV = 0x08,
16+
BATADV_LEGACY_UNICAST_4ADDR = 0x09,
17+
BATADV_LEGACY_CODED = 0x0a,
18+
};
19+
20+
#define ETH_ALEN 6
21+
22+
struct batadv_legacy_unicast_packet {
23+
uint8_t packet_type;
24+
uint8_t version;
25+
uint8_t ttl;
26+
uint8_t ttvn;
27+
uint8_t dest[ETH_ALEN];
28+
};
29+
30+
struct batadv_legacy_unicast_4addr_packet {
31+
uint8_t packet_type;
32+
uint8_t version;
33+
uint8_t ttl;
34+
uint8_t src[ETH_ALEN];
35+
uint8_t subtype;
36+
uint8_t reserved;
37+
};
38+
39+
struct batadv_legacy_unicast_frag_packet {
40+
uint8_t packet_type;
41+
uint8_t version;
42+
uint8_t ttl;
43+
uint8_t ttvn;
44+
uint8_t dest[ETH_ALEN];
45+
uint8_t flags;
46+
uint8_t align;
47+
uint8_t orig[ETH_ALEN];
48+
uint8_t seqno[2]; /* 2-byte integral value */
49+
};
50+
51+
struct batadv_legacy_bcast_packet {
52+
uint8_t packet_type;
53+
uint8_t version;
54+
uint8_t ttl;
55+
uint8_t reserved;
56+
uint8_t seqno[4]; /* 4-byte integral value */
57+
uint8_t orig[ETH_ALEN];
58+
};
59+
60+
struct batadv_legacy_coded_packet {
61+
uint8_t packet_type;
62+
uint8_t version;
63+
uint8_t ttl;
64+
uint8_t first_ttvn;
65+
uint8_t first_source[ETH_ALEN];
66+
uint8_t first_orig_dest[ETH_ALEN];
67+
uint8_t first_crc[4]; /* 4-byte integral value */
68+
uint8_t second_ttl;
69+
uint8_t second_ttvn;
70+
uint8_t second_dest[ETH_ALEN];
71+
uint8_t second_source[ETH_ALEN];
72+
uint8_t second_orig_dest[ETH_ALEN];
73+
uint8_t second_crc[4]; /* 4-byte integral value */
74+
uint8_t coded_len[2]; /* 2-byte integral value */
75+
};
76+
77+
#endif /* _BATADV_LEGACY_PACKET_H_ */

batadv_packet.h

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/* SPDX-License-Identifier: BSD-3 */
2+
/* Copyright (C) 2024 Linus Lüssing */
3+
4+
#ifndef _BATADV_PACKET_H_
5+
#define _BATADV_PACKET_H_
6+
7+
/* For the definitive and most recent packet format definition,
8+
* see the batadv_packet.h in the Linux kernel.
9+
*/
10+
11+
enum batadv_packettype {
12+
BATADV_IV_OGM = 0x00,
13+
BATADV_BCAST = 0x01,
14+
BATADV_CODED = 0x02,
15+
BATADV_ELP = 0x03,
16+
BATADV_OGM2 = 0x04,
17+
BATADV_MCAST = 0x05,
18+
BATADV_UNICAST = 0x40,
19+
BATADV_UNICAST_FRAG = 0x41,
20+
BATADV_UNICAST_4ADDR = 0x42,
21+
BATADV_ICMP = 0x43,
22+
BATADV_UNICAST_TVLV = 0x44,
23+
};
24+
25+
#define ETH_ALEN 6
26+
27+
struct batadv_unicast_packet {
28+
uint8_t packet_type;
29+
uint8_t version;
30+
uint8_t ttl;
31+
uint8_t ttvn;
32+
uint8_t dest[ETH_ALEN];
33+
};
34+
35+
struct batadv_unicast_4addr_packet {
36+
struct batadv_unicast_packet u;
37+
uint8_t src[ETH_ALEN];
38+
uint8_t subtype;
39+
uint8_t reserved;
40+
};
41+
42+
struct batadv_frag_packet {
43+
uint8_t packet_type;
44+
uint8_t version;
45+
uint8_t ttl;
46+
uint8_t num_pri; /* number and priority */
47+
uint8_t dest[ETH_ALEN];
48+
uint8_t orig[ETH_ALEN];
49+
uint8_t seqno[2]; /* 2-byte integral value */
50+
uint8_t total_size[2]; /* 2-byte integral value */
51+
};
52+
53+
struct batadv_bcast_packet {
54+
uint8_t packet_type;
55+
uint8_t version;
56+
uint8_t ttl;
57+
uint8_t reserved;
58+
uint8_t seqno[4]; /* 4-byte integral value */
59+
uint8_t orig[ETH_ALEN];
60+
};
61+
62+
struct batadv_coded_packet {
63+
uint8_t packet_type;
64+
uint8_t version;
65+
uint8_t ttl;
66+
uint8_t first_ttvn;
67+
uint8_t first_source[ETH_ALEN];
68+
uint8_t first_orig_dest[ETH_ALEN];
69+
uint8_t first_crc[4]; /* 4-byte integral value */
70+
uint8_t second_ttl;
71+
uint8_t second_ttvn;
72+
uint8_t second_dest[ETH_ALEN];
73+
uint8_t second_source[ETH_ALEN];
74+
uint8_t second_orig_dest[ETH_ALEN];
75+
uint8_t second_crc[4]; /* 4-byte integral value */
76+
uint8_t coded_len[2]; /* 2-byte integral value */
77+
};
78+
79+
#endif /* _BATADV_PACKET_H_ */

ethertype.h

Lines changed: 3 additions & 0 deletions
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

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
#include "sunatmpos.h"
5555
#include "pflog.h"
5656
#include "ppp.h"
57+
#include "batadv_packet.h"
58+
#include "batadv_legacy_packet.h"
5759
#include "pcap/sll.h"
5860
#include "pcap/ipnet.h"
5961
#include "arcnet.h"
@@ -9951,6 +9953,168 @@ gen_vxlan(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni)
99519953
return b1;
99529954
}
99539955

9956+
static struct block *
9957+
gen_batadv_check_version(compiler_state_t *cstate, struct block *b0, bpf_u_int32 version)
9958+
{
9959+
struct block *b1;
9960+
9961+
if (version > UINT8_MAX)
9962+
bpf_error(cstate,
9963+
"batman-adv compatibility version number %u unsupported",
9964+
version);
9965+
9966+
b1 = gen_cmp(cstate, OR_LINKPL, 1, BPF_B, version);
9967+
gen_and(b0, b1);
9968+
9969+
return b1;
9970+
}
9971+
9972+
static struct block *
9973+
gen_batadv_check_type(compiler_state_t *cstate, struct block *b0,
9974+
bpf_u_int32 version, bpf_u_int32 type)
9975+
{
9976+
struct block *b1;
9977+
9978+
switch (version) {
9979+
case 14:
9980+
case 15:
9981+
if (type > UINT8_MAX)
9982+
bpf_error(cstate,
9983+
"batman-adv packet type %u unsupported for compatibility version %u",
9984+
type, version);
9985+
9986+
b1 = gen_cmp(cstate, OR_LINKPL, 0, BPF_B, type);
9987+
gen_and(b0, b1);
9988+
b0 = b1;
9989+
9990+
break;
9991+
default:
9992+
bpf_error(cstate,
9993+
"batman-adv compatibility version number %u unsupported",
9994+
version);
9995+
}
9996+
9997+
return b0;
9998+
}
9999+
10000+
10001+
static void gen_batadv_push_offset(compiler_state_t *cstate, u_int offset)
10002+
{
10003+
PUSH_LINKHDR(cstate, DLT_EN10MB, cstate->off_linkpl.is_variable,
10004+
cstate->off_linkpl.constant_part + cstate->off_nl + offset,
10005+
cstate->off_linkpl.reg);
10006+
10007+
cstate->off_linktype.constant_part += cstate->off_linkhdr.constant_part;
10008+
cstate->off_linkpl.constant_part += cstate->off_linkhdr.constant_part;
10009+
10010+
cstate->off_nl = 0;
10011+
cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
10012+
}
10013+
10014+
static void
10015+
gen_batadv_offsets_v14(compiler_state_t *cstate, bpf_u_int32 type)
10016+
{
10017+
size_t offset;
10018+
10019+
switch (type) {
10020+
case BATADV_LEGACY_UNICAST: /* 0x03 */
10021+
offset = sizeof(struct batadv_legacy_unicast_packet);
10022+
break;
10023+
case BATADV_LEGACY_BCAST: /* 0x04 */
10024+
offset = sizeof(struct batadv_legacy_bcast_packet);
10025+
break;
10026+
case BATADV_LEGACY_UNICAST_FRAG: /* 0x06 */
10027+
offset = sizeof(struct batadv_legacy_unicast_frag_packet);
10028+
break;
10029+
case BATADV_LEGACY_UNICAST_4ADDR: /* 0x09 */
10030+
offset = sizeof(struct batadv_legacy_unicast_4addr_packet);
10031+
break;
10032+
case BATADV_LEGACY_CODED: /* 0x0a */
10033+
offset = sizeof(struct batadv_legacy_coded_packet);
10034+
break;
10035+
default:
10036+
offset = 0;
10037+
}
10038+
10039+
if (offset)
10040+
gen_batadv_push_offset(cstate, (u_int)offset);
10041+
}
10042+
10043+
static void
10044+
gen_batadv_offsets_v15(compiler_state_t *cstate, bpf_u_int32 type)
10045+
{
10046+
size_t offset;
10047+
10048+
switch (type) {
10049+
case BATADV_BCAST: /* 0x01 */
10050+
offset = sizeof(struct batadv_bcast_packet);
10051+
break;
10052+
case BATADV_CODED: /* 0x02 */
10053+
offset = sizeof(struct batadv_coded_packet);
10054+
break;
10055+
case BATADV_UNICAST: /* 0x40 */
10056+
offset = sizeof(struct batadv_unicast_packet);
10057+
break;
10058+
case BATADV_UNICAST_FRAG: /* 0x41 */
10059+
offset = sizeof(struct batadv_frag_packet);
10060+
break;
10061+
case BATADV_UNICAST_4ADDR: /* 0x42 */
10062+
offset = sizeof(struct batadv_unicast_4addr_packet);
10063+
break;
10064+
case BATADV_MCAST: /* 0x05 */
10065+
/* unsupported for now, needs variable offset to
10066+
* take tvlv_len into account
10067+
*/
10068+
/* fall through */
10069+
default:
10070+
offset = 0;
10071+
}
10072+
10073+
if (offset)
10074+
gen_batadv_push_offset(cstate, (u_int)offset);
10075+
}
10076+
10077+
static void
10078+
gen_batadv_offsets(compiler_state_t *cstate, bpf_u_int32 version, bpf_u_int32 type)
10079+
{
10080+
switch (version) {
10081+
case 14:
10082+
gen_batadv_offsets_v14(cstate, type);
10083+
break;
10084+
case 15:
10085+
gen_batadv_offsets_v15(cstate, type);
10086+
break;
10087+
default:
10088+
break;
10089+
}
10090+
}
10091+
10092+
struct block *
10093+
gen_batadv(compiler_state_t *cstate, bpf_u_int32 version, int has_version,
10094+
bpf_u_int32 type, int has_type)
10095+
{
10096+
struct block *b0;
10097+
10098+
/*
10099+
* Catch errors reported by us and routines below us, and return NULL
10100+
* on an error.
10101+
*/
10102+
if (setjmp(cstate->top_ctx))
10103+
return (NULL);
10104+
10105+
b0 = gen_linktype(cstate, ETHERTYPE_BATMAN);
10106+
10107+
if (has_version)
10108+
b0 = gen_batadv_check_version(cstate, b0, version);
10109+
10110+
if (has_type) {
10111+
b0 = gen_batadv_check_type(cstate, b0, version, type);
10112+
gen_batadv_offsets(cstate, version, type);
10113+
}
10114+
10115+
return b0;
10116+
}
10117+
995410118
/* Check that the encapsulated frame has a link layer header
995510119
* for Ethernet filters. */
995610120
static struct block *

gencode.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,9 @@ struct block *gen_pppoes(compiler_state_t *, bpf_u_int32, int);
359359
struct block *gen_geneve(compiler_state_t *, bpf_u_int32, int);
360360
struct block *gen_vxlan(compiler_state_t *, bpf_u_int32, int);
361361

362+
struct block *gen_batadv(compiler_state_t *, bpf_u_int32, int,
363+
bpf_u_int32, int);
364+
362365
struct block *gen_atmfield_code(compiler_state_t *, int, bpf_u_int32,
363366
int, int);
364367
struct block *gen_atmtype_abbrev(compiler_state_t *, int);

0 commit comments

Comments
 (0)