]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - net/ipv6/xfrm6_input.c
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[mirror_ubuntu-bionic-kernel.git] / net / ipv6 / xfrm6_input.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
1da177e4
LT
2/*
3 * xfrm6_input.c: based on net/ipv4/xfrm4_input.c
4 *
5 * Authors:
6 * Mitsuru KANDA @USAGI
67ba4152
IM
7 * Kazunori MIYAZAWA @USAGI
8 * Kunihiro Ishiguro <kunihiro@ipinfusion.com>
1da177e4
LT
9 * YOSHIFUJI Hideaki @USAGI
10 * IPv6 support
11 */
12
13#include <linux/module.h>
14#include <linux/string.h>
b05e1066
PM
15#include <linux/netfilter.h>
16#include <linux/netfilter_ipv6.h>
1da177e4
LT
17#include <net/ipv6.h>
18#include <net/xfrm.h>
19
227620e2
HX
20int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb)
21{
22 return xfrm6_extract_header(skb);
23}
24
63c43787
ND
25int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi,
26 struct ip6_tnl *t)
1da177e4 27{
63c43787 28 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t;
2fcb45b6 29 XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
716062fd
HX
30 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
31 return xfrm_input(skb, nexthdr, spi, 0);
32}
33EXPORT_SYMBOL(xfrm6_rcv_spi);
b05e1066 34
716062fd
HX
35int xfrm6_transport_finish(struct sk_buff *skb, int async)
36{
7785bba2 37 struct xfrm_offload *xo = xfrm_offload(skb);
e9cba694 38 int nhlen = skb->data - skb_network_header(skb);
7785bba2 39
60d5fcfb
HX
40 skb_network_header(skb)[IP6CB(skb)->nhoff] =
41 XFRM_MODE_SKB_CB(skb)->protocol;
42
0883ae0e
HX
43#ifndef CONFIG_NETFILTER
44 if (!async)
45 return 1;
46#endif
47
e9cba694 48 __skb_push(skb, nhlen);
7c88e21a 49 ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
e9cba694 50 skb_postpush_rcsum(skb, skb_network_header(skb), nhlen);
b05e1066 51
7785bba2
SK
52 if (xo && (xo->flags & XFRM_GRO)) {
53 skb_mac_header_rebuild(skb);
54 return -1;
55 }
56
29a26a56
EB
57 NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING,
58 dev_net(skb->dev), NULL, skb, skb->dev, NULL,
716062fd
HX
59 ip6_rcv_finish);
60 return -1;
1da177e4
LT
61}
62
63c43787 63int xfrm6_rcv_tnl(struct sk_buff *skb, struct ip6_tnl *t)
1da177e4 64{
33b5ecb8 65 return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
63c43787 66 0, t);
1da177e4 67}
63c43787 68EXPORT_SYMBOL(xfrm6_rcv_tnl);
7159039a 69
63c43787
ND
70int xfrm6_rcv(struct sk_buff *skb)
71{
72 return xfrm6_rcv_tnl(skb, NULL);
73}
74EXPORT_SYMBOL(xfrm6_rcv);
fbd9a5b4
MN
75int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
76 xfrm_address_t *saddr, u8 proto)
77{
59c9940e 78 struct net *net = dev_net(skb->dev);
1ab1457c 79 struct xfrm_state *x = NULL;
fbd9a5b4
MN
80 int i = 0;
81
b0fcee82
SK
82 if (secpath_set(skb)) {
83 XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR);
84 goto drop;
9473e1f6
MN
85 }
86
87 if (1 + skb->sp->len == XFRM_MAX_DEPTH) {
59c9940e 88 XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR);
9473e1f6
MN
89 goto drop;
90 }
91
fbd9a5b4
MN
92 for (i = 0; i < 3; i++) {
93 xfrm_address_t *dst, *src;
a002c6fd 94
fbd9a5b4
MN
95 switch (i) {
96 case 0:
97 dst = daddr;
98 src = saddr;
99 break;
100 case 1:
101 /* lookup state with wild-card source address */
fbd9a5b4 102 dst = daddr;
a002c6fd 103 src = (xfrm_address_t *)&in6addr_any;
fbd9a5b4 104 break;
fbd9a5b4 105 default:
1ab1457c 106 /* lookup state with wild-card addresses */
a002c6fd
YH
107 dst = (xfrm_address_t *)&in6addr_any;
108 src = (xfrm_address_t *)&in6addr_any;
fbd9a5b4 109 break;
1ab1457c 110 }
fbd9a5b4 111
bd55775c 112 x = xfrm_state_lookup_byaddr(net, skb->mark, dst, src, proto, AF_INET6);
fbd9a5b4
MN
113 if (!x)
114 continue;
115
116 spin_lock(&x->lock);
117
a002c6fd
YH
118 if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) &&
119 likely(x->km.state == XFRM_STATE_VALID) &&
120 !xfrm_state_check_expire(x)) {
fbd9a5b4 121 spin_unlock(&x->lock);
a002c6fd
YH
122 if (x->type->input(x, skb) > 0) {
123 /* found a valid state */
124 break;
125 }
126 } else
fbd9a5b4 127 spin_unlock(&x->lock);
fbd9a5b4 128
a002c6fd
YH
129 xfrm_state_put(x);
130 x = NULL;
fbd9a5b4
MN
131 }
132
9473e1f6 133 if (!x) {
59c9940e 134 XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
afeb14b4 135 xfrm_audit_state_notfound_simple(skb, AF_INET6);
fbd9a5b4 136 goto drop;
fbd9a5b4
MN
137 }
138
9473e1f6
MN
139 skb->sp->xvec[skb->sp->len++] = x;
140
141 spin_lock(&x->lock);
fbd9a5b4 142
9473e1f6
MN
143 x->curlft.bytes += skb->len;
144 x->curlft.packets++;
145
146 spin_unlock(&x->lock);
fbd9a5b4
MN
147
148 return 1;
9473e1f6 149
fbd9a5b4 150drop:
fbd9a5b4
MN
151 return -1;
152}
7159039a 153EXPORT_SYMBOL(xfrm6_input_addr);