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 <pa...@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(-)

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_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;
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", &ethertype_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", &ethertype_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", 
&etheraddr_type, sha),
+               [ARPHDR_ETHER_DADDR]    = ARPHDR_TYPE("ether-daddr", 
&etheraddr_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),
        },
 };
 
diff --git a/src/scanner.l b/src/scanner.l
index f96944e976b3..5221086e38e5 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -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; }
-- 
2.11.0

Reply via email to