blob: 08313efc48c82660a5fd5c2ced3cc4c2b855af47 [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>
30#include <linux/sched.h>
31#include <linux/net.h>
32#include <linux/netdevice.h>
33#include <linux/in6.h>
34#include <linux/icmpv6.h>
35
36#include <net/sock.h>
37#include <net/snmp.h>
38
39#include <net/ipv6.h>
40#include <net/protocol.h>
41#include <net/transp_v6.h>
42#include <net/rawv6.h>
43#include <net/ndisc.h>
44#include <net/ip6_route.h>
45#include <net/addrconf.h>
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -070046#ifdef CONFIG_IPV6_MIP6
47#include <net/xfrm.h>
48#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50#include <asm/uaccess.h>
51
Masahide NAKAMURAc61a40432006-08-23 19:18:35 -070052int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
53{
54 int packet_len = skb->tail - skb->nh.raw;
55 struct ipv6_opt_hdr *hdr;
56 int len;
57
58 if (offset + 2 > packet_len)
59 goto bad;
60 hdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
61 len = ((hdr->hdrlen + 1) << 3);
62
63 if (offset + len > packet_len)
64 goto bad;
65
66 offset += 2;
67 len -= 2;
68
69 while (len > 0) {
70 int opttype = skb->nh.raw[offset];
71 int optlen;
72
73 if (opttype == type)
74 return offset;
75
76 switch (opttype) {
77 case IPV6_TLV_PAD0:
78 optlen = 1;
79 break;
80 default:
81 optlen = skb->nh.raw[offset + 1] + 2;
82 if (optlen > len)
83 goto bad;
84 break;
85 }
86 offset += optlen;
87 len -= optlen;
88 }
89 /* not_found */
Masahide NAKAMURAc61a40432006-08-23 19:18:35 -070090 bad:
91 return -1;
92}
93
Linus Torvalds1da177e2005-04-16 15:20:36 -070094/*
95 * Parsing tlv encoded headers.
96 *
97 * Parsing function "func" returns 1, if parsing succeed
98 * and 0, if it failed.
99 * It MUST NOT touch skb->h.
100 */
101
102struct tlvtype_proc {
103 int type;
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700104 int (*func)(struct sk_buff **skbp, int offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105};
106
107/*********************
108 Generic functions
109 *********************/
110
111/* An unknown option is detected, decide what to do */
112
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700113static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114{
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700115 struct sk_buff *skb = *skbp;
116
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 switch ((skb->nh.raw[optoff] & 0xC0) >> 6) {
118 case 0: /* ignore */
119 return 1;
120
121 case 1: /* drop packet */
122 break;
123
124 case 3: /* Send ICMP if not a multicast address and drop packet */
125 /* Actually, it is redundant check. icmp_send
126 will recheck in any case.
127 */
128 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
129 break;
130 case 2: /* send ICMP PARM PROB regardless and drop packet */
131 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
132 return 0;
133 };
134
135 kfree_skb(skb);
136 return 0;
137}
138
139/* Parse tlv encoded option header (hop-by-hop or destination) */
140
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700141static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142{
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700143 struct sk_buff *skb = *skbp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 struct tlvtype_proc *curr;
145 int off = skb->h.raw - skb->nh.raw;
146 int len = ((skb->h.raw[1]+1)<<3);
147
148 if ((skb->h.raw + len) - skb->data > skb_headlen(skb))
149 goto bad;
150
151 off += 2;
152 len -= 2;
153
154 while (len > 0) {
155 int optlen = skb->nh.raw[off+1]+2;
156
157 switch (skb->nh.raw[off]) {
158 case IPV6_TLV_PAD0:
159 optlen = 1;
160 break;
161
162 case IPV6_TLV_PADN:
163 break;
164
165 default: /* Other TLV code so scan list */
166 if (optlen > len)
167 goto bad;
168 for (curr=procs; curr->type >= 0; curr++) {
169 if (curr->type == skb->nh.raw[off]) {
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900170 /* type specific length/alignment
171 checks will be performed in the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 func(). */
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700173 if (curr->func(skbp, off) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 return 0;
175 break;
176 }
177 }
178 if (curr->type < 0) {
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700179 if (ip6_tlvopt_unknown(skbp, off) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 return 0;
181 }
182 break;
183 }
184 off += optlen;
185 len -= optlen;
186 }
187 if (len == 0)
188 return 1;
189bad:
190 kfree_skb(skb);
191 return 0;
192}
193
194/*****************************
195 Destination options header.
196 *****************************/
197
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700198#ifdef CONFIG_IPV6_MIP6
199static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
200{
201 struct sk_buff *skb = *skbp;
202 struct ipv6_destopt_hao *hao;
203 struct inet6_skb_parm *opt = IP6CB(skb);
204 struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->nh.raw;
205 struct in6_addr tmp_addr;
206 int ret;
207
208 if (opt->dsthao) {
209 LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
210 goto discard;
211 }
212 opt->dsthao = opt->dst1;
213 opt->dst1 = 0;
214
215 hao = (struct ipv6_destopt_hao *)(skb->nh.raw + optoff);
216
217 if (hao->length != 16) {
218 LIMIT_NETDEBUG(
219 KERN_DEBUG "hao invalid option length = %d\n", hao->length);
220 goto discard;
221 }
222
223 if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
224 LIMIT_NETDEBUG(
225 KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
226 goto discard;
227 }
228
229 ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
230 (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
231 if (unlikely(ret < 0))
232 goto discard;
233
234 if (skb_cloned(skb)) {
235 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
Masahide NAKAMURAdc435e62006-08-31 15:18:49 -0700236 struct inet6_skb_parm *opt2;
237
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700238 if (skb2 == NULL)
239 goto discard;
240
Masahide NAKAMURAdc435e62006-08-31 15:18:49 -0700241 opt2 = IP6CB(skb2);
242 memcpy(opt2, opt, sizeof(*opt2));
243
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700244 kfree_skb(skb);
245
246 /* update all variable using below by copied skbuff */
247 *skbp = skb = skb2;
248 hao = (struct ipv6_destopt_hao *)(skb2->nh.raw + optoff);
249 ipv6h = (struct ipv6hdr *)skb2->nh.raw;
250 }
251
252 if (skb->ip_summed == CHECKSUM_COMPLETE)
253 skb->ip_summed = CHECKSUM_NONE;
254
255 ipv6_addr_copy(&tmp_addr, &ipv6h->saddr);
256 ipv6_addr_copy(&ipv6h->saddr, &hao->addr);
257 ipv6_addr_copy(&hao->addr, &tmp_addr);
258
259 if (skb->tstamp.off_sec == 0)
260 __net_timestamp(skb);
261
262 return 1;
263
264 discard:
265 kfree_skb(skb);
266 return 0;
267}
268#endif
269
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270static struct tlvtype_proc tlvprocdestopt_lst[] = {
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700271#ifdef CONFIG_IPV6_MIP6
272 {
273 .type = IPV6_TLV_HAO,
274 .func = ipv6_dest_hao,
275 },
276#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 {-1, NULL}
278};
279
Patrick McHardy951dbc82006-01-06 23:02:34 -0800280static int ipv6_destopt_rcv(struct sk_buff **skbp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281{
282 struct sk_buff *skb = *skbp;
283 struct inet6_skb_parm *opt = IP6CB(skb);
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700284#ifdef CONFIG_IPV6_MIP6
285 __u16 dstbuf;
286#endif
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900287 struct dst_entry *dst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
289 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
290 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900291 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
292 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 kfree_skb(skb);
294 return -1;
295 }
296
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900297 opt->lastopt = skb->h.raw - skb->nh.raw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 opt->dst1 = skb->h.raw - skb->nh.raw;
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700299#ifdef CONFIG_IPV6_MIP6
300 dstbuf = opt->dst1;
301#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900303 dst = dst_clone(skb->dst);
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700304 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900305 dst_release(dst);
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700306 skb = *skbp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 skb->h.raw += ((skb->h.raw[1]+1)<<3);
Masahide NAKAMURAdc435e62006-08-31 15:18:49 -0700308 opt = IP6CB(skb);
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700309#ifdef CONFIG_IPV6_MIP6
310 opt->nhoff = dstbuf;
311#else
Patrick McHardy951dbc82006-01-06 23:02:34 -0800312 opt->nhoff = opt->dst1;
Masahide NAKAMURAa831f5b2006-08-23 19:24:48 -0700313#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 return 1;
315 }
316
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900317 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
318 dst_release(dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 return -1;
320}
321
322static struct inet6_protocol destopt_protocol = {
323 .handler = ipv6_destopt_rcv,
Herbert Xuadcfc7d2006-06-30 13:36:15 -0700324 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325};
326
327void __init ipv6_destopt_init(void)
328{
329 if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
330 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
331}
332
333/********************************
334 NONE header. No data in packet.
335 ********************************/
336
Patrick McHardy951dbc82006-01-06 23:02:34 -0800337static int ipv6_nodata_rcv(struct sk_buff **skbp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338{
339 struct sk_buff *skb = *skbp;
340
341 kfree_skb(skb);
342 return 0;
343}
344
345static struct inet6_protocol nodata_protocol = {
346 .handler = ipv6_nodata_rcv,
347 .flags = INET6_PROTO_NOPOLICY,
348};
349
350void __init ipv6_nodata_init(void)
351{
352 if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
353 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
354}
355
356/********************************
357 Routing header.
358 ********************************/
359
Patrick McHardy951dbc82006-01-06 23:02:34 -0800360static int ipv6_rthdr_rcv(struct sk_buff **skbp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361{
362 struct sk_buff *skb = *skbp;
363 struct inet6_skb_parm *opt = IP6CB(skb);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700364 struct in6_addr *addr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 struct in6_addr daddr;
366 int n, i;
367
368 struct ipv6_rt_hdr *hdr;
369 struct rt0_hdr *rthdr;
370
371 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
372 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900373 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
374 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 kfree_skb(skb);
376 return -1;
377 }
378
379 hdr = (struct ipv6_rt_hdr *) skb->h.raw;
380
381 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
382 skb->pkt_type != PACKET_HOST) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900383 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
384 IPSTATS_MIB_INADDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 kfree_skb(skb);
386 return -1;
387 }
388
389looped_back:
390 if (hdr->segments_left == 0) {
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700391 switch (hdr->type) {
392#ifdef CONFIG_IPV6_MIP6
393 case IPV6_SRCRT_TYPE_2:
394 /* Silently discard type 2 header unless it was
395 * processed by own
396 */
397 if (!addr) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900398 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
399 IPSTATS_MIB_INADDRERRORS);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700400 kfree_skb(skb);
401 return -1;
402 }
403 break;
404#endif
405 default:
406 break;
407 }
408
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900409 opt->lastopt = skb->h.raw - skb->nh.raw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 opt->srcrt = skb->h.raw - skb->nh.raw;
411 skb->h.raw += (hdr->hdrlen + 1) << 3;
412 opt->dst0 = opt->dst1;
413 opt->dst1 = 0;
Patrick McHardy951dbc82006-01-06 23:02:34 -0800414 opt->nhoff = (&hdr->nexthdr) - skb->nh.raw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 return 1;
416 }
417
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700418 switch (hdr->type) {
419 case IPV6_SRCRT_TYPE_0:
420 if (hdr->hdrlen & 0x01) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900421 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
422 IPSTATS_MIB_INHDRERRORS);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700423 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
424 return -1;
425 }
426 break;
427#ifdef CONFIG_IPV6_MIP6
428 case IPV6_SRCRT_TYPE_2:
429 /* Silently discard invalid RTH type 2 */
430 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900431 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
432 IPSTATS_MIB_INHDRERRORS);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700433 kfree_skb(skb);
434 return -1;
435 }
436 break;
437#endif
438 default:
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900439 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
440 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
442 return -1;
443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
445 /*
446 * This is the routing header forwarding algorithm from
447 * RFC 2460, page 16.
448 */
449
450 n = hdr->hdrlen >> 1;
451
452 if (hdr->segments_left > n) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900453 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
454 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
456 return -1;
457 }
458
459 /* We are about to mangle packet header. Be careful!
460 Do not damage packets queued somewhere.
461 */
462 if (skb_cloned(skb)) {
463 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 /* the copy is a forwarded packet */
465 if (skb2 == NULL) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900466 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
467 IPSTATS_MIB_OUTDISCARDS);
468 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 return -1;
470 }
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900471 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 *skbp = skb = skb2;
473 opt = IP6CB(skb2);
474 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
475 }
476
Patrick McHardy84fa7932006-08-29 16:44:56 -0700477 if (skb->ip_summed == CHECKSUM_COMPLETE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 skb->ip_summed = CHECKSUM_NONE;
479
480 i = n - --hdr->segments_left;
481
482 rthdr = (struct rt0_hdr *) hdr;
483 addr = rthdr->addr;
484 addr += i - 1;
485
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700486 switch (hdr->type) {
487#ifdef CONFIG_IPV6_MIP6
488 case IPV6_SRCRT_TYPE_2:
489 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
490 (xfrm_address_t *)&skb->nh.ipv6h->saddr,
491 IPPROTO_ROUTING) < 0) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900492 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
493 IPSTATS_MIB_INADDRERRORS);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700494 kfree_skb(skb);
495 return -1;
496 }
497 if (!ipv6_chk_home_addr(addr)) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900498 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
499 IPSTATS_MIB_INADDRERRORS);
Masahide NAKAMURA65d4ed92006-08-23 19:16:22 -0700500 kfree_skb(skb);
501 return -1;
502 }
503 break;
504#endif
505 default:
506 break;
507 }
508
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 if (ipv6_addr_is_multicast(addr)) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900510 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
511 IPSTATS_MIB_INADDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 kfree_skb(skb);
513 return -1;
514 }
515
516 ipv6_addr_copy(&daddr, addr);
517 ipv6_addr_copy(addr, &skb->nh.ipv6h->daddr);
518 ipv6_addr_copy(&skb->nh.ipv6h->daddr, &daddr);
519
520 dst_release(xchg(&skb->dst, NULL));
521 ip6_route_input(skb);
522 if (skb->dst->error) {
523 skb_push(skb, skb->data - skb->nh.raw);
524 dst_input(skb);
525 return -1;
526 }
527
528 if (skb->dst->dev->flags&IFF_LOOPBACK) {
529 if (skb->nh.ipv6h->hop_limit <= 1) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900530 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
531 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
533 0, skb->dev);
534 kfree_skb(skb);
535 return -1;
536 }
537 skb->nh.ipv6h->hop_limit--;
538 goto looped_back;
539 }
540
541 skb_push(skb, skb->data - skb->nh.raw);
542 dst_input(skb);
543 return -1;
544}
545
546static struct inet6_protocol rthdr_protocol = {
547 .handler = ipv6_rthdr_rcv,
Herbert Xuadcfc7d2006-06-30 13:36:15 -0700548 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549};
550
551void __init ipv6_rthdr_init(void)
552{
553 if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
554 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
555};
556
557/*
558 This function inverts received rthdr.
559 NOTE: specs allow to make it automatically only if
560 packet authenticated.
561
562 I will not discuss it here (though, I am really pissed off at
563 this stupid requirement making rthdr idea useless)
564
565 Actually, it creates severe problems for us.
566 Embryonic requests has no associated sockets,
567 so that user have no control over it and
568 cannot not only to set reply options, but
569 even to know, that someone wants to connect
570 without success. :-(
571
572 For now we need to test the engine, so that I created
573 temporary (or permanent) backdoor.
574 If listening socket set IPV6_RTHDR to 2, then we invert header.
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900575 --ANK (980729)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 */
577
578struct ipv6_txoptions *
579ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
580{
581 /* Received rthdr:
582
583 [ H1 -> H2 -> ... H_prev ] daddr=ME
584
585 Inverted result:
586 [ H_prev -> ... -> H1 ] daddr =sender
587
588 Note, that IP output engine will rewrite this rthdr
589 by rotating it left by one addr.
590 */
591
592 int n, i;
593 struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
594 struct rt0_hdr *irthdr;
595 struct ipv6_txoptions *opt;
596 int hdrlen = ipv6_optlen(hdr);
597
598 if (hdr->segments_left ||
599 hdr->type != IPV6_SRCRT_TYPE_0 ||
600 hdr->hdrlen & 0x01)
601 return NULL;
602
603 n = hdr->hdrlen >> 1;
604 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
605 if (opt == NULL)
606 return NULL;
607 memset(opt, 0, sizeof(*opt));
608 opt->tot_len = sizeof(*opt) + hdrlen;
609 opt->srcrt = (void*)(opt+1);
610 opt->opt_nflen = hdrlen;
611
612 memcpy(opt->srcrt, hdr, sizeof(*hdr));
613 irthdr = (struct rt0_hdr*)opt->srcrt;
Brian Haleye6df4392005-09-10 00:15:06 -0700614 irthdr->reserved = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 opt->srcrt->segments_left = n;
616 for (i=0; i<n; i++)
617 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
618 return opt;
619}
620
Arnaldo Carvalho de Melo3cf3dc62005-12-13 23:23:20 -0800621EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
622
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623/**********************************
624 Hop-by-hop options.
625 **********************************/
626
627/* Router Alert as of RFC 2711 */
628
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700629static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630{
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700631 struct sk_buff *skb = *skbp;
632
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 if (skb->nh.raw[optoff+1] == 2) {
634 IP6CB(skb)->ra = optoff;
635 return 1;
636 }
Patrick McHardy64ce2072005-08-09 20:50:53 -0700637 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900638 skb->nh.raw[optoff+1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 kfree_skb(skb);
640 return 0;
641}
642
643/* Jumbo payload */
644
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700645static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646{
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700647 struct sk_buff *skb = *skbp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 u32 pkt_len;
649
650 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
Patrick McHardy64ce2072005-08-09 20:50:53 -0700651 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900652 skb->nh.raw[optoff+1]);
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900653 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
654 IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 goto drop;
656 }
657
Al Viroe69a4adc2006-11-14 20:56:00 -0800658 pkt_len = ntohl(*(__be32*)(skb->nh.raw+optoff+2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 if (pkt_len <= IPV6_MAXPLEN) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900660 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
662 return 0;
663 }
664 if (skb->nh.ipv6h->payload_len) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900665 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
667 return 0;
668 }
669
670 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
YOSHIFUJI Hideakia11d2062006-11-04 20:11:37 +0900671 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 goto drop;
673 }
Stephen Hemminger42ca89c2005-09-08 12:57:43 -0700674
675 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
676 goto drop;
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 return 1;
679
680drop:
681 kfree_skb(skb);
682 return 0;
683}
684
685static struct tlvtype_proc tlvprochopopt_lst[] = {
686 {
687 .type = IPV6_TLV_ROUTERALERT,
688 .func = ipv6_hop_ra,
689 },
690 {
691 .type = IPV6_TLV_JUMBO,
692 .func = ipv6_hop_jumbo,
693 },
694 { -1, }
695};
696
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700697int ipv6_parse_hopopts(struct sk_buff **skbp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698{
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700699 struct sk_buff *skb = *skbp;
Patrick McHardy951dbc82006-01-06 23:02:34 -0800700 struct inet6_skb_parm *opt = IP6CB(skb);
701
YOSHIFUJI Hideakiec670092006-04-18 14:46:26 -0700702 /*
703 * skb->nh.raw is equal to skb->data, and
704 * skb->h.raw - skb->nh.raw is always equal to
705 * sizeof(struct ipv6hdr) by definition of
706 * hop-by-hop options.
707 */
708 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
709 !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
710 kfree_skb(skb);
711 return -1;
712 }
713
Patrick McHardy951dbc82006-01-06 23:02:34 -0800714 opt->hop = sizeof(struct ipv6hdr);
Masahide NAKAMURAa80ff032006-08-23 19:19:50 -0700715 if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
716 skb = *skbp;
Patrick McHardy951dbc82006-01-06 23:02:34 -0800717 skb->h.raw += (skb->h.raw[1]+1)<<3;
Masahide NAKAMURAdc435e62006-08-31 15:18:49 -0700718 opt = IP6CB(skb);
Patrick McHardy951dbc82006-01-06 23:02:34 -0800719 opt->nhoff = sizeof(struct ipv6hdr);
YOSHIFUJI Hideakib8097392006-04-18 14:48:45 -0700720 return 1;
Patrick McHardy951dbc82006-01-06 23:02:34 -0800721 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 return -1;
723}
724
725/*
726 * Creating outbound headers.
727 *
728 * "build" functions work when skb is filled from head to tail (datagram)
729 * "push" functions work when headers are added from tail to head (tcp)
730 *
731 * In both cases we assume, that caller reserved enough room
732 * for headers.
733 */
734
735static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
736 struct ipv6_rt_hdr *opt,
737 struct in6_addr **addr_p)
738{
739 struct rt0_hdr *phdr, *ihdr;
740 int hops;
741
742 ihdr = (struct rt0_hdr *) opt;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900743
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
745 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
746
747 hops = ihdr->rt_hdr.hdrlen >> 1;
748
749 if (hops > 1)
750 memcpy(phdr->addr, ihdr->addr + 1,
751 (hops - 1) * sizeof(struct in6_addr));
752
753 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
754 *addr_p = ihdr->addr;
755
756 phdr->rt_hdr.nexthdr = *proto;
757 *proto = NEXTHDR_ROUTING;
758}
759
760static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
761{
762 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
763
764 memcpy(h, opt, ipv6_optlen(opt));
765 h->nexthdr = *proto;
766 *proto = type;
767}
768
769void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
770 u8 *proto,
771 struct in6_addr **daddr)
772{
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900773 if (opt->srcrt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900775 /*
776 * IPV6_RTHDRDSTOPTS is ignored
777 * unless IPV6_RTHDR is set (RFC3542).
778 */
779 if (opt->dst0opt)
780 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
781 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 if (opt->hopopt)
783 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
784}
785
786void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
787{
788 if (opt->dst1opt)
789 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
790}
791
792struct ipv6_txoptions *
793ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
794{
795 struct ipv6_txoptions *opt2;
796
797 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
798 if (opt2) {
799 long dif = (char*)opt2 - (char*)opt;
800 memcpy(opt2, opt, opt->tot_len);
801 if (opt2->hopopt)
802 *((char**)&opt2->hopopt) += dif;
803 if (opt2->dst0opt)
804 *((char**)&opt2->dst0opt) += dif;
805 if (opt2->dst1opt)
806 *((char**)&opt2->dst1opt) += dif;
807 if (opt2->srcrt)
808 *((char**)&opt2->srcrt) += dif;
809 }
810 return opt2;
811}
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900812
Arnaldo Carvalho de Melo3cf3dc62005-12-13 23:23:20 -0800813EXPORT_SYMBOL_GPL(ipv6_dup_options);
814
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900815static int ipv6_renew_option(void *ohdr,
816 struct ipv6_opt_hdr __user *newopt, int newoptlen,
817 int inherit,
818 struct ipv6_opt_hdr **hdr,
819 char **p)
820{
821 if (inherit) {
822 if (ohdr) {
823 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
824 *hdr = (struct ipv6_opt_hdr *)*p;
825 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
826 }
827 } else {
828 if (newopt) {
829 if (copy_from_user(*p, newopt, newoptlen))
830 return -EFAULT;
831 *hdr = (struct ipv6_opt_hdr *)*p;
832 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
833 return -EINVAL;
834 *p += CMSG_ALIGN(newoptlen);
835 }
836 }
837 return 0;
838}
839
840struct ipv6_txoptions *
841ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
842 int newtype,
843 struct ipv6_opt_hdr __user *newopt, int newoptlen)
844{
845 int tot_len = 0;
846 char *p;
847 struct ipv6_txoptions *opt2;
848 int err;
849
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700850 if (opt) {
851 if (newtype != IPV6_HOPOPTS && opt->hopopt)
852 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
853 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
854 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
855 if (newtype != IPV6_RTHDR && opt->srcrt)
856 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
857 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
858 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
859 }
860
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900861 if (newopt && newoptlen)
862 tot_len += CMSG_ALIGN(newoptlen);
863
864 if (!tot_len)
865 return NULL;
866
YOSHIFUJI Hideaki8b8aa4b2005-11-20 12:18:17 +0900867 tot_len += sizeof(*opt2);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900868 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
869 if (!opt2)
870 return ERR_PTR(-ENOBUFS);
871
872 memset(opt2, 0, tot_len);
873
874 opt2->tot_len = tot_len;
875 p = (char *)(opt2 + 1);
876
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700877 err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900878 newtype != IPV6_HOPOPTS,
879 &opt2->hopopt, &p);
880 if (err)
881 goto out;
882
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700883 err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900884 newtype != IPV6_RTHDRDSTOPTS,
885 &opt2->dst0opt, &p);
886 if (err)
887 goto out;
888
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700889 err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900890 newtype != IPV6_RTHDR,
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700891 (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900892 if (err)
893 goto out;
894
YOSHIFUJI Hideaki99c7bc02006-08-31 14:52:17 -0700895 err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900896 newtype != IPV6_DSTOPTS,
897 &opt2->dst1opt, &p);
898 if (err)
899 goto out;
900
901 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
902 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
903 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
904 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
905
906 return opt2;
907out:
YOSHIFUJI Hideaki8b8aa4b2005-11-20 12:18:17 +0900908 sock_kfree_s(sk, opt2, opt2->tot_len);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900909 return ERR_PTR(err);
910}
911
YOSHIFUJI Hideakidf9890c2005-11-20 12:23:18 +0900912struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
913 struct ipv6_txoptions *opt)
914{
915 /*
916 * ignore the dest before srcrt unless srcrt is being included.
917 * --yoshfuji
918 */
919 if (opt && opt->dst0opt && !opt->srcrt) {
920 if (opt_space != opt) {
921 memcpy(opt_space, opt, sizeof(*opt_space));
922 opt = opt_space;
923 }
924 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
925 opt->dst0opt = NULL;
926 }
927
928 return opt;
929}
930