Branch data Line data Source code
1 : : /*
2 : : * xfrm6_input.c: based on net/ipv4/xfrm4_input.c
3 : : *
4 : : * Authors:
5 : : * Mitsuru KANDA @USAGI
6 : : * Kazunori MIYAZAWA @USAGI
7 : : * Kunihiro Ishiguro <kunihiro@ipinfusion.com>
8 : : * YOSHIFUJI Hideaki @USAGI
9 : : * IPv6 support
10 : : */
11 : :
12 : : #include <linux/module.h>
13 : : #include <linux/string.h>
14 : : #include <linux/netfilter.h>
15 : : #include <linux/netfilter_ipv6.h>
16 : : #include <net/ipv6.h>
17 : : #include <net/xfrm.h>
18 : :
19 : 0 : int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb)
20 : : {
21 : 0 : return xfrm6_extract_header(skb);
22 : : }
23 : :
24 : 0 : int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
25 : : {
26 : 0 : XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
27 : 0 : XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
28 : 0 : return xfrm_input(skb, nexthdr, spi, 0);
29 : : }
30 : : EXPORT_SYMBOL(xfrm6_rcv_spi);
31 : :
32 : 0 : int xfrm6_transport_finish(struct sk_buff *skb, int async)
33 : : {
34 : 0 : skb_network_header(skb)[IP6CB(skb)->nhoff] =
35 : 0 : XFRM_MODE_SKB_CB(skb)->protocol;
36 : :
37 : : #ifndef CONFIG_NETFILTER
38 : : if (!async)
39 : : return 1;
40 : : #endif
41 : :
42 [ # # ]: 0 : ipv6_hdr(skb)->payload_len = htons(skb->len);
43 : 0 : __skb_push(skb, skb->data - skb_network_header(skb));
44 : :
45 : 0 : NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL,
46 : : ip6_rcv_finish);
47 : 0 : return -1;
48 : : }
49 : :
50 : 0 : int xfrm6_rcv(struct sk_buff *skb)
51 : : {
52 : 0 : return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
53 : : 0);
54 : : }
55 : :
56 : : EXPORT_SYMBOL(xfrm6_rcv);
57 : :
58 : 0 : int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
59 : : xfrm_address_t *saddr, u8 proto)
60 : : {
61 : : struct net *net = dev_net(skb->dev);
62 : : struct xfrm_state *x = NULL;
63 : : int i = 0;
64 : :
65 : : /* Allocate new secpath or COW existing one. */
66 [ # # ][ # # ]: 0 : if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
67 : : struct sec_path *sp;
68 : :
69 : 0 : sp = secpath_dup(skb->sp);
70 [ # # ]: 0 : if (!sp) {
71 : : XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR);
72 : : goto drop;
73 : : }
74 [ # # ]: 0 : if (skb->sp)
75 : : secpath_put(skb->sp);
76 : 0 : skb->sp = sp;
77 : : }
78 : :
79 [ # # ]: 0 : if (1 + skb->sp->len == XFRM_MAX_DEPTH) {
80 : : XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR);
81 : : goto drop;
82 : : }
83 : :
84 [ # # ]: 0 : for (i = 0; i < 3; i++) {
85 : : xfrm_address_t *dst, *src;
86 : :
87 [ # # # ]: 0 : switch (i) {
88 : : case 0:
89 : : dst = daddr;
90 : : src = saddr;
91 : 0 : break;
92 : : case 1:
93 : : /* lookup state with wild-card source address */
94 : : dst = daddr;
95 : : src = (xfrm_address_t *)&in6addr_any;
96 : 0 : break;
97 : : default:
98 : : /* lookup state with wild-card addresses */
99 : : dst = (xfrm_address_t *)&in6addr_any;
100 : : src = (xfrm_address_t *)&in6addr_any;
101 : : break;
102 : : }
103 : :
104 : 0 : x = xfrm_state_lookup_byaddr(net, skb->mark, dst, src, proto, AF_INET6);
105 [ # # ]: 0 : if (!x)
106 : 0 : continue;
107 : :
108 : : spin_lock(&x->lock);
109 : :
110 [ # # ][ # # ]: 0 : if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) &&
[ # # ]
111 [ # # ]: 0 : likely(x->km.state == XFRM_STATE_VALID) &&
112 : 0 : !xfrm_state_check_expire(x)) {
113 : : spin_unlock(&x->lock);
114 [ # # ]: 0 : if (x->type->input(x, skb) > 0) {
115 : : /* found a valid state */
116 : : break;
117 : : }
118 : : } else
119 : : spin_unlock(&x->lock);
120 : :
121 : : xfrm_state_put(x);
122 : : x = NULL;
123 : : }
124 : :
125 [ # # ]: 0 : if (!x) {
126 : : XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
127 : 0 : xfrm_audit_state_notfound_simple(skb, AF_INET6);
128 : 0 : goto drop;
129 : : }
130 : :
131 : 0 : skb->sp->xvec[skb->sp->len++] = x;
132 : :
133 : : spin_lock(&x->lock);
134 : :
135 : 0 : x->curlft.bytes += skb->len;
136 : 0 : x->curlft.packets++;
137 : :
138 : : spin_unlock(&x->lock);
139 : :
140 : 0 : return 1;
141 : :
142 : : drop:
143 : : return -1;
144 : : }
145 : :
146 : : EXPORT_SYMBOL(xfrm6_input_addr);
|