1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * xfrm4_input.c |
4 | * |
5 | * Changes: |
6 | * YOSHIFUJI Hideaki @USAGI |
7 | * Split up af-specific portion |
8 | * Derek Atkins <derek@ihtfp.com> |
9 | * Add Encapsulation support |
10 | * |
11 | */ |
12 | |
13 | #include <linux/slab.h> |
14 | #include <linux/module.h> |
15 | #include <linux/string.h> |
16 | #include <linux/netfilter.h> |
17 | #include <linux/netfilter_ipv4.h> |
18 | #include <net/ip.h> |
19 | #include <net/xfrm.h> |
20 | #include <net/protocol.h> |
21 | #include <net/gro.h> |
22 | |
23 | static int xfrm4_rcv_encap_finish2(struct net *net, struct sock *sk, |
24 | struct sk_buff *skb) |
25 | { |
26 | return dst_input(skb); |
27 | } |
28 | |
29 | static inline int xfrm4_rcv_encap_finish(struct net *net, struct sock *sk, |
30 | struct sk_buff *skb) |
31 | { |
32 | if (!skb_dst(skb)) { |
33 | const struct iphdr *iph = ip_hdr(skb); |
34 | |
35 | if (ip_route_input_noref(skb, dst: iph->daddr, src: iph->saddr, |
36 | tos: iph->tos, devin: skb->dev)) |
37 | goto drop; |
38 | } |
39 | |
40 | if (xfrm_trans_queue(skb, finish: xfrm4_rcv_encap_finish2)) |
41 | goto drop; |
42 | |
43 | return 0; |
44 | drop: |
45 | kfree_skb(skb); |
46 | return NET_RX_DROP; |
47 | } |
48 | |
49 | int xfrm4_transport_finish(struct sk_buff *skb, int async) |
50 | { |
51 | struct xfrm_offload *xo = xfrm_offload(skb); |
52 | struct iphdr *iph = ip_hdr(skb); |
53 | |
54 | iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol; |
55 | |
56 | #ifndef CONFIG_NETFILTER |
57 | if (!async) |
58 | return -iph->protocol; |
59 | #endif |
60 | |
61 | __skb_push(skb, len: skb->data - skb_network_header(skb)); |
62 | iph->tot_len = htons(skb->len); |
63 | ip_send_check(ip: iph); |
64 | |
65 | if (xo && (xo->flags & XFRM_GRO)) { |
66 | skb_mac_header_rebuild(skb); |
67 | skb_reset_transport_header(skb); |
68 | return 0; |
69 | } |
70 | |
71 | NF_HOOK(pf: NFPROTO_IPV4, hook: NF_INET_PRE_ROUTING, |
72 | net: dev_net(dev: skb->dev), NULL, skb, in: skb->dev, NULL, |
73 | okfn: xfrm4_rcv_encap_finish); |
74 | return 0; |
75 | } |
76 | |
77 | static int __xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb, bool pull) |
78 | { |
79 | struct udp_sock *up = udp_sk(sk); |
80 | struct udphdr *uh; |
81 | struct iphdr *iph; |
82 | int iphlen, len; |
83 | __u8 *udpdata; |
84 | __be32 *udpdata32; |
85 | u16 encap_type; |
86 | |
87 | encap_type = READ_ONCE(up->encap_type); |
88 | /* if this is not encapsulated socket, then just return now */ |
89 | if (!encap_type) |
90 | return 1; |
91 | |
92 | /* If this is a paged skb, make sure we pull up |
93 | * whatever data we need to look at. */ |
94 | len = skb->len - sizeof(struct udphdr); |
95 | if (!pskb_may_pull(skb, len: sizeof(struct udphdr) + min(len, 8))) |
96 | return 1; |
97 | |
98 | /* Now we can get the pointers */ |
99 | uh = udp_hdr(skb); |
100 | udpdata = (__u8 *)uh + sizeof(struct udphdr); |
101 | udpdata32 = (__be32 *)udpdata; |
102 | |
103 | switch (encap_type) { |
104 | default: |
105 | case UDP_ENCAP_ESPINUDP: |
106 | /* Check if this is a keepalive packet. If so, eat it. */ |
107 | if (len == 1 && udpdata[0] == 0xff) { |
108 | return -EINVAL; |
109 | } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { |
110 | /* ESP Packet without Non-ESP header */ |
111 | len = sizeof(struct udphdr); |
112 | } else |
113 | /* Must be an IKE packet.. pass it through */ |
114 | return 1; |
115 | break; |
116 | case UDP_ENCAP_ESPINUDP_NON_IKE: |
117 | /* Check if this is a keepalive packet. If so, eat it. */ |
118 | if (len == 1 && udpdata[0] == 0xff) { |
119 | return -EINVAL; |
120 | } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && |
121 | udpdata32[0] == 0 && udpdata32[1] == 0) { |
122 | |
123 | /* ESP Packet with Non-IKE marker */ |
124 | len = sizeof(struct udphdr) + 2 * sizeof(u32); |
125 | } else |
126 | /* Must be an IKE packet.. pass it through */ |
127 | return 1; |
128 | break; |
129 | } |
130 | |
131 | /* At this point we are sure that this is an ESPinUDP packet, |
132 | * so we need to remove 'len' bytes from the packet (the UDP |
133 | * header and optional ESP marker bytes) and then modify the |
134 | * protocol to ESP, and then call into the transform receiver. |
135 | */ |
136 | if (skb_unclone(skb, GFP_ATOMIC)) |
137 | return -EINVAL; |
138 | |
139 | /* Now we can update and verify the packet length... */ |
140 | iph = ip_hdr(skb); |
141 | iphlen = iph->ihl << 2; |
142 | iph->tot_len = htons(ntohs(iph->tot_len) - len); |
143 | if (skb->len < iphlen + len) { |
144 | /* packet is too small!?! */ |
145 | return -EINVAL; |
146 | } |
147 | |
148 | /* pull the data buffer up to the ESP header and set the |
149 | * transport header to point to ESP. Keep UDP on the stack |
150 | * for later. |
151 | */ |
152 | if (pull) { |
153 | __skb_pull(skb, len); |
154 | skb_reset_transport_header(skb); |
155 | } else { |
156 | skb_set_transport_header(skb, offset: len); |
157 | } |
158 | |
159 | /* process ESP */ |
160 | return 0; |
161 | } |
162 | |
163 | /* If it's a keepalive packet, then just eat it. |
164 | * If it's an encapsulated packet, then pass it to the |
165 | * IPsec xfrm input. |
166 | * Returns 0 if skb passed to xfrm or was dropped. |
167 | * Returns >0 if skb should be passed to UDP. |
168 | * Returns <0 if skb should be resubmitted (-ret is protocol) |
169 | */ |
170 | int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) |
171 | { |
172 | int ret; |
173 | |
174 | ret = __xfrm4_udp_encap_rcv(sk, skb, pull: true); |
175 | if (!ret) |
176 | return xfrm4_rcv_encap(skb, IPPROTO_ESP, spi: 0, |
177 | udp_sk(sk)->encap_type); |
178 | |
179 | if (ret < 0) { |
180 | kfree_skb(skb); |
181 | return 0; |
182 | } |
183 | |
184 | return ret; |
185 | } |
186 | EXPORT_SYMBOL(xfrm4_udp_encap_rcv); |
187 | |
188 | struct sk_buff *xfrm4_gro_udp_encap_rcv(struct sock *sk, struct list_head *head, |
189 | struct sk_buff *skb) |
190 | { |
191 | int offset = skb_gro_offset(skb); |
192 | const struct net_offload *ops; |
193 | struct sk_buff *pp = NULL; |
194 | int ret; |
195 | |
196 | offset = offset - sizeof(struct udphdr); |
197 | |
198 | if (!pskb_pull(skb, len: offset)) |
199 | return NULL; |
200 | |
201 | rcu_read_lock(); |
202 | ops = rcu_dereference(inet_offloads[IPPROTO_ESP]); |
203 | if (!ops || !ops->callbacks.gro_receive) |
204 | goto out; |
205 | |
206 | ret = __xfrm4_udp_encap_rcv(sk, skb, pull: false); |
207 | if (ret) |
208 | goto out; |
209 | |
210 | skb_push(skb, len: offset); |
211 | NAPI_GRO_CB(skb)->proto = IPPROTO_UDP; |
212 | |
213 | pp = call_gro_receive(cb: ops->callbacks.gro_receive, head, skb); |
214 | rcu_read_unlock(); |
215 | |
216 | return pp; |
217 | |
218 | out: |
219 | rcu_read_unlock(); |
220 | skb_push(skb, len: offset); |
221 | NAPI_GRO_CB(skb)->same_flow = 0; |
222 | NAPI_GRO_CB(skb)->flush = 1; |
223 | |
224 | return NULL; |
225 | } |
226 | EXPORT_SYMBOL(xfrm4_gro_udp_encap_rcv); |
227 | |
228 | int xfrm4_rcv(struct sk_buff *skb) |
229 | { |
230 | return xfrm4_rcv_spi(skb, nexthdr: ip_hdr(skb)->protocol, spi: 0); |
231 | } |
232 | EXPORT_SYMBOL(xfrm4_rcv); |
233 | |