Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
0ca743a5 PNA |
2 | #ifndef _NF_TABLES_IPV4_H_ |
3 | #define _NF_TABLES_IPV4_H_ | |
4 | ||
5 | #include <net/netfilter/nf_tables.h> | |
6 | #include <net/ip.h> | |
7 | ||
f06ad944 | 8 | static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt) |
0ca743a5 PNA |
9 | { |
10 | struct iphdr *ip; | |
11 | ||
0ca743a5 | 12 | ip = ip_hdr(pkt->skb); |
b5bdc6f9 | 13 | pkt->flags = NFT_PKTINFO_L4PROTO; |
4566bf27 | 14 | pkt->tprot = ip->protocol; |
897389de FW |
15 | pkt->thoff = ip_hdrlen(pkt->skb); |
16 | pkt->fragoff = ntohs(ip->frag_off) & IP_OFFSET; | |
0ca743a5 PNA |
17 | } |
18 | ||
f06ad944 | 19 | static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt) |
ddc8b602 PNA |
20 | { |
21 | struct iphdr *iph, _iph; | |
22 | u32 len, thoff; | |
23 | ||
f06ad944 FW |
24 | iph = skb_header_pointer(pkt->skb, skb_network_offset(pkt->skb), |
25 | sizeof(*iph), &_iph); | |
ddc8b602 PNA |
26 | if (!iph) |
27 | return -1; | |
28 | ||
ddc8b602 PNA |
29 | if (iph->ihl < 5 || iph->version != 4) |
30 | return -1; | |
31 | ||
32 | len = ntohs(iph->tot_len); | |
33 | thoff = iph->ihl * 4; | |
f06ad944 | 34 | if (pkt->skb->len < len) |
ddc8b602 PNA |
35 | return -1; |
36 | else if (len < thoff) | |
37 | return -1; | |
38 | ||
b5bdc6f9 | 39 | pkt->flags = NFT_PKTINFO_L4PROTO; |
ddc8b602 | 40 | pkt->tprot = iph->protocol; |
897389de FW |
41 | pkt->thoff = thoff; |
42 | pkt->fragoff = ntohs(iph->frag_off) & IP_OFFSET; | |
ddc8b602 PNA |
43 | |
44 | return 0; | |
45 | } | |
46 | ||
f06ad944 | 47 | static inline void nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt) |
ddc8b602 | 48 | { |
f06ad944 FW |
49 | if (__nft_set_pktinfo_ipv4_validate(pkt) < 0) |
50 | nft_set_pktinfo_unspec(pkt); | |
ddc8b602 PNA |
51 | } |
52 | ||
f06ad944 | 53 | static inline int nft_set_pktinfo_ipv4_ingress(struct nft_pktinfo *pkt) |
d3519cb8 PNA |
54 | { |
55 | struct iphdr *iph; | |
56 | u32 len, thoff; | |
57 | ||
f06ad944 | 58 | if (!pskb_may_pull(pkt->skb, sizeof(*iph))) |
d3519cb8 PNA |
59 | return -1; |
60 | ||
f06ad944 | 61 | iph = ip_hdr(pkt->skb); |
d3519cb8 PNA |
62 | if (iph->ihl < 5 || iph->version != 4) |
63 | goto inhdr_error; | |
64 | ||
65 | len = ntohs(iph->tot_len); | |
66 | thoff = iph->ihl * 4; | |
f06ad944 | 67 | if (pkt->skb->len < len) { |
d3519cb8 PNA |
68 | __IP_INC_STATS(nft_net(pkt), IPSTATS_MIB_INTRUNCATEDPKTS); |
69 | return -1; | |
70 | } else if (len < thoff) { | |
71 | goto inhdr_error; | |
72 | } | |
73 | ||
b5bdc6f9 | 74 | pkt->flags = NFT_PKTINFO_L4PROTO; |
d3519cb8 | 75 | pkt->tprot = iph->protocol; |
897389de FW |
76 | pkt->thoff = thoff; |
77 | pkt->fragoff = ntohs(iph->frag_off) & IP_OFFSET; | |
d3519cb8 PNA |
78 | |
79 | return 0; | |
80 | ||
81 | inhdr_error: | |
82 | __IP_INC_STATS(nft_net(pkt), IPSTATS_MIB_INHDRERRORS); | |
83 | return -1; | |
84 | } | |
b5bdc6f9 | 85 | |
0ca743a5 | 86 | #endif |