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 struct sec_path *sp; 90 int i = 0; 91 92 sp = secpath_set(skb); 93 if (!sp) { 94 XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR); 95 goto drop; 96 } 97 98 if (1 + sp->len == XFRM_MAX_DEPTH) { 99 XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); 100 goto drop; 101 } 102 103 for (i = 0; i < 3; i++) { 104 xfrm_address_t *dst, *src; 105 106 switch (i) { 107 case 0: 108 dst = daddr; 109 src = saddr; 110 break; 111 case 1: 112 /* lookup state with wild-card source address */ 113 dst = daddr; 114 src = (xfrm_address_t *)&in6addr_any; 115 break; 116 default: 117 /* lookup state with wild-card addresses */ 118 dst = (xfrm_address_t *)&in6addr_any; 119 src = (xfrm_address_t *)&in6addr_any; 120 break; 121 } 122 123 x = xfrm_state_lookup_byaddr(net, skb->mark, dst, src, proto, AF_INET6); 124 if (!x) 125 continue; 126 127 spin_lock(&x->lock); 128 129 if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) && 130 likely(x->km.state == XFRM_STATE_VALID) && 131 !xfrm_state_check_expire(x)) { 132 spin_unlock(&x->lock); 133 if (x->type->input(x, skb) > 0) { 134 /* found a valid state */ 135 break; 136 } 137 } else 138 spin_unlock(&x->lock); 139 140 xfrm_state_put(x); 141 x = NULL; 142 } 143 144 if (!x) { 145 XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); 146 xfrm_audit_state_notfound_simple(skb, AF_INET6); 147 goto drop; 148 } 149 150 sp->xvec[sp->len++] = x; 151 152 spin_lock(&x->lock); 153 154 x->curlft.bytes += skb->len; 155 x->curlft.packets++; 156 157 spin_unlock(&x->lock); 158 159 return 1; 160 161 drop: 162 return -1; 163 } 164 EXPORT_SYMBOL(xfrm6_input_addr); 165