]> Git Repo - J-linux.git/blob - net/ipv6/xfrm6_input.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / net / ipv6 / xfrm6_input.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * xfrm6_input.c: based on net/ipv4/xfrm4_input.c
4  *
5  * Authors:
6  *      Mitsuru KANDA @USAGI
7  *      Kazunori MIYAZAWA @USAGI
8  *      Kunihiro Ishiguro <[email protected]>
9  *      YOSHIFUJI Hideaki @USAGI
10  *              IPv6 support
11  */
12
13 #include <linux/module.h>
14 #include <linux/string.h>
15 #include <linux/netfilter.h>
16 #include <linux/netfilter_ipv6.h>
17 #include <net/ipv6.h>
18 #include <net/xfrm.h>
19 #include <net/protocol.h>
20 #include <net/gro.h>
21
22 int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi,
23                   struct ip6_tnl *t)
24 {
25         XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t;
26         XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
27         XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
28         return xfrm_input(skb, nexthdr, spi, 0);
29 }
30 EXPORT_SYMBOL(xfrm6_rcv_spi);
31
32 static int xfrm6_transport_finish2(struct net *net, struct sock *sk,
33                                    struct sk_buff *skb)
34 {
35         if (xfrm_trans_queue(skb, ip6_rcv_finish)) {
36                 kfree_skb(skb);
37                 return NET_RX_DROP;
38         }
39
40         return 0;
41 }
42
43 int xfrm6_transport_finish(struct sk_buff *skb, int async)
44 {
45         struct xfrm_offload *xo = xfrm_offload(skb);
46         int nhlen = -skb_network_offset(skb);
47
48         skb_network_header(skb)[IP6CB(skb)->nhoff] =
49                 XFRM_MODE_SKB_CB(skb)->protocol;
50
51 #ifndef CONFIG_NETFILTER
52         if (!async)
53                 return 1;
54 #endif
55
56         __skb_push(skb, nhlen);
57         ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
58         skb_postpush_rcsum(skb, skb_network_header(skb), nhlen);
59
60         if (xo && (xo->flags & XFRM_GRO)) {
61                 /* The full l2 header needs to be preserved so that re-injecting the packet at l2
62                  * works correctly in the presence of vlan tags.
63                  */
64                 skb_mac_header_rebuild_full(skb, xo->orig_mac_len);
65                 skb_reset_network_header(skb);
66                 skb_reset_transport_header(skb);
67                 return 0;
68         }
69
70         NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING,
71                 dev_net(skb->dev), NULL, skb, skb->dev, NULL,
72                 xfrm6_transport_finish2);
73         return 0;
74 }
75
76 static int __xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb, bool pull)
77 {
78         struct udp_sock *up = udp_sk(sk);
79         struct udphdr *uh;
80         struct ipv6hdr *ip6h;
81         int len;
82         int ip6hlen = sizeof(struct ipv6hdr);
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, 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         }
117
118         /* At this point we are sure that this is an ESPinUDP packet,
119          * so we need to remove 'len' bytes from the packet (the UDP
120          * header and optional ESP marker bytes) and then modify the
121          * protocol to ESP, and then call into the transform receiver.
122          */
123         if (skb_unclone(skb, GFP_ATOMIC))
124                 return -EINVAL;
125
126         /* Now we can update and verify the packet length... */
127         ip6h = ipv6_hdr(skb);
128         ip6h->payload_len = htons(ntohs(ip6h->payload_len) - len);
129         if (skb->len < ip6hlen + len) {
130                 /* packet is too small!?! */
131                 return -EINVAL;
132         }
133
134         /* pull the data buffer up to the ESP header and set the
135          * transport header to point to ESP.  Keep UDP on the stack
136          * for later.
137          */
138         if (pull) {
139                 __skb_pull(skb, len);
140                 skb_reset_transport_header(skb);
141         } else {
142                 skb_set_transport_header(skb, len);
143         }
144
145         /* process ESP */
146         return 0;
147 }
148
149 /* If it's a keepalive packet, then just eat it.
150  * If it's an encapsulated packet, then pass it to the
151  * IPsec xfrm input.
152  * Returns 0 if skb passed to xfrm or was dropped.
153  * Returns >0 if skb should be passed to UDP.
154  * Returns <0 if skb should be resubmitted (-ret is protocol)
155  */
156 int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
157 {
158         int ret;
159
160         if (skb->protocol == htons(ETH_P_IP))
161                 return xfrm4_udp_encap_rcv(sk, skb);
162
163         ret = __xfrm6_udp_encap_rcv(sk, skb, true);
164         if (!ret)
165                 return xfrm6_rcv_encap(skb, IPPROTO_ESP, 0,
166                                        udp_sk(sk)->encap_type);
167
168         if (ret < 0) {
169                 kfree_skb(skb);
170                 return 0;
171         }
172
173         return ret;
174 }
175
176 struct sk_buff *xfrm6_gro_udp_encap_rcv(struct sock *sk, struct list_head *head,
177                                         struct sk_buff *skb)
178 {
179         int offset = skb_gro_offset(skb);
180         const struct net_offload *ops;
181         struct sk_buff *pp = NULL;
182         int ret;
183
184         if (skb->protocol == htons(ETH_P_IP))
185                 return xfrm4_gro_udp_encap_rcv(sk, head, skb);
186
187         offset = offset - sizeof(struct udphdr);
188
189         if (!pskb_pull(skb, offset))
190                 return NULL;
191
192         rcu_read_lock();
193         ops = rcu_dereference(inet6_offloads[IPPROTO_ESP]);
194         if (!ops || !ops->callbacks.gro_receive)
195                 goto out;
196
197         ret = __xfrm6_udp_encap_rcv(sk, skb, false);
198         if (ret)
199                 goto out;
200
201         skb_push(skb, offset);
202         NAPI_GRO_CB(skb)->proto = IPPROTO_UDP;
203
204         pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
205         rcu_read_unlock();
206
207         return pp;
208
209 out:
210         rcu_read_unlock();
211         skb_push(skb, offset);
212         NAPI_GRO_CB(skb)->same_flow = 0;
213         NAPI_GRO_CB(skb)->flush = 1;
214
215         return NULL;
216 }
217
218 int xfrm6_rcv_tnl(struct sk_buff *skb, struct ip6_tnl *t)
219 {
220         return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
221                              0, t);
222 }
223 EXPORT_SYMBOL(xfrm6_rcv_tnl);
224
225 int xfrm6_rcv(struct sk_buff *skb)
226 {
227         return xfrm6_rcv_tnl(skb, NULL);
228 }
229 EXPORT_SYMBOL(xfrm6_rcv);
230 int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
231                      xfrm_address_t *saddr, u8 proto)
232 {
233         struct net *net = dev_net(skb->dev);
234         struct xfrm_state *x = NULL;
235         struct sec_path *sp;
236         int i = 0;
237
238         sp = secpath_set(skb);
239         if (!sp) {
240                 XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR);
241                 goto drop;
242         }
243
244         if (1 + sp->len == XFRM_MAX_DEPTH) {
245                 XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR);
246                 goto drop;
247         }
248
249         for (i = 0; i < 3; i++) {
250                 xfrm_address_t *dst, *src;
251
252                 switch (i) {
253                 case 0:
254                         dst = daddr;
255                         src = saddr;
256                         break;
257                 case 1:
258                         /* lookup state with wild-card source address */
259                         dst = daddr;
260                         src = (xfrm_address_t *)&in6addr_any;
261                         break;
262                 default:
263                         /* lookup state with wild-card addresses */
264                         dst = (xfrm_address_t *)&in6addr_any;
265                         src = (xfrm_address_t *)&in6addr_any;
266                         break;
267                 }
268
269                 x = xfrm_state_lookup_byaddr(net, skb->mark, dst, src, proto, AF_INET6);
270                 if (!x)
271                         continue;
272
273                 if (unlikely(x->dir && x->dir != XFRM_SA_DIR_IN)) {
274                         XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEDIRERROR);
275                         xfrm_state_put(x);
276                         x = NULL;
277                         continue;
278                 }
279
280                 spin_lock(&x->lock);
281
282                 if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) &&
283                     likely(x->km.state == XFRM_STATE_VALID) &&
284                     !xfrm_state_check_expire(x)) {
285                         spin_unlock(&x->lock);
286                         if (x->type->input(x, skb) > 0) {
287                                 /* found a valid state */
288                                 break;
289                         }
290                 } else
291                         spin_unlock(&x->lock);
292
293                 xfrm_state_put(x);
294                 x = NULL;
295         }
296
297         if (!x) {
298                 XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
299                 xfrm_audit_state_notfound_simple(skb, AF_INET6);
300                 goto drop;
301         }
302
303         sp->xvec[sp->len++] = x;
304
305         spin_lock(&x->lock);
306
307         x->curlft.bytes += skb->len;
308         x->curlft.packets++;
309
310         spin_unlock(&x->lock);
311
312         return 1;
313
314 drop:
315         return -1;
316 }
317 EXPORT_SYMBOL(xfrm6_input_addr);
This page took 0.04355 seconds and 4 git commands to generate.