xref: /linux/net/ipv6/mip6.c (revision 606d099cdd1080bbb50ea50dc52d98252f8f10a1)
1 /*
2  * Copyright (C)2003-2006 Helsinki University of Technology
3  * Copyright (C)2003-2006 USAGI/WIDE Project
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 /*
20  * Authors:
21  *	Noriaki TAKAMIYA @USAGI
22  *	Masahide NAKAMURA @USAGI
23  */
24 
25 #include <linux/module.h>
26 #include <linux/skbuff.h>
27 #include <linux/time.h>
28 #include <linux/ipv6.h>
29 #include <linux/icmpv6.h>
30 #include <net/sock.h>
31 #include <net/ipv6.h>
32 #include <net/ip6_checksum.h>
33 #include <net/xfrm.h>
34 #include <net/mip6.h>
35 
36 static xfrm_address_t *mip6_xfrm_addr(struct xfrm_state *x, xfrm_address_t *addr)
37 {
38 	return x->coaddr;
39 }
40 
41 static inline unsigned int calc_padlen(unsigned int len, unsigned int n)
42 {
43 	return (n - len + 16) & 0x7;
44 }
45 
46 static inline void *mip6_padn(__u8 *data, __u8 padlen)
47 {
48 	if (!data)
49 		return NULL;
50 	if (padlen == 1) {
51 		data[0] = MIP6_OPT_PAD_1;
52 	} else if (padlen > 1) {
53 		data[0] = MIP6_OPT_PAD_N;
54 		data[1] = padlen - 2;
55 		if (padlen > 2)
56 			memset(data+2, 0, data[1]);
57 	}
58 	return data + padlen;
59 }
60 
61 static inline void mip6_param_prob(struct sk_buff *skb, int code, int pos)
62 {
63 	icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev);
64 }
65 
66 static int mip6_mh_len(int type)
67 {
68 	int len = 0;
69 
70 	switch (type) {
71 	case IP6_MH_TYPE_BRR:
72 		len = 0;
73 		break;
74 	case IP6_MH_TYPE_HOTI:
75 	case IP6_MH_TYPE_COTI:
76 	case IP6_MH_TYPE_BU:
77 	case IP6_MH_TYPE_BACK:
78 		len = 1;
79 		break;
80 	case IP6_MH_TYPE_HOT:
81 	case IP6_MH_TYPE_COT:
82 	case IP6_MH_TYPE_BERROR:
83 		len = 2;
84 		break;
85 	}
86 	return len;
87 }
88 
89 int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
90 {
91 	struct ip6_mh *mh;
92 	int mhlen;
93 
94 	if (!pskb_may_pull(skb, (skb->h.raw - skb->data) + 8) ||
95 	    !pskb_may_pull(skb, (skb->h.raw - skb->data) + ((skb->h.raw[1] + 1) << 3)))
96 		return -1;
97 
98 	mh = (struct ip6_mh *)skb->h.raw;
99 
100 	if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) {
101 		LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n",
102 			       mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type));
103 		mip6_param_prob(skb, 0, (&mh->ip6mh_hdrlen) - skb->nh.raw);
104 		return -1;
105 	}
106 	mhlen = (mh->ip6mh_hdrlen + 1) << 3;
107 
108 	if (skb->ip_summed == CHECKSUM_COMPLETE) {
109 		skb->ip_summed = CHECKSUM_UNNECESSARY;
110 		if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
111 				    &skb->nh.ipv6h->daddr,
112 				    mhlen, IPPROTO_MH,
113 				    skb->csum)) {
114 			LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH hw checksum failed\n");
115 			skb->ip_summed = CHECKSUM_NONE;
116 		}
117 	}
118 	if (skb->ip_summed == CHECKSUM_NONE) {
119 		if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
120 				    &skb->nh.ipv6h->daddr,
121 				    mhlen, IPPROTO_MH,
122 				    skb_checksum(skb, 0, mhlen, 0))) {
123 			LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH checksum failed "
124 				       "[" NIP6_FMT " > " NIP6_FMT "]\n",
125 				       NIP6(skb->nh.ipv6h->saddr),
126 				       NIP6(skb->nh.ipv6h->daddr));
127 			return -1;
128 		}
129 		skb->ip_summed = CHECKSUM_UNNECESSARY;
130 	}
131 
132 	if (mh->ip6mh_proto != IPPROTO_NONE) {
133 		LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",
134 			       mh->ip6mh_proto);
135 		mip6_param_prob(skb, 0, (&mh->ip6mh_proto) - skb->nh.raw);
136 		return -1;
137 	}
138 
139 	return 0;
140 }
141 
142 struct mip6_report_rate_limiter {
143 	spinlock_t lock;
144 	struct timeval stamp;
145 	int iif;
146 	struct in6_addr src;
147 	struct in6_addr dst;
148 };
149 
150 static struct mip6_report_rate_limiter mip6_report_rl = {
151 	.lock = SPIN_LOCK_UNLOCKED
152 };
153 
154 static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb)
155 {
156 	struct ipv6hdr *iph = skb->nh.ipv6h;
157 	struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data;
158 
159 	if (!ipv6_addr_equal(&iph->saddr, (struct in6_addr *)x->coaddr) &&
160 	    !ipv6_addr_any((struct in6_addr *)x->coaddr))
161 		return -ENOENT;
162 
163 	return destopt->nexthdr;
164 }
165 
166 /* Destination Option Header is inserted.
167  * IP Header's src address is replaced with Home Address Option in
168  * Destination Option Header.
169  */
170 static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb)
171 {
172 	struct ipv6hdr *iph;
173 	struct ipv6_destopt_hdr *dstopt;
174 	struct ipv6_destopt_hao *hao;
175 	u8 nexthdr;
176 	int len;
177 
178 	iph = (struct ipv6hdr *)skb->data;
179 	iph->payload_len = htons(skb->len - sizeof(*iph));
180 
181 	nexthdr = *skb->nh.raw;
182 	*skb->nh.raw = IPPROTO_DSTOPTS;
183 
184 	dstopt = (struct ipv6_destopt_hdr *)skb->h.raw;
185 	dstopt->nexthdr = nexthdr;
186 
187 	hao = mip6_padn((char *)(dstopt + 1),
188 			calc_padlen(sizeof(*dstopt), 6));
189 
190 	hao->type = IPV6_TLV_HAO;
191 	hao->length = sizeof(*hao) - 2;
192 	BUG_TRAP(hao->length == 16);
193 
194 	len = ((char *)hao - (char *)dstopt) + sizeof(*hao);
195 
196 	memcpy(&hao->addr, &iph->saddr, sizeof(hao->addr));
197 	memcpy(&iph->saddr, x->coaddr, sizeof(iph->saddr));
198 
199 	BUG_TRAP(len == x->props.header_len);
200 	dstopt->hdrlen = (x->props.header_len >> 3) - 1;
201 
202 	return 0;
203 }
204 
205 static inline int mip6_report_rl_allow(struct timeval *stamp,
206 				       struct in6_addr *dst,
207 				       struct in6_addr *src, int iif)
208 {
209 	int allow = 0;
210 
211 	spin_lock_bh(&mip6_report_rl.lock);
212 	if (mip6_report_rl.stamp.tv_sec != stamp->tv_sec ||
213 	    mip6_report_rl.stamp.tv_usec != stamp->tv_usec ||
214 	    mip6_report_rl.iif != iif ||
215 	    !ipv6_addr_equal(&mip6_report_rl.src, src) ||
216 	    !ipv6_addr_equal(&mip6_report_rl.dst, dst)) {
217 		mip6_report_rl.stamp.tv_sec = stamp->tv_sec;
218 		mip6_report_rl.stamp.tv_usec = stamp->tv_usec;
219 		mip6_report_rl.iif = iif;
220 		ipv6_addr_copy(&mip6_report_rl.src, src);
221 		ipv6_addr_copy(&mip6_report_rl.dst, dst);
222 		allow = 1;
223 	}
224 	spin_unlock_bh(&mip6_report_rl.lock);
225 	return allow;
226 }
227 
228 static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct flowi *fl)
229 {
230 	struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
231 	struct ipv6_destopt_hao *hao = NULL;
232 	struct xfrm_selector sel;
233 	int offset;
234 	struct timeval stamp;
235 	int err = 0;
236 
237 	if (unlikely(fl->proto == IPPROTO_MH &&
238 		     fl->fl_mh_type <= IP6_MH_TYPE_MAX))
239 		goto out;
240 
241 	if (likely(opt->dsthao)) {
242 		offset = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO);
243 		if (likely(offset >= 0))
244 			hao = (struct ipv6_destopt_hao *)(skb->nh.raw + offset);
245 	}
246 
247 	skb_get_timestamp(skb, &stamp);
248 
249 	if (!mip6_report_rl_allow(&stamp, &skb->nh.ipv6h->daddr,
250 				  hao ? &hao->addr : &skb->nh.ipv6h->saddr,
251 				  opt->iif))
252 		goto out;
253 
254 	memset(&sel, 0, sizeof(sel));
255 	memcpy(&sel.daddr, (xfrm_address_t *)&skb->nh.ipv6h->daddr,
256 	       sizeof(sel.daddr));
257 	sel.prefixlen_d = 128;
258 	memcpy(&sel.saddr, (xfrm_address_t *)&skb->nh.ipv6h->saddr,
259 	       sizeof(sel.saddr));
260 	sel.prefixlen_s = 128;
261 	sel.family = AF_INET6;
262 	sel.proto = fl->proto;
263 	sel.dport = xfrm_flowi_dport(fl);
264 	if (sel.dport)
265 		sel.dport_mask = htons(~0);
266 	sel.sport = xfrm_flowi_sport(fl);
267 	if (sel.sport)
268 		sel.sport_mask = htons(~0);
269 	sel.ifindex = fl->oif;
270 
271 	err = km_report(IPPROTO_DSTOPTS, &sel,
272 			(hao ? (xfrm_address_t *)&hao->addr : NULL));
273 
274  out:
275 	return err;
276 }
277 
278 static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
279 			       u8 **nexthdr)
280 {
281 	u16 offset = sizeof(struct ipv6hdr);
282 	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1);
283 	unsigned int packet_len = skb->tail - skb->nh.raw;
284 	int found_rhdr = 0;
285 
286 	*nexthdr = &skb->nh.ipv6h->nexthdr;
287 
288 	while (offset + 1 <= packet_len) {
289 
290 		switch (**nexthdr) {
291 		case NEXTHDR_HOP:
292 			break;
293 		case NEXTHDR_ROUTING:
294 			found_rhdr = 1;
295 			break;
296 		case NEXTHDR_DEST:
297 			/*
298 			 * HAO MUST NOT appear more than once.
299 			 * XXX: It is better to try to find by the end of
300 			 * XXX: packet if HAO exists.
301 			 */
302 			if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) {
303 				LIMIT_NETDEBUG(KERN_WARNING "mip6: hao exists already, override\n");
304 				return offset;
305 			}
306 
307 			if (found_rhdr)
308 				return offset;
309 
310 			break;
311 		default:
312 			return offset;
313 		}
314 
315 		offset += ipv6_optlen(exthdr);
316 		*nexthdr = &exthdr->nexthdr;
317 		exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
318 	}
319 
320 	return offset;
321 }
322 
323 static int mip6_destopt_init_state(struct xfrm_state *x)
324 {
325 	if (x->id.spi) {
326 		printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
327 		       x->id.spi);
328 		return -EINVAL;
329 	}
330 	if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
331 		printk(KERN_INFO "%s: state's mode is not %u: %u\n",
332 		       __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
333 		return -EINVAL;
334 	}
335 
336 	x->props.header_len = sizeof(struct ipv6_destopt_hdr) +
337 		calc_padlen(sizeof(struct ipv6_destopt_hdr), 6) +
338 		sizeof(struct ipv6_destopt_hao);
339 	BUG_TRAP(x->props.header_len == 24);
340 
341 	return 0;
342 }
343 
344 /*
345  * Do nothing about destroying since it has no specific operation for
346  * destination options header unlike IPsec protocols.
347  */
348 static void mip6_destopt_destroy(struct xfrm_state *x)
349 {
350 }
351 
352 static struct xfrm_type mip6_destopt_type =
353 {
354 	.description	= "MIP6DESTOPT",
355 	.owner		= THIS_MODULE,
356 	.proto	     	= IPPROTO_DSTOPTS,
357 	.flags		= XFRM_TYPE_NON_FRAGMENT,
358 	.init_state	= mip6_destopt_init_state,
359 	.destructor	= mip6_destopt_destroy,
360 	.input		= mip6_destopt_input,
361 	.output		= mip6_destopt_output,
362  	.reject		= mip6_destopt_reject,
363 	.hdr_offset	= mip6_destopt_offset,
364 	.local_addr	= mip6_xfrm_addr,
365 };
366 
367 static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb)
368 {
369 	struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data;
370 
371 	if (!ipv6_addr_equal(&rt2->addr, (struct in6_addr *)x->coaddr) &&
372 	    !ipv6_addr_any((struct in6_addr *)x->coaddr))
373 		return -ENOENT;
374 
375 	return rt2->rt_hdr.nexthdr;
376 }
377 
378 /* Routing Header type 2 is inserted.
379  * IP Header's dst address is replaced with Routing Header's Home Address.
380  */
381 static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb)
382 {
383 	struct ipv6hdr *iph;
384 	struct rt2_hdr *rt2;
385 	u8 nexthdr;
386 
387 	iph = (struct ipv6hdr *)skb->data;
388 	iph->payload_len = htons(skb->len - sizeof(*iph));
389 
390 	nexthdr = *skb->nh.raw;
391 	*skb->nh.raw = IPPROTO_ROUTING;
392 
393 	rt2 = (struct rt2_hdr *)skb->h.raw;
394 	rt2->rt_hdr.nexthdr = nexthdr;
395 	rt2->rt_hdr.hdrlen = (x->props.header_len >> 3) - 1;
396 	rt2->rt_hdr.type = IPV6_SRCRT_TYPE_2;
397 	rt2->rt_hdr.segments_left = 1;
398 	memset(&rt2->reserved, 0, sizeof(rt2->reserved));
399 
400 	BUG_TRAP(rt2->rt_hdr.hdrlen == 2);
401 
402 	memcpy(&rt2->addr, &iph->daddr, sizeof(rt2->addr));
403 	memcpy(&iph->daddr, x->coaddr, sizeof(iph->daddr));
404 
405 	return 0;
406 }
407 
408 static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
409 			     u8 **nexthdr)
410 {
411 	u16 offset = sizeof(struct ipv6hdr);
412 	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1);
413 	unsigned int packet_len = skb->tail - skb->nh.raw;
414 	int found_rhdr = 0;
415 
416 	*nexthdr = &skb->nh.ipv6h->nexthdr;
417 
418 	while (offset + 1 <= packet_len) {
419 
420 		switch (**nexthdr) {
421 		case NEXTHDR_HOP:
422 			break;
423 		case NEXTHDR_ROUTING:
424 			if (offset + 3 <= packet_len) {
425 				struct ipv6_rt_hdr *rt;
426 				rt = (struct ipv6_rt_hdr *)(skb->nh.raw + offset);
427 				if (rt->type != 0)
428 					return offset;
429 			}
430 			found_rhdr = 1;
431 			break;
432 		case NEXTHDR_DEST:
433 			if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
434 				return offset;
435 
436 			if (found_rhdr)
437 				return offset;
438 
439 			break;
440 		default:
441 			return offset;
442 		}
443 
444 		offset += ipv6_optlen(exthdr);
445 		*nexthdr = &exthdr->nexthdr;
446 		exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
447 	}
448 
449 	return offset;
450 }
451 
452 static int mip6_rthdr_init_state(struct xfrm_state *x)
453 {
454 	if (x->id.spi) {
455 		printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
456 		       x->id.spi);
457 		return -EINVAL;
458 	}
459 	if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
460 		printk(KERN_INFO "%s: state's mode is not %u: %u\n",
461 		       __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
462 		return -EINVAL;
463 	}
464 
465 	x->props.header_len = sizeof(struct rt2_hdr);
466 
467 	return 0;
468 }
469 
470 /*
471  * Do nothing about destroying since it has no specific operation for routing
472  * header type 2 unlike IPsec protocols.
473  */
474 static void mip6_rthdr_destroy(struct xfrm_state *x)
475 {
476 }
477 
478 static struct xfrm_type mip6_rthdr_type =
479 {
480 	.description	= "MIP6RT",
481 	.owner		= THIS_MODULE,
482 	.proto	     	= IPPROTO_ROUTING,
483 	.flags		= XFRM_TYPE_NON_FRAGMENT,
484 	.init_state	= mip6_rthdr_init_state,
485 	.destructor	= mip6_rthdr_destroy,
486 	.input		= mip6_rthdr_input,
487 	.output		= mip6_rthdr_output,
488 	.hdr_offset	= mip6_rthdr_offset,
489 	.remote_addr	= mip6_xfrm_addr,
490 };
491 
492 int __init mip6_init(void)
493 {
494 	printk(KERN_INFO "Mobile IPv6\n");
495 
496 	if (xfrm_register_type(&mip6_destopt_type, AF_INET6) < 0) {
497 		printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __FUNCTION__);
498 		goto mip6_destopt_xfrm_fail;
499 	}
500 	if (xfrm_register_type(&mip6_rthdr_type, AF_INET6) < 0) {
501 		printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
502 		goto mip6_rthdr_xfrm_fail;
503 	}
504 	return 0;
505 
506  mip6_rthdr_xfrm_fail:
507 	xfrm_unregister_type(&mip6_destopt_type, AF_INET6);
508  mip6_destopt_xfrm_fail:
509 	return -EAGAIN;
510 }
511 
512 void __exit mip6_fini(void)
513 {
514 	if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
515 		printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
516 	if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
517 		printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
518 }
519