summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2019-05-22 22:06:16 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2019-05-24 21:14:30 +0200
commit4b0f2a712b5792d2842d89fe68d4230e0eb05c7e (patch)
tree954a866715d95529e65f39c3ff90920973186ac1
parenteeda228c2d1719f5b6276b40ad14a5b3c3e88536 (diff)
src: support for arp sender and target ethernet and IPv4 addresses
# nft add table arp x # nft add chain arp x y { type filter hook input priority 0\; } # nft add rule arp x y arp saddr ip 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 saddr ip 192.168.2.1 counter packets 1 bytes 46 } } You can also specify hardware sender address, eg. # nft add rule arp x y arp saddr ether aa:bb:cc:aa:bb:cc drop counter Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--doc/payload-expression.txt14
-rw-r--r--include/headers.h12
-rw-r--r--include/proto.h4
-rw-r--r--src/parser_bison.y4
-rw-r--r--src/proto.c22
-rw-r--r--tests/py/arp/arp.t7
-rw-r--r--tests/py/arp/arp.t.payload21
-rw-r--r--tests/py/arp/arp.t.payload.netdev28
8 files changed, 102 insertions, 10 deletions
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt
index 7f3ca42d..ebbffe50 100644
--- a/doc/payload-expression.txt
+++ b/doc/payload-expression.txt
@@ -44,7 +44,7 @@ ether_type
ARP HEADER EXPRESSION
~~~~~~~~~~~~~~~~~~~~~
[verse]
-*arp* {*htype* | *ptype* | *hlen* | *plen* | *operation*}
+*arp* {*htype* | *ptype* | *hlen* | *plen* | *operation* | *saddr* { *ip* | *ether* } | *daddr* { *ip* | *ether* }
.ARP header expression
[options="header"]
@@ -65,6 +65,18 @@ integer (8 bit)
|operation|
Operation |
arp_op
+|saddr ether|
+Ethernet sender address|
+ether_addr
+|daddr ether|
+Ethernet target address|
+ether_addr
+|saddr ip|
+IPv4 sender address|
+ipv4_addr
+|daddr ip|
+IPv4 target address|
+ipv4_addr
|======================
IPV4 HEADER EXPRESSION
diff --git a/include/headers.h b/include/headers.h
index 3d564deb..759f93bf 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 99c57a79..92b25edb 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -182,6 +182,10 @@ enum arp_hdr_fields {
ARPHDR_HLN,
ARPHDR_PLN,
ARPHDR_OP,
+ ARPHDR_SADDR_ETHER,
+ ARPHDR_DADDR_ETHER,
+ ARPHDR_SADDR_IP,
+ ARPHDR_DADDR_IP,
};
enum ip_hdr_fields {
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 9e632c0d..8c8cd432 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -4243,6 +4243,10 @@ arp_hdr_field : HTYPE { $$ = ARPHDR_HRD; }
| HLEN { $$ = ARPHDR_HLN; }
| PLEN { $$ = ARPHDR_PLN; }
| OPERATION { $$ = ARPHDR_OP; }
+ | SADDR ETHER { $$ = ARPHDR_SADDR_ETHER; }
+ | DADDR ETHER { $$ = ARPHDR_DADDR_ETHER; }
+ | SADDR IP { $$ = ARPHDR_SADDR_IP; }
+ | DADDR IP { $$ = ARPHDR_DADDR_IP; }
;
ip_hdr_expr : IP ip_hdr_field
diff --git a/src/proto.c b/src/proto.c
index f68fb684..67e86f20 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -874,23 +874,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_SADDR_ETHER] = ARPHDR_TYPE("saddr ether", &etheraddr_type, sha),
+ [ARPHDR_DADDR_ETHER] = ARPHDR_TYPE("daddr ether", &etheraddr_type, tha),
+ [ARPHDR_SADDR_IP] = ARPHDR_TYPE("saddr ip", &ipaddr_type, spa),
+ [ARPHDR_DADDR_IP] = ARPHDR_TYPE("daddr ip", &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_SADDR_ETHER) | (1 << ARPHDR_DADDR_ETHER) |
+ (1 << ARPHDR_SADDR_IP) | (1 << ARPHDR_DADDR_IP),
},
};
diff --git a/tests/py/arp/arp.t b/tests/py/arp/arp.t
index d62cc546..86bab523 100644
--- a/tests/py/arp/arp.t
+++ b/tests/py/arp/arp.t
@@ -55,4 +55,9 @@ arp operation != inreply;ok
arp operation != nak;ok
arp operation != reply;ok
-meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566;ok;iifname "invalid" arp htype 1 arp ptype ip arp hlen 6 arp plen 4 @nh,192,32 3232272144 @nh,144,48 set 18838586676582
+arp saddr ip 1.2.3.4;ok
+arp daddr ip 4.3.2.1;ok
+arp saddr ether aa:bb:cc:aa:bb:cc;ok
+arp daddr ether aa:bb:cc:aa:bb:cc;ok
+
+meta iifname "invalid" arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566;ok;iifname "invalid" arp htype 1 arp ptype ip arp hlen 6 arp plen 4 arp daddr ip 192.168.143.16 arp daddr ether set 11:22:33:44:55:66
diff --git a/tests/py/arp/arp.t.payload b/tests/py/arp/arp.t.payload
index 33e73417..d36bef18 100644
--- a/tests/py/arp/arp.t.payload
+++ b/tests/py/arp/arp.t.payload
@@ -280,3 +280,24 @@ arp test-arp input
[ cmp eq reg 1 0x108fa8c0 ]
[ immediate reg 1 0x44332211 0x00006655 ]
[ payload write reg 1 => 6b @ network header + 18 csum_type 0 csum_off 0 csum_flags 0x0 ]
+
+# arp saddr ip 1.2.3.4
+arp test-arp input
+ [ payload load 4b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+
+# arp daddr ip 4.3.2.1
+arp test-arp input
+ [ payload load 4b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x01020304 ]
+
+# arp saddr ether aa:bb:cc:aa:bb:cc
+arp test-arp input
+ [ payload load 6b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0xaaccbbaa 0x0000ccbb ]
+
+# arp daddr ether aa:bb:cc:aa:bb:cc
+arp test-arp input
+ [ payload load 6b @ network header + 18 => reg 1 ]
+ [ cmp eq reg 1 0xaaccbbaa 0x0000ccbb ]
+
diff --git a/tests/py/arp/arp.t.payload.netdev b/tests/py/arp/arp.t.payload.netdev
index 4fcf3504..0146cf50 100644
--- a/tests/py/arp/arp.t.payload.netdev
+++ b/tests/py/arp/arp.t.payload.netdev
@@ -373,3 +373,31 @@ netdev test-netdev ingress
[ immediate reg 1 0x44332211 0x00006655 ]
[ payload write reg 1 => 6b @ network header + 18 csum_type 0 csum_off 0 csum_flags 0x0 ]
+# arp saddr ip 1.2.3.4
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 4b @ network header + 14 => reg 1 ]
+ [ cmp eq reg 1 0x04030201 ]
+
+# arp daddr ip 4.3.2.1
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 4b @ network header + 24 => reg 1 ]
+ [ cmp eq reg 1 0x01020304 ]
+
+# arp saddr ether aa:bb:cc:aa:bb:cc
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 6b @ network header + 8 => reg 1 ]
+ [ cmp eq reg 1 0xaaccbbaa 0x0000ccbb ]
+
+# arp daddr ether aa:bb:cc:aa:bb:cc
+netdev test-netdev ingress
+ [ meta load protocol => reg 1 ]
+ [ cmp eq reg 1 0x00000608 ]
+ [ payload load 6b @ network header + 18 => reg 1 ]
+ [ cmp eq reg 1 0xaaccbbaa 0x0000ccbb ]
+