Skip to content

Commit c247897

Browse files
committed
netfilter: nft_payload: access GRE payload via inner offset
Parse GRE v0 packets to properly set up inner offset, this allow for matching on inner headers. Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent d037abc commit c247897

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

net/netfilter/nft_payload.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
/* For layer 4 checksum field offset. */
2020
#include <linux/tcp.h>
2121
#include <linux/udp.h>
22+
#include <net/gre.h>
2223
#include <linux/icmpv6.h>
2324
#include <linux/ip.h>
2425
#include <linux/ipv6.h>
@@ -100,6 +101,37 @@ static int __nft_payload_inner_offset(struct nft_pktinfo *pkt)
100101
pkt->inneroff = thoff + __tcp_hdrlen(th);
101102
}
102103
break;
104+
case IPPROTO_GRE: {
105+
u32 offset = sizeof(struct gre_base_hdr), version;
106+
struct gre_base_hdr *gre, _gre;
107+
108+
gre = skb_header_pointer(pkt->skb, thoff, sizeof(_gre), &_gre);
109+
if (!gre)
110+
return -1;
111+
112+
version = gre->flags & GRE_VERSION;
113+
switch (version) {
114+
case GRE_VERSION_0:
115+
if (gre->flags & GRE_ROUTING)
116+
return -1;
117+
118+
if (gre->flags & GRE_CSUM) {
119+
offset += sizeof_field(struct gre_full_hdr, csum) +
120+
sizeof_field(struct gre_full_hdr, reserved1);
121+
}
122+
if (gre->flags & GRE_KEY)
123+
offset += sizeof_field(struct gre_full_hdr, key);
124+
125+
if (gre->flags & GRE_SEQ)
126+
offset += sizeof_field(struct gre_full_hdr, seq);
127+
break;
128+
default:
129+
return -1;
130+
}
131+
132+
pkt->inneroff = thoff + offset;
133+
}
134+
break;
103135
default:
104136
return -1;
105137
}

0 commit comments

Comments
 (0)