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