xref: /linux/net/ipv6/netfilter.c (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1 /*
2  * IPv6 specific functions of netfilter core
3  *
4  * Rusty Russell (C) 2000 -- This code is GPL.
5  * Patrick McHardy (C) 2006-2012
6  */
7 #include <linux/kernel.h>
8 #include <linux/init.h>
9 #include <linux/ipv6.h>
10 #include <linux/netfilter.h>
11 #include <linux/netfilter_ipv6.h>
12 #include <linux/export.h>
13 #include <net/addrconf.h>
14 #include <net/dst.h>
15 #include <net/ipv6.h>
16 #include <net/ip6_route.h>
17 #include <net/xfrm.h>
18 #include <net/netfilter/nf_queue.h>
19 #include <net/netfilter/nf_conntrack_bridge.h>
20 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
21 #include "../bridge/br_private.h"
22 
23 int ip6_route_me_harder(struct net *net, struct sock *sk_partial, struct sk_buff *skb)
24 {
25 	const struct ipv6hdr *iph = ipv6_hdr(skb);
26 	struct sock *sk = sk_to_full_sk(sk_partial);
27 	struct net_device *dev = skb_dst_dev(skb);
28 	struct flow_keys flkeys;
29 	unsigned int hh_len;
30 	struct dst_entry *dst;
31 	int strict = (ipv6_addr_type(&iph->daddr) &
32 		      (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
33 	struct flowi6 fl6 = {
34 		.flowi6_l3mdev = l3mdev_master_ifindex(dev),
35 		.flowi6_mark = skb->mark,
36 		.flowi6_uid = sock_net_uid(net, sk),
37 		.daddr = iph->daddr,
38 		.saddr = iph->saddr,
39 		.flowlabel = ip6_flowinfo(iph),
40 	};
41 	int err;
42 
43 	if (sk && sk->sk_bound_dev_if)
44 		fl6.flowi6_oif = sk->sk_bound_dev_if;
45 	else if (strict)
46 		fl6.flowi6_oif = dev->ifindex;
47 
48 	fib6_rules_early_flow_dissect(net, skb, &fl6, &flkeys);
49 	dst = ip6_route_output(net, sk, &fl6);
50 	err = dst->error;
51 	if (err) {
52 		IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
53 		net_dbg_ratelimited("ip6_route_me_harder: No more route\n");
54 		dst_release(dst);
55 		return err;
56 	}
57 
58 	/* Drop old route. */
59 	skb_dst_drop(skb);
60 
61 	skb_dst_set(skb, dst);
62 
63 #ifdef CONFIG_XFRM
64 	if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
65 	    xfrm_decode_session(net, skb, flowi6_to_flowi(&fl6), AF_INET6) == 0) {
66 		/* ignore return value from skb_dstref_steal, xfrm_lookup takes
67 		 * care of dropping the refcnt if needed.
68 		 */
69 		skb_dstref_steal(skb);
70 		dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), sk, 0);
71 		if (IS_ERR(dst))
72 			return PTR_ERR(dst);
73 		skb_dst_set(skb, dst);
74 	}
75 #endif
76 
77 	/* Change in oif may mean change in hh_len. */
78 	hh_len = skb_dst_dev(skb)->hard_header_len;
79 	if (skb_headroom(skb) < hh_len &&
80 	    pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)),
81 			     0, GFP_ATOMIC))
82 		return -ENOMEM;
83 
84 	return 0;
85 }
86 EXPORT_SYMBOL(ip6_route_me_harder);
87 
88 static int nf_ip6_reroute(struct sk_buff *skb,
89 			  const struct nf_queue_entry *entry)
90 {
91 	struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry);
92 
93 	if (entry->state.hook == NF_INET_LOCAL_OUT) {
94 		const struct ipv6hdr *iph = ipv6_hdr(skb);
95 		if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) ||
96 		    !ipv6_addr_equal(&iph->saddr, &rt_info->saddr) ||
97 		    skb->mark != rt_info->mark)
98 			return ip6_route_me_harder(entry->state.net, entry->state.sk, skb);
99 	}
100 	return 0;
101 }
102 
103 int __nf_ip6_route(struct net *net, struct dst_entry **dst,
104 		   struct flowi *fl, bool strict)
105 {
106 	static const struct ipv6_pinfo fake_pinfo;
107 	static const struct inet_sock fake_sk = {
108 		/* makes ip6_route_output set RT6_LOOKUP_F_IFACE: */
109 		.sk.sk_bound_dev_if = 1,
110 		.pinet6 = (struct ipv6_pinfo *) &fake_pinfo,
111 	};
112 	const void *sk = strict ? &fake_sk : NULL;
113 	struct dst_entry *result;
114 	int err;
115 
116 	result = ip6_route_output(net, sk, &fl->u.ip6);
117 	err = result->error;
118 	if (err)
119 		dst_release(result);
120 	else
121 		*dst = result;
122 	return err;
123 }
124 EXPORT_SYMBOL_GPL(__nf_ip6_route);
125 
126 int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
127 		    struct nf_bridge_frag_data *data,
128 		    int (*output)(struct net *, struct sock *sk,
129 				  const struct nf_bridge_frag_data *data,
130 				  struct sk_buff *))
131 {
132 	int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size;
133 	u8 tstamp_type = skb->tstamp_type;
134 	ktime_t tstamp = skb->tstamp;
135 	struct ip6_frag_state state;
136 	u8 *prevhdr, nexthdr = 0;
137 	unsigned int mtu, hlen;
138 	int hroom, err = 0;
139 	__be32 frag_id;
140 
141 	err = ip6_find_1stfragopt(skb, &prevhdr);
142 	if (err < 0)
143 		goto blackhole;
144 	hlen = err;
145 	nexthdr = *prevhdr;
146 
147 	mtu = skb->dev->mtu;
148 	if (frag_max_size > mtu ||
149 	    frag_max_size < IPV6_MIN_MTU)
150 		goto blackhole;
151 
152 	mtu = frag_max_size;
153 	if (mtu < hlen + sizeof(struct frag_hdr) + 8)
154 		goto blackhole;
155 	mtu -= hlen + sizeof(struct frag_hdr);
156 
157 	frag_id = ipv6_select_ident(net, &ipv6_hdr(skb)->daddr,
158 				    &ipv6_hdr(skb)->saddr);
159 
160 	if (skb->ip_summed == CHECKSUM_PARTIAL &&
161 	    (err = skb_checksum_help(skb)))
162 		goto blackhole;
163 
164 	hroom = LL_RESERVED_SPACE(skb->dev);
165 	if (skb_has_frag_list(skb)) {
166 		unsigned int first_len = skb_pagelen(skb);
167 		struct ip6_fraglist_iter iter;
168 		struct sk_buff *frag2;
169 
170 		if (first_len - hlen > mtu)
171 			goto blackhole;
172 
173 		if (skb_cloned(skb) ||
174 		    skb_headroom(skb) < (hroom + sizeof(struct frag_hdr)))
175 			goto slow_path;
176 
177 		skb_walk_frags(skb, frag2) {
178 			if (frag2->len > mtu)
179 				goto blackhole;
180 
181 			/* Partially cloned skb? */
182 			if (skb_shared(frag2) ||
183 			    skb_headroom(frag2) < (hlen + hroom + sizeof(struct frag_hdr)))
184 				goto slow_path;
185 		}
186 
187 		err = ip6_fraglist_init(skb, hlen, prevhdr, nexthdr, frag_id,
188 					&iter);
189 		if (err < 0)
190 			goto blackhole;
191 
192 		for (;;) {
193 			/* Prepare header of the next frame,
194 			 * before previous one went down.
195 			 */
196 			if (iter.frag)
197 				ip6_fraglist_prepare(skb, &iter);
198 
199 			skb_set_delivery_time(skb, tstamp, tstamp_type);
200 			err = output(net, sk, data, skb);
201 			if (err || !iter.frag)
202 				break;
203 
204 			skb = ip6_fraglist_next(&iter);
205 		}
206 
207 		kfree(iter.tmp_hdr);
208 		if (!err)
209 			return 0;
210 
211 		kfree_skb_list(iter.frag);
212 		return err;
213 	}
214 slow_path:
215 	/* This is a linearized skbuff, the original geometry is lost for us.
216 	 * This may also be a clone skbuff, we could preserve the geometry for
217 	 * the copies but probably not worth the effort.
218 	 */
219 	ip6_frag_init(skb, hlen, mtu, skb->dev->needed_tailroom,
220 		      LL_RESERVED_SPACE(skb->dev), prevhdr, nexthdr, frag_id,
221 		      &state);
222 
223 	while (state.left > 0) {
224 		struct sk_buff *skb2;
225 
226 		skb2 = ip6_frag_next(skb, &state);
227 		if (IS_ERR(skb2)) {
228 			err = PTR_ERR(skb2);
229 			goto blackhole;
230 		}
231 
232 		skb_set_delivery_time(skb2, tstamp, tstamp_type);
233 		err = output(net, sk, data, skb2);
234 		if (err)
235 			goto blackhole;
236 	}
237 	consume_skb(skb);
238 	return err;
239 
240 blackhole:
241 	kfree_skb(skb);
242 	return 0;
243 }
244 EXPORT_SYMBOL_GPL(br_ip6_fragment);
245 
246 static const struct nf_ipv6_ops ipv6ops = {
247 #if IS_MODULE(CONFIG_IPV6)
248 	.chk_addr		= ipv6_chk_addr,
249 	.route_me_harder	= ip6_route_me_harder,
250 	.dev_get_saddr		= ipv6_dev_get_saddr,
251 	.route			= __nf_ip6_route,
252 #if IS_ENABLED(CONFIG_SYN_COOKIES)
253 	.cookie_init_sequence	= __cookie_v6_init_sequence,
254 	.cookie_v6_check	= __cookie_v6_check,
255 #endif
256 #endif
257 	.route_input		= ip6_route_input,
258 	.fragment		= ip6_fragment,
259 	.reroute		= nf_ip6_reroute,
260 #if IS_MODULE(CONFIG_IPV6)
261 	.br_fragment		= br_ip6_fragment,
262 #endif
263 };
264 
265 int __init ipv6_netfilter_init(void)
266 {
267 	RCU_INIT_POINTER(nf_ipv6_ops, &ipv6ops);
268 	return 0;
269 }
270 
271 /* This can be called from inet6_init() on errors, so it cannot
272  * be marked __exit. -DaveM
273  */
274 void ipv6_netfilter_fini(void)
275 {
276 	RCU_INIT_POINTER(nf_ipv6_ops, NULL);
277 }
278