@@ -78,6 +78,18 @@ struct sctphdr {
uint32_t checksum;
};
+struct arp_hdr {
+ uint16_t htype;
+ uint16_t ptype;
+ uint8_t hlen;
+ uint8_t plen;
+ uint16_t oper;
+ uint8_t sha[6];
+ uint32_t spa;
+ uint8_t tha[6];
+ uint32_t tpa;
+} __attribute__((__packed__));
+
struct ipv6hdr {
uint8_t version:4,
priority:4;
@@ -182,6 +182,10 @@ enum arp_hdr_fields {
ARPHDR_HLN,
ARPHDR_PLN,
ARPHDR_OP,
+ ARPHDR_IP_SADDR,
+ ARPHDR_IP_DADDR,
+ ARPHDR_ETHER_SADDR,
+ ARPHDR_ETHER_DADDR,
};
enum ip_hdr_fields {
@@ -296,6 +296,10 @@ int nft_lex(void *, void *, void *);
%token HLEN "hlen"
%token PLEN "plen"
%token OPERATION "operation"
+%token ETHER_SADDR "ether-saddr"
+%token ETHER_DADDR "ether-daddr"
+%token IP_SADDR "ip-saddr"
+%token IP_DADDR "ip-daddr"
%token IP "ip"
%token HDRVERSION "version"
@@ -4204,6 +4208,10 @@ arp_hdr_field : HTYPE { $$ = ARPHDR_HRD; }
| HLEN { $$ = ARPHDR_HLN; }
| PLEN { $$ = ARPHDR_PLN; }
| OPERATION { $$ = ARPHDR_OP; }
+ | ETHER_SADDR { $$ = ARPHDR_ETHER_SADDR; }
+ | ETHER_DADDR { $$ = ARPHDR_ETHER_DADDR; }
+ | IP_SADDR { $$ = ARPHDR_IP_SADDR; }
+ | IP_DADDR { $$ = ARPHDR_IP_DADDR; }
;
ip_hdr_expr : IP ip_hdr_field
@@ -822,23 +822,29 @@ const struct datatype arpop_type = {
};
#define ARPHDR_TYPE(__name, __type, __member) \
- HDR_TYPE(__name, __type, struct arphdr, __member)
+ HDR_TYPE(__name, __type, struct arp_hdr, __member)
#define ARPHDR_FIELD(__name, __member) \
- HDR_FIELD(__name, struct arphdr, __member)
+ HDR_FIELD(__name, struct arp_hdr, __member)
const struct proto_desc proto_arp = {
.name = "arp",
.base = PROTO_BASE_NETWORK_HDR,
.templates = {
- [ARPHDR_HRD] = ARPHDR_FIELD("htype", ar_hrd),
- [ARPHDR_PRO] = ARPHDR_TYPE("ptype", ðertype_type, ar_pro),
- [ARPHDR_HLN] = ARPHDR_FIELD("hlen", ar_hln),
- [ARPHDR_PLN] = ARPHDR_FIELD("plen", ar_pln),
- [ARPHDR_OP] = ARPHDR_TYPE("operation", &arpop_type, ar_op),
+ [ARPHDR_HRD] = ARPHDR_FIELD("htype", htype),
+ [ARPHDR_PRO] = ARPHDR_TYPE("ptype", ðertype_type, ptype),
+ [ARPHDR_HLN] = ARPHDR_FIELD("hlen", hlen),
+ [ARPHDR_PLN] = ARPHDR_FIELD("plen", plen),
+ [ARPHDR_OP] = ARPHDR_TYPE("operation", &arpop_type, oper),
+ [ARPHDR_ETHER_SADDR] = ARPHDR_TYPE("ether-saddr", ðeraddr_type, sha),
+ [ARPHDR_ETHER_DADDR] = ARPHDR_TYPE("ether-daddr", ðeraddr_type, tha),
+ [ARPHDR_IP_SADDR] = ARPHDR_TYPE("ip-saddr", &ipaddr_type, spa),
+ [ARPHDR_IP_DADDR] = ARPHDR_TYPE("ip-daddr", &ipaddr_type, tpa),
},
.format = {
.filter = (1 << ARPHDR_HRD) | (1 << ARPHDR_PRO) |
- (1 << ARPHDR_HLN) | (1 << ARPHDR_PLN),
+ (1 << ARPHDR_HLN) | (1 << ARPHDR_PLN) |
+ (1 << ARPHDR_ETHER_SADDR) | (1 << ARPHDR_ETHER_DADDR) |
+ (1 << ARPHDR_IP_SADDR) | (1 << ARPHDR_IP_DADDR),
},
};
@@ -389,6 +389,10 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"hlen" { return HLEN; }
"plen" { return PLEN; }
"operation" { return OPERATION; }
+"ip-saddr" { return IP_SADDR; }
+"ip-daddr" { return IP_DADDR; }
+"ether-saddr" { return ETHER_SADDR; }
+"ether-daddr" { return ETHER_DADDR; }
"ip" { return IP; }
"version" { return HDRVERSION; }
Add ip-saddr, ip-daddr, ether-saddr, ether-daddr for arp, eg. # nft add table arp x # nft add chain arp x y { type filter hook input priority 0\; } # nft add rule arp x y arp ip-saddr 192.168.2.1 counter Testing this: # ip neigh flush dev eth0 # ping 8.8.8.8 # nft list ruleset table arp x { chain y { type filter hook input priority filter; policy accept; arp ip-saddr 192.168.2.1 counter packets 1 bytes 46 } } Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> --- Documentation is still missing, and we should generate dependencies to restrict htype and ptype. include/headers.h | 12 ++++++++++++ include/proto.h | 4 ++++ src/parser_bison.y | 8 ++++++++ src/proto.c | 22 ++++++++++++++-------- src/scanner.l | 4 ++++ 5 files changed, 42 insertions(+), 8 deletions(-)