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
---
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(-)
diff --git a/include/headers.h b/include/headers.h
index 3d564debf8b0..759f93bf8c7a 100644
--- a/include/headers.h
+++ b/include/headers.h
@@ -78,6 +78,18 @@ struct sctphdr {
uint32_tchecksum;
};
+struct arp_hdr {
+ uint16_thtype;
+ uint16_tptype;
+ uint8_t hlen;
+ uint8_t plen;
+ uint16_toper;
+ uint8_t sha[6];
+ uint32_tspa;
+ uint8_t tha[6];
+ uint32_ttpa;
+} __attribute__((__packed__));
+
struct ipv6hdr {
uint8_t version:4,
priority:4;
diff --git a/include/proto.h b/include/proto.h
index 9a9f9255f047..b097e8fcbc2b 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -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 {
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 34202b0415ec..e94282a43615 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -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
diff --git a/src/proto.c b/src/proto.c
index d178bf39ea90..d52f11ce6f30 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -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", _type,
ar_pro),
- [ARPHDR_HLN]= ARPHDR_FIELD("hlen", ar_hln),
- [ARPHDR_PLN]= ARPHDR_FIELD("plen", ar_pln),
- [ARPHDR_OP] = ARPHDR_TYPE("operation", _type,
ar_op),
+ [ARPHDR_HRD]= ARPHDR_FIELD("htype", htype),
+ [ARPHDR_PRO]= ARPHDR_TYPE("ptype", _type,
ptype),
+ [ARPHDR_HLN]= ARPHDR_FIELD("hlen", hlen),
+ [ARPHDR_PLN]= ARPHDR_FIELD("plen", plen),
+ [ARPHDR_OP] = ARPHDR_TYPE("operation", _type,
oper),
+ [ARPHDR_ETHER_SADDR]= ARPHDR_TYPE("ether-saddr",
_type, sha),
+ [ARPHDR_ETHER_DADDR]= ARPHDR_TYPE("ether-daddr",
_type, tha),
+ [ARPHDR_IP_SADDR] = ARPHDR_TYPE("ip-saddr", _type,
spa),
+ [ARPHDR_IP_DADDR] = ARPHDR_TYPE("ip-daddr", _type,
tpa),
},
.format = {
.filter = (1 << ARPHDR_HRD) | (1 << ARPHDR_PRO) |
- (1 << ARPHDR_HLN) | (1 <<