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 <kunihiro@ipinfusion.com> 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 20 int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb) 21 { 22 return xfrm6_extract_header(skb); 23 } 24 25 int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi, 26 struct ip6_tnl *t) 27 { 28 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t; 29 XFRM_SPI_SKB_CB(skb)->family = AF_INET6; 30 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr); 31 return xfrm_input(skb, nexthdr, spi, 0); 32 } 33 EXPORT_SYMBOL(xfrm6_rcv_spi); 34 35 static int xfrm6_transport_finish2(struct net *net, struct sock *sk, 36 struct sk_buff *skb) 37 { 38 if (xfrm_trans_queue(skb, ip6_rcv_finish)) 39 __kfree_skb(skb); 40 return -1; 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->data - skb_network_header(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 skb_mac_header_rebuild(skb); 62 return -1; 63 } 64 65 NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, 66 dev_net(skb->dev), NULL, skb, skb->dev, NULL, 67 xfrm6_transport_finish2); 68 return -1; 69 } 70 71 int xfrm6_rcv_tnl(struct sk_buff *skb, struct ip6_tnl *t) 72 { 73 return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff], 74 0, t); 75 } 76 EXPORT_SYMBOL(xfrm6_rcv_tnl); 77 78 int xfrm6_rcv(struct sk_buff *skb) 79 { 80 return xfrm6_rcv_tnl(skb, NULL); 81 } 82 EXPORT_SYMBOL(xfrm6_rcv); 83 int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, 84 xfrm_address_t *saddr, u8 proto) 85 { 86 struct net *net = dev_net(skb->dev); 87 struct xfrm_state *x = NULL; 88 int i = 0; 89 90 if (secpath_set(skb)) { 91 XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR); 92 goto drop; 93 } 94 95 if (1 + skb->sp->len == XFRM_MAX_DEPTH) { 96 XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); 97 goto drop; 98 } 99 100 for (i = 0; i < 3; i++) { 101 xfrm_address_t *dst, *src; 102 103 switch (i) { 104 case 0: 105 dst = daddr; 106 src = saddr; 107 break; 108 case 1: 109 /* lookup state with wild-card source address */ 110 dst = daddr; 111 src = (xfrm_address_t *)&in6addr_any; 112 break; 113 default: 114 /* lookup state with wild-card addresses */ 115 dst = (xfrm_address_t *)&in6addr_any; 116 src = (xfrm_address_t *)&in6addr_any; 117 break; 118 } 119 120 x = xfrm_state_lookup_byaddr(net, skb->mark, dst, src, proto, AF_INET6); 121 if (!x) 122 continue; 123 124 spin_lock(&x->lock); 125 126 if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) && 127 likely(x->km.state == XFRM_STATE_VALID) && 128 !xfrm_state_check_expire(x)) { 129 spin_unlock(&x->lock); 130 if (x->type->input(x, skb) > 0) { 131 /* found a valid state */ 132 break; 133 } 134 } else 135 spin_unlock(&x->lock); 136 137 xfrm_state_put(x); 138 x = NULL; 139 } 140 141 if (!x) { 142 XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); 143 xfrm_audit_state_notfound_simple(skb, AF_INET6); 144 goto drop; 145 } 146 147 skb->sp->xvec[skb->sp->len++] = x; 148 149 spin_lock(&x->lock); 150 151 x->curlft.bytes += skb->len; 152 x->curlft.packets++; 153 154 spin_unlock(&x->lock); 155 156 return 1; 157 158 drop: 159 return -1; 160 } 161 EXPORT_SYMBOL(xfrm6_input_addr); 162