blob: 28e0c6568272054ddcae0ac4e41f71493959adc2 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Extension Header handling for IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 * Andi Kleen <ak@muc.de>
8 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
9 *
10 * $Id: exthdrs.c,v 1.13 2001/06/19 15:58:56 davem Exp $
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18/* Changes:
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +090019 * yoshfuji : ensure not to overrun while parsing
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 * tlv options.
21 * Mitsuru KANDA @USAGI and: Remove ipv6_parse_exthdrs().
22 * YOSHIFUJI Hideaki @USAGI Register inbound extension header
23 * handlers as inet6_protocol{}.
24 */
25
26#include <linux/errno.h>
27#include <linux/types.h>
28#include <linux/socket.h>
29#include <linux/sockios.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/net.h>
31#include <linux/netdevice.h>
32#include <linux/in6.h>
33#include <linux/icmpv6.h>
34
35#include <net/sock.h>
36#include <net/snmp.h>
37
38#include <net/ipv6.h>
39#include <net/protocol.h>
40#include <net/transp_v6.h>
41#include <net/rawv6.h>
42#include <net/ndisc.h>
43#include <net/ip6_route.h>
44#include <net/addrconf.h>
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -070045#ifdef CONFIG_IPV6_MIP6
46#include <net/xfrm.h>
47#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49#include <asm/uaccess.h>
50
Masahide NAKAMURAc61a4042006-08-23 19:18:35 -070051int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
52{
53 int packet_len = skb->tail - skb->nh.raw;
54 struct ipv6_opt_hdr *hdr;
55 int len;
56
57 if (offset + 2 > packet_len)
58 goto bad;
59 hdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
60 len = ((hdr->hdrlen + 1) << 3);
61
62 if (offset + len > packet_len)
63 goto bad;
64
65 offset += 2;
66 len -= 2;
67
68 while (len > 0) {
69 int opttype = skb->nh.raw[offset];
70 int optlen;
71
72 if (opttype == type)
73 return offset;
74
75 switch (opttype) {
76 case IPV6_TLV_PAD0:
77 optlen = 1;
78 break;
79 default:
80 optlen = skb->nh.raw[offset + 1] + 2;
81 if (optlen > len)
82 goto bad;
83 break;
84 }
85 offset += optlen;
86 len -= optlen;
87 }
88 /* not_found */
Masahide NAKAMURAc61a4042006-08-23 19:18:35 -070089 bad:
90 return -1;
91}
92
Linus Torvalds1da177e2005-04-16 15:20:36 -070093/*
94 * Parsing tlv encoded headers.
95 *
96 * Parsing function "func" returns 1, if parsing succeed
97 * and 0, if it failed.
98 * It MUST NOT touch skb->h.
99 */
100
101struct tlvtype_proc {
102 int type;
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700103 int (*func)(struct sk_buff **skbp, int offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104};
105
106/*********************
107 Generic functions
108 *********************/
109
110/* An unknown option is detected, decide what to do */
111
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700112static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113{
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700114 struct sk_buff *skb = *skbp;
115
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 switch ((skb->nh.raw[optoff] & 0xC0) >> 6) {
117 case 0: /* ignore */
118 return 1;
119
120 case 1: /* drop packet */
121 break;
122
123 case 3: /* Send ICMP if not a multicast address and drop packet */
124 /* Actually, it is redundant check. icmp_send
125 will recheck in any case.
126 */
127 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
128 break;
129 case 2: /* send ICMP PARM PROB regardless and drop packet */
130 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
131 return 0;
132 };
133
134 kfree_skb(skb);
135 return 0;
136}
137
138/* Parse tlv encoded option header (hop-by-hop or destination) */
139
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700140static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141{
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700142 struct sk_buff *skb = *skbp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 struct tlvtype_proc *curr;
144 int off = skb->h.raw - skb->nh.raw;
145 int len = ((skb->h.raw[1]+1)<<3);
146
147 if ((skb->h.raw + len) - skb->data > skb_headlen(skb))
148 goto bad;
149
150 off += 2;
151 len -= 2;
152
153 while (len > 0) {
154 int optlen = skb->nh.raw[off+1]+2;
155
156 switch (skb->nh.raw[off]) {
157 case IPV6_TLV_PAD0:
158 optlen = 1;
159 break;
160
161 case IPV6_TLV_PADN:
162 break;
163
164 default: /* Other TLV code so scan list */
165 if (optlen > len)
166 goto bad;
167 for (curr=procs; curr->type >= 0; curr++) {
168 if (curr->type == skb->nh.raw[off]) {
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900169 /* type specific length/alignment
170 checks will be performed in the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 func(). */
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700172 if (curr->func(skbp, off) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 return 0;
174 break;
175 }
176 }
177 if (curr->type < 0) {
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700178 if (ip6_tlvopt_unknown(skbp, off) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 return 0;
180 }
181 break;
182 }
183 off += optlen;
184 len -= optlen;
185 }
186 if (len == 0)
187 return 1;
188bad:
189 kfree_skb(skb);
190 return 0;
191}
192
193/*****************************
194 Destination options header.
195 *****************************/
196
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700197#ifdef CONFIG_IPV6_MIP6
198static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
199{
200 struct sk_buff *skb = *skbp;
201 struct ipv6_destopt_hao *hao;
202 struct inet6_skb_parm *opt = IP6CB(skb);
203 struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->nh.raw;
204 struct in6_addr tmp_addr;
205 int ret;
206
207 if (opt->dsthao) {
208 LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
209 goto discard;
210 }
211 opt->dsthao = opt->dst1;
212 opt->dst1 = 0;
213
214 hao = (struct ipv6_destopt_hao *)(skb->nh.raw + optoff);
215
216 if (hao->length != 16) {
217 LIMIT_NETDEBUG(
218 KERN_DEBUG "hao invalid option length = %d\n", hao->length);
219 goto discard;
220 }
221
222 if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
223 LIMIT_NETDEBUG(
224 KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
225 goto discard;
226 }
227
228 ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
229 (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
230 if (unlikely(ret < 0))
231 goto discard;
232
233 if (skb_cloned(skb)) {
234 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
Masahide NAKAMURAdc435e62006-08-31 15:18:49 -0700235 struct inet6_skb_parm *opt2;
236
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700237 if (skb2 == NULL)
238 goto discard;
239
Masahide NAKAMURAdc435e62006-08-31 15:18:49 -0700240 opt2 = IP6CB(skb2);
241 memcpy(opt2, opt, sizeof(*opt2));
242
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700243 kfree_skb(skb);
244
245 /* update all variable using below by copied skbuff */
246 *skbp = skb = skb2;
247 hao = (struct ipv6_destopt_hao *)(skb2->nh.raw + optoff);
248 ipv6h = (struct ipv6hdr *)skb2->nh.raw;
249 }
250
251 if (skb->ip_summed == CHECKSUM_COMPLETE)
252 skb->ip_summed = CHECKSUM_NONE;
253
254 ipv6_addr_copy(&tmp_addr, &ipv6h->saddr);
255 ipv6_addr_copy(&ipv6h->saddr, &hao->addr);
256 ipv6_addr_copy(&hao->addr, &tmp_addr);
257
258 if (skb->tstamp.off_sec == 0)
259 __net_timestamp(skb);
260
261 return 1;
262
263 discard:
264 kfree_skb(skb);
265 return 0;
266}
267#endif
268
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269static struct tlvtype_proc tlvprocdestopt_lst[] = {
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700270#ifdef CONFIG_IPV6_MIP6
271 {
272 .type = IPV6_TLV_HAO,
273 .func = ipv6_dest_hao,
274 },
275#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 {-1, NULL}
277};
278
Patrick McHardy951dbc82006-01-06 23:02:34 -0800279static int ipv6_destopt_rcv(struct sk_buff **skbp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280{
281 struct sk_buff *skb = *skbp;
282 struct inet6_skb_parm *opt = IP6CB(skb);
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700283#ifdef CONFIG_IPV6_MIP6
284 __u16 dstbuf;
285#endif
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900286 struct dst_entry *dst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
288 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
289 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900290 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
291 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 kfree_skb(skb);
293 return -1;
294 }
295
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900296 opt->lastopt = skb->h.raw - skb->nh.raw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 opt->dst1 = skb->h.raw - skb->nh.raw;
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700298#ifdef CONFIG_IPV6_MIP6
299 dstbuf = opt->dst1;
300#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900302 dst = dst_clone(skb->dst);
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700303 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900304 dst_release(dst);
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700305 skb = *skbp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 skb->h.raw += ((skb->h.raw[1]+1)<<3);
Masahide NAKAMURAdc435e62006-08-31 15:18:49 -0700307 opt = IP6CB(skb);
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700308#ifdef CONFIG_IPV6_MIP6
309 opt->nhoff = dstbuf;
310#else
Patrick McHardy951dbc82006-01-06 23:02:34 -0800311 opt->nhoff = opt->dst1;
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700312#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 return 1;
314 }
315
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900316 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
317 dst_release(dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 return -1;
319}
320
321static struct inet6_protocol destopt_protocol = {
322 .handler = ipv6_destopt_rcv,
Herbert Xuadcfc7d2006-06-30 13:36:15 -0700323 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324};
325
326void __init ipv6_destopt_init(void)
327{
328 if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
329 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
330}
331
332/********************************
333 NONE header. No data in packet.
334 ********************************/
335
Patrick McHardy951dbc82006-01-06 23:02:34 -0800336static int ipv6_nodata_rcv(struct sk_buff **skbp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337{
338 struct sk_buff *skb = *skbp;
339
340 kfree_skb(skb);
341 return 0;
342}
343
344static struct inet6_protocol nodata_protocol = {
345 .handler = ipv6_nodata_rcv,
346 .flags = INET6_PROTO_NOPOLICY,
347};
348
349void __init ipv6_nodata_init(void)
350{
351 if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
352 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
353}
354
355/********************************
356 Routing header.
357 ********************************/
358
Patrick McHardy951dbc82006-01-06 23:02:34 -0800359static int ipv6_rthdr_rcv(struct sk_buff **skbp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360{
361 struct sk_buff *skb = *skbp;
362 struct inet6_skb_parm *opt = IP6CB(skb);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700363 struct in6_addr *addr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 struct in6_addr daddr;
365 int n, i;
366
367 struct ipv6_rt_hdr *hdr;
368 struct rt0_hdr *rthdr;
369
370 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
371 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900372 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
373 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 kfree_skb(skb);
375 return -1;
376 }
377
378 hdr = (struct ipv6_rt_hdr *) skb->h.raw;
379
380 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
381 skb->pkt_type != PACKET_HOST) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900382 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
383 IPSTATS_MIB_INADDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 kfree_skb(skb);
385 return -1;
386 }
387
388looped_back:
389 if (hdr->segments_left == 0) {
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700390 switch (hdr->type) {
391#ifdef CONFIG_IPV6_MIP6
392 case IPV6_SRCRT_TYPE_2:
393 /* Silently discard type 2 header unless it was
394 * processed by own
395 */
396 if (!addr) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900397 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
398 IPSTATS_MIB_INADDRERRORS);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700399 kfree_skb(skb);
400 return -1;
401 }
402 break;
403#endif
404 default:
405 break;
406 }
407
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900408 opt->lastopt = skb->h.raw - skb->nh.raw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 opt->srcrt = skb->h.raw - skb->nh.raw;
410 skb->h.raw += (hdr->hdrlen + 1) << 3;
411 opt->dst0 = opt->dst1;
412 opt->dst1 = 0;
Patrick McHardy951dbc82006-01-06 23:02:34 -0800413 opt->nhoff = (&hdr->nexthdr) - skb->nh.raw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 return 1;
415 }
416
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700417 switch (hdr->type) {
418 case IPV6_SRCRT_TYPE_0:
419 if (hdr->hdrlen & 0x01) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900420 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
421 IPSTATS_MIB_INHDRERRORS);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700422 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
423 return -1;
424 }
425 break;
426#ifdef CONFIG_IPV6_MIP6
427 case IPV6_SRCRT_TYPE_2:
428 /* Silently discard invalid RTH type 2 */
429 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900430 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
431 IPSTATS_MIB_INHDRERRORS);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700432 kfree_skb(skb);
433 return -1;
434 }
435 break;
436#endif
437 default:
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900438 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
439 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
441 return -1;
442 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
444 /*
445 * This is the routing header forwarding algorithm from
446 * RFC 2460, page 16.
447 */
448
449 n = hdr->hdrlen >> 1;
450
451 if (hdr->segments_left > n) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900452 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
453 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
455 return -1;
456 }
457
458 /* We are about to mangle packet header. Be careful!
459 Do not damage packets queued somewhere.
460 */
461 if (skb_cloned(skb)) {
462 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 /* the copy is a forwarded packet */
464 if (skb2 == NULL) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900465 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
466 IPSTATS_MIB_OUTDISCARDS);
467 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 return -1;
469 }
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900470 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 *skbp = skb = skb2;
472 opt = IP6CB(skb2);
473 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
474 }
475
Patrick McHardy84fa7932006-08-29 16:44:56 -0700476 if (skb->ip_summed == CHECKSUM_COMPLETE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 skb->ip_summed = CHECKSUM_NONE;
478
479 i = n - --hdr->segments_left;
480
481 rthdr = (struct rt0_hdr *) hdr;
482 addr = rthdr->addr;
483 addr += i - 1;
484
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700485 switch (hdr->type) {
486#ifdef CONFIG_IPV6_MIP6
487 case IPV6_SRCRT_TYPE_2:
488 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
489 (xfrm_address_t *)&skb->nh.ipv6h->saddr,
490 IPPROTO_ROUTING) < 0) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900491 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
492 IPSTATS_MIB_INADDRERRORS);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700493 kfree_skb(skb);
494 return -1;
495 }
496 if (!ipv6_chk_home_addr(addr)) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900497 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
498 IPSTATS_MIB_INADDRERRORS);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700499 kfree_skb(skb);
500 return -1;
501 }
502 break;
503#endif
504 default:
505 break;
506 }
507
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 if (ipv6_addr_is_multicast(addr)) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900509 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
510 IPSTATS_MIB_INADDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 kfree_skb(skb);
512 return -1;
513 }
514
515 ipv6_addr_copy(&daddr, addr);
516 ipv6_addr_copy(addr, &skb->nh.ipv6h->daddr);
517 ipv6_addr_copy(&skb->nh.ipv6h->daddr, &daddr);
518
519 dst_release(xchg(&skb->dst, NULL));
520 ip6_route_input(skb);
521 if (skb->dst->error) {
522 skb_push(skb, skb->data - skb->nh.raw);
523 dst_input(skb);
524 return -1;
525 }
526
527 if (skb->dst->dev->flags&IFF_LOOPBACK) {
528 if (skb->nh.ipv6h->hop_limit <= 1) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900529 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
530 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
532 0, skb->dev);
533 kfree_skb(skb);
534 return -1;
535 }
536 skb->nh.ipv6h->hop_limit--;
537 goto looped_back;
538 }
539
540 skb_push(skb, skb->data - skb->nh.raw);
541 dst_input(skb);
542 return -1;
543}
544
545static struct inet6_protocol rthdr_protocol = {
546 .handler = ipv6_rthdr_rcv,
Herbert Xuadcfc7d2006-06-30 13:36:15 -0700547 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548};
549
550void __init ipv6_rthdr_init(void)
551{
552 if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
553 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
554};
555
556/*
557 This function inverts received rthdr.
558 NOTE: specs allow to make it automatically only if
559 packet authenticated.
560
561 I will not discuss it here (though, I am really pissed off at
562 this stupid requirement making rthdr idea useless)
563
564 Actually, it creates severe problems for us.
565 Embryonic requests has no associated sockets,
566 so that user have no control over it and
567 cannot not only to set reply options, but
568 even to know, that someone wants to connect
569 without success. :-(
570
571 For now we need to test the engine, so that I created
572 temporary (or permanent) backdoor.
573 If listening socket set IPV6_RTHDR to 2, then we invert header.
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900574 --ANK (980729)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 */
576
577struct ipv6_txoptions *
578ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
579{
580 /* Received rthdr:
581
582 [ H1 -> H2 -> ... H_prev ] daddr=ME
583
584 Inverted result:
585 [ H_prev -> ... -> H1 ] daddr =sender
586
587 Note, that IP output engine will rewrite this rthdr
588 by rotating it left by one addr.
589 */
590
591 int n, i;
592 struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
593 struct rt0_hdr *irthdr;
594 struct ipv6_txoptions *opt;
595 int hdrlen = ipv6_optlen(hdr);
596
597 if (hdr->segments_left ||
598 hdr->type != IPV6_SRCRT_TYPE_0 ||
599 hdr->hdrlen & 0x01)
600 return NULL;
601
602 n = hdr->hdrlen >> 1;
603 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
604 if (opt == NULL)
605 return NULL;
606 memset(opt, 0, sizeof(*opt));
607 opt->tot_len = sizeof(*opt) + hdrlen;
608 opt->srcrt = (void*)(opt+1);
609 opt->opt_nflen = hdrlen;
610
611 memcpy(opt->srcrt, hdr, sizeof(*hdr));
612 irthdr = (struct rt0_hdr*)opt->srcrt;
Brian Haleye6df4392005-09-10 00:15:06 -0700613 irthdr->reserved = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 opt->srcrt->segments_left = n;
615 for (i=0; i<n; i++)
616 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
617 return opt;
618}
619
Arnaldo Carvalho de Melo3cf3dc62005-12-13 23:23:20 -0800620EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
621
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622/**********************************
623 Hop-by-hop options.
624 **********************************/
625
626/* Router Alert as of RFC 2711 */
627
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700628static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629{
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700630 struct sk_buff *skb = *skbp;
631
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 if (skb->nh.raw[optoff+1] == 2) {
633 IP6CB(skb)->ra = optoff;
634 return 1;
635 }
Patrick McHardy64ce2072005-08-09 20:50:53 -0700636 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900637 skb->nh.raw[optoff+1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 kfree_skb(skb);
639 return 0;
640}
641
642/* Jumbo payload */
643
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700644static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700646 struct sk_buff *skb = *skbp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 u32 pkt_len;
648
649 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
Patrick McHardy64ce2072005-08-09 20:50:53 -0700650 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900651 skb->nh.raw[optoff+1]);
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900652 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
653 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 goto drop;
655 }
656
Al Viroe69a4ad2006-11-14 20:56:00 -0800657 pkt_len = ntohl(*(__be32*)(skb->nh.raw+optoff+2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 if (pkt_len <= IPV6_MAXPLEN) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900659 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
661 return 0;
662 }
663 if (skb->nh.ipv6h->payload_len) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900664 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
666 return 0;
667 }
668
669 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900670 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 goto drop;
672 }
Stephen Hemminger42ca89c2005-09-08 12:57:43 -0700673
674 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
675 goto drop;
676
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 return 1;
678
679drop:
680 kfree_skb(skb);
681 return 0;
682}
683
684static struct tlvtype_proc tlvprochopopt_lst[] = {
685 {
686 .type = IPV6_TLV_ROUTERALERT,
687 .func = ipv6_hop_ra,
688 },
689 {
690 .type = IPV6_TLV_JUMBO,
691 .func = ipv6_hop_jumbo,
692 },
693 { -1, }
694};
695
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700696int ipv6_parse_hopopts(struct sk_buff **skbp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697{
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700698 struct sk_buff *skb = *skbp;
Patrick McHardy951dbc82006-01-06 23:02:34 -0800699 struct inet6_skb_parm *opt = IP6CB(skb);
700
YOSHIFUJI Hideakiec670092006-04-18 14:46:26 -0700701 /*
702 * skb->nh.raw is equal to skb->data, and
703 * skb->h.raw - skb->nh.raw is always equal to
704 * sizeof(struct ipv6hdr) by definition of
705 * hop-by-hop options.
706 */
707 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
708 !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
709 kfree_skb(skb);
710 return -1;
711 }
712
Patrick McHardy951dbc82006-01-06 23:02:34 -0800713 opt->hop = sizeof(struct ipv6hdr);
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700714 if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
715 skb = *skbp;
Patrick McHardy951dbc82006-01-06 23:02:34 -0800716 skb->h.raw += (skb->h.raw[1]+1)<<3;
Masahide NAKAMURAdc435e62006-08-31 15:18:49 -0700717 opt = IP6CB(skb);
Patrick McHardy951dbc82006-01-06 23:02:34 -0800718 opt->nhoff = sizeof(struct ipv6hdr);
YOSHIFUJI Hideakib8097392006-04-18 14:48:45 -0700719 return 1;
Patrick McHardy951dbc82006-01-06 23:02:34 -0800720 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 return -1;
722}
723
724/*
725 * Creating outbound headers.
726 *
727 * "build" functions work when skb is filled from head to tail (datagram)
728 * "push" functions work when headers are added from tail to head (tcp)
729 *
730 * In both cases we assume, that caller reserved enough room
731 * for headers.
732 */
733
734static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
735 struct ipv6_rt_hdr *opt,
736 struct in6_addr **addr_p)
737{
738 struct rt0_hdr *phdr, *ihdr;
739 int hops;
740
741 ihdr = (struct rt0_hdr *) opt;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900742
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
744 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
745
746 hops = ihdr->rt_hdr.hdrlen >> 1;
747
748 if (hops > 1)
749 memcpy(phdr->addr, ihdr->addr + 1,
750 (hops - 1) * sizeof(struct in6_addr));
751
752 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
753 *addr_p = ihdr->addr;
754
755 phdr->rt_hdr.nexthdr = *proto;
756 *proto = NEXTHDR_ROUTING;
757}
758
759static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
760{
761 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
762
763 memcpy(h, opt, ipv6_optlen(opt));
764 h->nexthdr = *proto;
765 *proto = type;
766}
767
768void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
769 u8 *proto,
770 struct in6_addr **daddr)
771{
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900772 if (opt->srcrt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900774 /*
775 * IPV6_RTHDRDSTOPTS is ignored
776 * unless IPV6_RTHDR is set (RFC3542).
777 */
778 if (opt->dst0opt)
779 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
780 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 if (opt->hopopt)
782 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
783}
784
785void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
786{
787 if (opt->dst1opt)
788 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
789}
790
791struct ipv6_txoptions *
792ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
793{
794 struct ipv6_txoptions *opt2;
795
796 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
797 if (opt2) {
798 long dif = (char*)opt2 - (char*)opt;
799 memcpy(opt2, opt, opt->tot_len);
800 if (opt2->hopopt)
801 *((char**)&opt2->hopopt) += dif;
802 if (opt2->dst0opt)
803 *((char**)&opt2->dst0opt) += dif;
804 if (opt2->dst1opt)
805 *((char**)&opt2->dst1opt) += dif;
806 if (opt2->srcrt)
807 *((char**)&opt2->srcrt) += dif;
808 }
809 return opt2;
810}
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900811
Arnaldo Carvalho de Melo3cf3dc62005-12-13 23:23:20 -0800812EXPORT_SYMBOL_GPL(ipv6_dup_options);
813
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900814static int ipv6_renew_option(void *ohdr,
815 struct ipv6_opt_hdr __user *newopt, int newoptlen,
816 int inherit,
817 struct ipv6_opt_hdr **hdr,
818 char **p)
819{
820 if (inherit) {
821 if (ohdr) {
822 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
823 *hdr = (struct ipv6_opt_hdr *)*p;
824 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
825 }
826 } else {
827 if (newopt) {
828 if (copy_from_user(*p, newopt, newoptlen))
829 return -EFAULT;
830 *hdr = (struct ipv6_opt_hdr *)*p;
831 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
832 return -EINVAL;
833 *p += CMSG_ALIGN(newoptlen);
834 }
835 }
836 return 0;
837}
838
839struct ipv6_txoptions *
840ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
841 int newtype,
842 struct ipv6_opt_hdr __user *newopt, int newoptlen)
843{
844 int tot_len = 0;
845 char *p;
846 struct ipv6_txoptions *opt2;
847 int err;
848
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700849 if (opt) {
850 if (newtype != IPV6_HOPOPTS && opt->hopopt)
851 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
852 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
853 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
854 if (newtype != IPV6_RTHDR && opt->srcrt)
855 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
856 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
857 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
858 }
859
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900860 if (newopt && newoptlen)
861 tot_len += CMSG_ALIGN(newoptlen);
862
863 if (!tot_len)
864 return NULL;
865
YOSHIFUJI Hideaki8b8aa4b2005-11-20 12:18:17 +0900866 tot_len += sizeof(*opt2);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900867 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
868 if (!opt2)
869 return ERR_PTR(-ENOBUFS);
870
871 memset(opt2, 0, tot_len);
872
873 opt2->tot_len = tot_len;
874 p = (char *)(opt2 + 1);
875
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700876 err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900877 newtype != IPV6_HOPOPTS,
878 &opt2->hopopt, &p);
879 if (err)
880 goto out;
881
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700882 err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900883 newtype != IPV6_RTHDRDSTOPTS,
884 &opt2->dst0opt, &p);
885 if (err)
886 goto out;
887
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700888 err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900889 newtype != IPV6_RTHDR,
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700890 (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900891 if (err)
892 goto out;
893
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700894 err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900895 newtype != IPV6_DSTOPTS,
896 &opt2->dst1opt, &p);
897 if (err)
898 goto out;
899
900 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
901 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
902 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
903 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
904
905 return opt2;
906out:
YOSHIFUJI Hideaki8b8aa4b2005-11-20 12:18:17 +0900907 sock_kfree_s(sk, opt2, opt2->tot_len);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900908 return ERR_PTR(err);
909}
910
YOSHIFUJI Hideakidf9890c2005-11-20 12:23:18 +0900911struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
912 struct ipv6_txoptions *opt)
913{
914 /*
915 * ignore the dest before srcrt unless srcrt is being included.
916 * --yoshfuji
917 */
918 if (opt && opt->dst0opt && !opt->srcrt) {
919 if (opt_space != opt) {
920 memcpy(opt_space, opt, sizeof(*opt_space));
921 opt = opt_space;
922 }
923 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
924 opt->dst0opt = NULL;
925 }
926
927 return opt;
928}
929