1 // SPDX-License-Identifier: GPL-2.0
3 * xfrm6_input.c: based on net/ipv4/xfrm4_input.c
7 * Kazunori MIYAZAWA @USAGI
8 * Kunihiro Ishiguro <kunihiro@ipinfusion.com>
9 * YOSHIFUJI Hideaki @USAGI
13 #include <linux/module.h>
14 #include <linux/string.h>
15 #include <linux/netfilter.h>
16 #include <linux/netfilter_ipv6.h>
20 int xfrm6_rcv_spi(struct sk_buff
*skb
, int nexthdr
, __be32 spi
,
23 XFRM_TUNNEL_SKB_CB(skb
)->tunnel
.ip6
= t
;
24 XFRM_SPI_SKB_CB(skb
)->family
= AF_INET6
;
25 XFRM_SPI_SKB_CB(skb
)->daddroff
= offsetof(struct ipv6hdr
, daddr
);
26 return xfrm_input(skb
, nexthdr
, spi
, 0);
28 EXPORT_SYMBOL(xfrm6_rcv_spi
);
30 static int xfrm6_transport_finish2(struct net
*net
, struct sock
*sk
,
33 if (xfrm_trans_queue(skb
, ip6_rcv_finish
)) {
41 int xfrm6_transport_finish(struct sk_buff
*skb
, int async
)
43 struct xfrm_offload
*xo
= xfrm_offload(skb
);
44 int nhlen
= skb
->data
- skb_network_header(skb
);
46 skb_network_header(skb
)[IP6CB(skb
)->nhoff
] =
47 XFRM_MODE_SKB_CB(skb
)->protocol
;
49 #ifndef CONFIG_NETFILTER
54 __skb_push(skb
, nhlen
);
55 ipv6_hdr(skb
)->payload_len
= htons(skb
->len
- sizeof(struct ipv6hdr
));
56 skb_postpush_rcsum(skb
, skb_network_header(skb
), nhlen
);
58 if (xo
&& (xo
->flags
& XFRM_GRO
)) {
59 skb_mac_header_rebuild(skb
);
60 skb_reset_transport_header(skb
);
64 NF_HOOK(NFPROTO_IPV6
, NF_INET_PRE_ROUTING
,
65 dev_net(skb
->dev
), NULL
, skb
, skb
->dev
, NULL
,
66 xfrm6_transport_finish2
);
70 /* If it's a keepalive packet, then just eat it.
71 * If it's an encapsulated packet, then pass it to the
73 * Returns 0 if skb passed to xfrm or was dropped.
74 * Returns >0 if skb should be passed to UDP.
75 * Returns <0 if skb should be resubmitted (-ret is protocol)
77 int xfrm6_udp_encap_rcv(struct sock
*sk
, struct sk_buff
*skb
)
79 struct udp_sock
*up
= udp_sk(sk
);
83 int ip6hlen
= sizeof(struct ipv6hdr
);
87 __u16 encap_type
= up
->encap_type
;
89 /* if this is not encapsulated socket, then just return now */
93 /* If this is a paged skb, make sure we pull up
94 * whatever data we need to look at. */
95 len
= skb
->len
- sizeof(struct udphdr
);
96 if (!pskb_may_pull(skb
, sizeof(struct udphdr
) + min(len
, 8)))
99 /* Now we can get the pointers */
101 udpdata
= (__u8
*)uh
+ sizeof(struct udphdr
);
102 udpdata32
= (__be32
*)udpdata
;
104 switch (encap_type
) {
106 case UDP_ENCAP_ESPINUDP
:
107 /* Check if this is a keepalive packet. If so, eat it. */
108 if (len
== 1 && udpdata
[0] == 0xff) {
110 } else if (len
> sizeof(struct ip_esp_hdr
) && udpdata32
[0] != 0) {
111 /* ESP Packet without Non-ESP header */
112 len
= sizeof(struct udphdr
);
114 /* Must be an IKE packet.. pass it through */
117 case UDP_ENCAP_ESPINUDP_NON_IKE
:
118 /* Check if this is a keepalive packet. If so, eat it. */
119 if (len
== 1 && udpdata
[0] == 0xff) {
121 } else if (len
> 2 * sizeof(u32
) + sizeof(struct ip_esp_hdr
) &&
122 udpdata32
[0] == 0 && udpdata32
[1] == 0) {
124 /* ESP Packet with Non-IKE marker */
125 len
= sizeof(struct udphdr
) + 2 * sizeof(u32
);
127 /* Must be an IKE packet.. pass it through */
132 /* At this point we are sure that this is an ESPinUDP packet,
133 * so we need to remove 'len' bytes from the packet (the UDP
134 * header and optional ESP marker bytes) and then modify the
135 * protocol to ESP, and then call into the transform receiver.
137 if (skb_unclone(skb
, GFP_ATOMIC
))
140 /* Now we can update and verify the packet length... */
141 ip6h
= ipv6_hdr(skb
);
142 ip6h
->payload_len
= htons(ntohs(ip6h
->payload_len
) - len
);
143 if (skb
->len
< ip6hlen
+ len
) {
144 /* packet is too small!?! */
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
152 __skb_pull(skb
, len
);
153 skb_reset_transport_header(skb
);
156 return xfrm6_rcv_encap(skb
, IPPROTO_ESP
, 0, encap_type
);
163 int xfrm6_rcv_tnl(struct sk_buff
*skb
, struct ip6_tnl
*t
)
165 return xfrm6_rcv_spi(skb
, skb_network_header(skb
)[IP6CB(skb
)->nhoff
],
168 EXPORT_SYMBOL(xfrm6_rcv_tnl
);
170 int xfrm6_rcv(struct sk_buff
*skb
)
172 return xfrm6_rcv_tnl(skb
, NULL
);
174 EXPORT_SYMBOL(xfrm6_rcv
);
175 int xfrm6_input_addr(struct sk_buff
*skb
, xfrm_address_t
*daddr
,
176 xfrm_address_t
*saddr
, u8 proto
)
178 struct net
*net
= dev_net(skb
->dev
);
179 struct xfrm_state
*x
= NULL
;
183 sp
= secpath_set(skb
);
185 XFRM_INC_STATS(net
, LINUX_MIB_XFRMINERROR
);
189 if (1 + sp
->len
== XFRM_MAX_DEPTH
) {
190 XFRM_INC_STATS(net
, LINUX_MIB_XFRMINBUFFERERROR
);
194 for (i
= 0; i
< 3; i
++) {
195 xfrm_address_t
*dst
, *src
;
203 /* lookup state with wild-card source address */
205 src
= (xfrm_address_t
*)&in6addr_any
;
208 /* lookup state with wild-card addresses */
209 dst
= (xfrm_address_t
*)&in6addr_any
;
210 src
= (xfrm_address_t
*)&in6addr_any
;
214 x
= xfrm_state_lookup_byaddr(net
, skb
->mark
, dst
, src
, proto
, AF_INET6
);
220 if ((!i
|| (x
->props
.flags
& XFRM_STATE_WILDRECV
)) &&
221 likely(x
->km
.state
== XFRM_STATE_VALID
) &&
222 !xfrm_state_check_expire(x
)) {
223 spin_unlock(&x
->lock
);
224 if (x
->type
->input(x
, skb
) > 0) {
225 /* found a valid state */
229 spin_unlock(&x
->lock
);
236 XFRM_INC_STATS(net
, LINUX_MIB_XFRMINNOSTATES
);
237 xfrm_audit_state_notfound_simple(skb
, AF_INET6
);
241 sp
->xvec
[sp
->len
++] = x
;
245 x
->curlft
.bytes
+= skb
->len
;
248 spin_unlock(&x
->lock
);
255 EXPORT_SYMBOL(xfrm6_input_addr
);