[IPV6] MIP6: Kill unnecessary ifdefs.
[deliverable/linux.git] / net / ipv6 / exthdrs.c
CommitLineData
1da177e4
LT
1/*
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:
1ab1457c 19 * yoshfuji : ensure not to overrun while parsing
1da177e4
LT
20 * 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>
1da177e4
LT
30#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>
65d4ed92
MN
45#ifdef CONFIG_IPV6_MIP6
46#include <net/xfrm.h>
47#endif
1da177e4
LT
48
49#include <asm/uaccess.h>
50
c61a4043
MN
51int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
52{
d56f90a7 53 const unsigned char *nh = skb_network_header(skb);
27a884dc 54 int packet_len = skb->tail - skb->network_header;
c61a4043
MN
55 struct ipv6_opt_hdr *hdr;
56 int len;
57
58 if (offset + 2 > packet_len)
59 goto bad;
d56f90a7 60 hdr = (struct ipv6_opt_hdr *)(nh + offset);
c61a4043
MN
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) {
d56f90a7 70 int opttype = nh[offset];
c61a4043
MN
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:
d56f90a7 81 optlen = nh[offset + 1] + 2;
c61a4043
MN
82 if (optlen > len)
83 goto bad;
84 break;
85 }
86 offset += optlen;
87 len -= optlen;
88 }
89 /* not_found */
c61a4043
MN
90 bad:
91 return -1;
92}
93
1da177e4
LT
94/*
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;
a80ff03e 104 int (*func)(struct sk_buff **skbp, int offset);
1da177e4
LT
105};
106
107/*********************
108 Generic functions
109 *********************/
110
111/* An unknown option is detected, decide what to do */
112
a80ff03e 113static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
1da177e4 114{
a80ff03e
MN
115 struct sk_buff *skb = *skbp;
116
d56f90a7 117 switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) {
1da177e4
LT
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 */
0660e03f 128 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr))
1da177e4
LT
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;
3ff50b79 133 }
1da177e4
LT
134
135 kfree_skb(skb);
136 return 0;
137}
138
139/* Parse tlv encoded option header (hop-by-hop or destination) */
140
a80ff03e 141static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
1da177e4 142{
a80ff03e 143 struct sk_buff *skb = *skbp;
1da177e4 144 struct tlvtype_proc *curr;
d56f90a7 145 const unsigned char *nh = skb_network_header(skb);
cfe1fc77 146 int off = skb_network_header_len(skb);
9c70220b 147 int len = (skb_transport_header(skb)[1] + 1) << 3;
1da177e4 148
ea2ae17d 149 if (skb_transport_offset(skb) + len > skb_headlen(skb))
1da177e4
LT
150 goto bad;
151
152 off += 2;
153 len -= 2;
154
155 while (len > 0) {
d56f90a7 156 int optlen = nh[off + 1] + 2;
1da177e4 157
d56f90a7 158 switch (nh[off]) {
1da177e4
LT
159 case IPV6_TLV_PAD0:
160 optlen = 1;
161 break;
162
163 case IPV6_TLV_PADN:
164 break;
165
166 default: /* Other TLV code so scan list */
167 if (optlen > len)
168 goto bad;
169 for (curr=procs; curr->type >= 0; curr++) {
d56f90a7 170 if (curr->type == nh[off]) {
1ab1457c
YH
171 /* type specific length/alignment
172 checks will be performed in the
1da177e4 173 func(). */
a80ff03e 174 if (curr->func(skbp, off) == 0)
1da177e4
LT
175 return 0;
176 break;
177 }
178 }
179 if (curr->type < 0) {
a80ff03e 180 if (ip6_tlvopt_unknown(skbp, off) == 0)
1da177e4
LT
181 return 0;
182 }
183 break;
184 }
185 off += optlen;
186 len -= optlen;
187 }
188 if (len == 0)
189 return 1;
190bad:
191 kfree_skb(skb);
192 return 0;
193}
194
195/*****************************
196 Destination options header.
197 *****************************/
198
a831f5bb
MN
199#ifdef CONFIG_IPV6_MIP6
200static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
201{
202 struct sk_buff *skb = *skbp;
203 struct ipv6_destopt_hao *hao;
204 struct inet6_skb_parm *opt = IP6CB(skb);
0660e03f 205 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
a831f5bb
MN
206 struct in6_addr tmp_addr;
207 int ret;
208
209 if (opt->dsthao) {
210 LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
211 goto discard;
212 }
213 opt->dsthao = opt->dst1;
214 opt->dst1 = 0;
215
d56f90a7 216 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff);
a831f5bb
MN
217
218 if (hao->length != 16) {
219 LIMIT_NETDEBUG(
220 KERN_DEBUG "hao invalid option length = %d\n", hao->length);
221 goto discard;
222 }
223
224 if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
225 LIMIT_NETDEBUG(
226 KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
227 goto discard;
228 }
229
230 ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
231 (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
232 if (unlikely(ret < 0))
233 goto discard;
234
235 if (skb_cloned(skb)) {
236 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
dc435e6d
MN
237 struct inet6_skb_parm *opt2;
238
a831f5bb
MN
239 if (skb2 == NULL)
240 goto discard;
241
dc435e6d
MN
242 opt2 = IP6CB(skb2);
243 memcpy(opt2, opt, sizeof(*opt2));
244
a831f5bb
MN
245 kfree_skb(skb);
246
247 /* update all variable using below by copied skbuff */
248 *skbp = skb = skb2;
d56f90a7
ACM
249 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) +
250 optoff);
0660e03f 251 ipv6h = ipv6_hdr(skb2);
a831f5bb
MN
252 }
253
254 if (skb->ip_summed == CHECKSUM_COMPLETE)
255 skb->ip_summed = CHECKSUM_NONE;
256
257 ipv6_addr_copy(&tmp_addr, &ipv6h->saddr);
258 ipv6_addr_copy(&ipv6h->saddr, &hao->addr);
259 ipv6_addr_copy(&hao->addr, &tmp_addr);
260
b7aa0bf7 261 if (skb->tstamp.tv64 == 0)
a831f5bb
MN
262 __net_timestamp(skb);
263
264 return 1;
265
266 discard:
267 kfree_skb(skb);
268 return 0;
269}
270#endif
271
1da177e4 272static struct tlvtype_proc tlvprocdestopt_lst[] = {
a831f5bb
MN
273#ifdef CONFIG_IPV6_MIP6
274 {
275 .type = IPV6_TLV_HAO,
276 .func = ipv6_dest_hao,
277 },
278#endif
1da177e4
LT
279 {-1, NULL}
280};
281
951dbc8a 282static int ipv6_destopt_rcv(struct sk_buff **skbp)
1da177e4
LT
283{
284 struct sk_buff *skb = *skbp;
285 struct inet6_skb_parm *opt = IP6CB(skb);
a831f5bb
MN
286#ifdef CONFIG_IPV6_MIP6
287 __u16 dstbuf;
288#endif
a11d206d 289 struct dst_entry *dst;
1da177e4 290
ea2ae17d
ACM
291 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
292 !pskb_may_pull(skb, (skb_transport_offset(skb) +
9c70220b 293 ((skb_transport_header(skb)[1] + 1) << 3)))) {
a11d206d
YH
294 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
295 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
296 kfree_skb(skb);
297 return -1;
298 }
299
cfe1fc77 300 opt->lastopt = opt->dst1 = skb_network_header_len(skb);
a831f5bb
MN
301#ifdef CONFIG_IPV6_MIP6
302 dstbuf = opt->dst1;
303#endif
1da177e4 304
a11d206d 305 dst = dst_clone(skb->dst);
a80ff03e 306 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
a11d206d 307 dst_release(dst);
a80ff03e 308 skb = *skbp;
b0e380b1 309 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
dc435e6d 310 opt = IP6CB(skb);
a831f5bb
MN
311#ifdef CONFIG_IPV6_MIP6
312 opt->nhoff = dstbuf;
313#else
951dbc8a 314 opt->nhoff = opt->dst1;
a831f5bb 315#endif
1da177e4
LT
316 return 1;
317 }
318
a11d206d
YH
319 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
320 dst_release(dst);
1da177e4
LT
321 return -1;
322}
323
324static struct inet6_protocol destopt_protocol = {
325 .handler = ipv6_destopt_rcv,
adcfc7d0 326 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
1da177e4
LT
327};
328
329void __init ipv6_destopt_init(void)
330{
331 if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
332 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
333}
334
335/********************************
336 NONE header. No data in packet.
337 ********************************/
338
951dbc8a 339static int ipv6_nodata_rcv(struct sk_buff **skbp)
1da177e4
LT
340{
341 struct sk_buff *skb = *skbp;
342
343 kfree_skb(skb);
344 return 0;
345}
346
347static struct inet6_protocol nodata_protocol = {
348 .handler = ipv6_nodata_rcv,
349 .flags = INET6_PROTO_NOPOLICY,
350};
351
352void __init ipv6_nodata_init(void)
353{
354 if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
355 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
356}
357
358/********************************
359 Routing header.
360 ********************************/
361
951dbc8a 362static int ipv6_rthdr_rcv(struct sk_buff **skbp)
1da177e4
LT
363{
364 struct sk_buff *skb = *skbp;
365 struct inet6_skb_parm *opt = IP6CB(skb);
65d4ed92 366 struct in6_addr *addr = NULL;
1da177e4 367 struct in6_addr daddr;
0bcbc926 368 struct inet6_dev *idev;
1da177e4 369 int n, i;
1da177e4
LT
370 struct ipv6_rt_hdr *hdr;
371 struct rt0_hdr *rthdr;
0bcbc926
YH
372 int accept_source_route = ipv6_devconf.accept_source_route;
373
374 if (accept_source_route < 0 ||
375 ((idev = in6_dev_get(skb->dev)) == NULL)) {
376 kfree_skb(skb);
377 return -1;
378 }
379 if (idev->cnf.accept_source_route < 0) {
380 in6_dev_put(idev);
381 kfree_skb(skb);
382 return -1;
383 }
384
385 if (accept_source_route > idev->cnf.accept_source_route)
386 accept_source_route = idev->cnf.accept_source_route;
387
388 in6_dev_put(idev);
1da177e4 389
ea2ae17d
ACM
390 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
391 !pskb_may_pull(skb, (skb_transport_offset(skb) +
9c70220b 392 ((skb_transport_header(skb)[1] + 1) << 3)))) {
a11d206d
YH
393 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
394 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
395 kfree_skb(skb);
396 return -1;
397 }
398
9c70220b 399 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
1da177e4 400
0bcbc926
YH
401 switch (hdr->type) {
402#ifdef CONFIG_IPV6_MIP6
ebbd90a7 403 case IPV6_SRCRT_TYPE_2:
0bcbc926
YH
404 break;
405#endif
406 case IPV6_SRCRT_TYPE_0:
a23cf14b 407 if (accept_source_route > 0)
0bcbc926
YH
408 break;
409 kfree_skb(skb);
410 return -1;
411 default:
412 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
413 IPSTATS_MIB_INHDRERRORS);
d56f90a7
ACM
414 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
415 (&hdr->type) - skb_network_header(skb));
0bcbc926
YH
416 return -1;
417 }
418
0660e03f 419 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
1da177e4 420 skb->pkt_type != PACKET_HOST) {
a11d206d
YH
421 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
422 IPSTATS_MIB_INADDRERRORS);
1da177e4
LT
423 kfree_skb(skb);
424 return -1;
425 }
426
427looped_back:
428 if (hdr->segments_left == 0) {
65d4ed92
MN
429 switch (hdr->type) {
430#ifdef CONFIG_IPV6_MIP6
431 case IPV6_SRCRT_TYPE_2:
432 /* Silently discard type 2 header unless it was
433 * processed by own
434 */
435 if (!addr) {
a11d206d
YH
436 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
437 IPSTATS_MIB_INADDRERRORS);
65d4ed92
MN
438 kfree_skb(skb);
439 return -1;
440 }
441 break;
442#endif
443 default:
444 break;
445 }
446
cfe1fc77 447 opt->lastopt = opt->srcrt = skb_network_header_len(skb);
b0e380b1 448 skb->transport_header += (hdr->hdrlen + 1) << 3;
1da177e4
LT
449 opt->dst0 = opt->dst1;
450 opt->dst1 = 0;
d56f90a7 451 opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
1da177e4
LT
452 return 1;
453 }
454
65d4ed92
MN
455 switch (hdr->type) {
456 case IPV6_SRCRT_TYPE_0:
457 if (hdr->hdrlen & 0x01) {
a11d206d
YH
458 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
459 IPSTATS_MIB_INHDRERRORS);
d56f90a7
ACM
460 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
461 ((&hdr->hdrlen) -
462 skb_network_header(skb)));
65d4ed92
MN
463 return -1;
464 }
465 break;
466#ifdef CONFIG_IPV6_MIP6
467 case IPV6_SRCRT_TYPE_2:
468 /* Silently discard invalid RTH type 2 */
469 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
a11d206d
YH
470 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
471 IPSTATS_MIB_INHDRERRORS);
65d4ed92
MN
472 kfree_skb(skb);
473 return -1;
474 }
475 break;
476#endif
1da177e4 477 }
1da177e4
LT
478
479 /*
480 * This is the routing header forwarding algorithm from
481 * RFC 2460, page 16.
482 */
483
484 n = hdr->hdrlen >> 1;
485
486 if (hdr->segments_left > n) {
a11d206d
YH
487 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
488 IPSTATS_MIB_INHDRERRORS);
d56f90a7
ACM
489 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
490 ((&hdr->segments_left) -
491 skb_network_header(skb)));
1da177e4
LT
492 return -1;
493 }
494
495 /* We are about to mangle packet header. Be careful!
496 Do not damage packets queued somewhere.
497 */
498 if (skb_cloned(skb)) {
499 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
1da177e4
LT
500 /* the copy is a forwarded packet */
501 if (skb2 == NULL) {
a11d206d
YH
502 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
503 IPSTATS_MIB_OUTDISCARDS);
504 kfree_skb(skb);
1da177e4
LT
505 return -1;
506 }
a11d206d 507 kfree_skb(skb);
1da177e4
LT
508 *skbp = skb = skb2;
509 opt = IP6CB(skb2);
bff9b61c 510 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb2);
1da177e4
LT
511 }
512
84fa7933 513 if (skb->ip_summed == CHECKSUM_COMPLETE)
1da177e4
LT
514 skb->ip_summed = CHECKSUM_NONE;
515
516 i = n - --hdr->segments_left;
517
518 rthdr = (struct rt0_hdr *) hdr;
519 addr = rthdr->addr;
520 addr += i - 1;
521
65d4ed92
MN
522 switch (hdr->type) {
523#ifdef CONFIG_IPV6_MIP6
524 case IPV6_SRCRT_TYPE_2:
525 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
0660e03f 526 (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
65d4ed92 527 IPPROTO_ROUTING) < 0) {
a11d206d
YH
528 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
529 IPSTATS_MIB_INADDRERRORS);
65d4ed92
MN
530 kfree_skb(skb);
531 return -1;
532 }
533 if (!ipv6_chk_home_addr(addr)) {
a11d206d
YH
534 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
535 IPSTATS_MIB_INADDRERRORS);
65d4ed92
MN
536 kfree_skb(skb);
537 return -1;
538 }
539 break;
540#endif
541 default:
542 break;
543 }
544
1da177e4 545 if (ipv6_addr_is_multicast(addr)) {
a11d206d
YH
546 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
547 IPSTATS_MIB_INADDRERRORS);
1da177e4
LT
548 kfree_skb(skb);
549 return -1;
550 }
551
552 ipv6_addr_copy(&daddr, addr);
0660e03f
ACM
553 ipv6_addr_copy(addr, &ipv6_hdr(skb)->daddr);
554 ipv6_addr_copy(&ipv6_hdr(skb)->daddr, &daddr);
1da177e4
LT
555
556 dst_release(xchg(&skb->dst, NULL));
557 ip6_route_input(skb);
558 if (skb->dst->error) {
d56f90a7 559 skb_push(skb, skb->data - skb_network_header(skb));
1da177e4
LT
560 dst_input(skb);
561 return -1;
562 }
563
564 if (skb->dst->dev->flags&IFF_LOOPBACK) {
0660e03f 565 if (ipv6_hdr(skb)->hop_limit <= 1) {
a11d206d
YH
566 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
567 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
568 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
569 0, skb->dev);
570 kfree_skb(skb);
571 return -1;
572 }
0660e03f 573 ipv6_hdr(skb)->hop_limit--;
1da177e4
LT
574 goto looped_back;
575 }
576
d56f90a7 577 skb_push(skb, skb->data - skb_network_header(skb));
1da177e4
LT
578 dst_input(skb);
579 return -1;
580}
581
582static struct inet6_protocol rthdr_protocol = {
583 .handler = ipv6_rthdr_rcv,
adcfc7d0 584 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
1da177e4
LT
585};
586
587void __init ipv6_rthdr_init(void)
588{
589 if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
590 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
591};
592
593/*
594 This function inverts received rthdr.
595 NOTE: specs allow to make it automatically only if
596 packet authenticated.
597
598 I will not discuss it here (though, I am really pissed off at
599 this stupid requirement making rthdr idea useless)
600
601 Actually, it creates severe problems for us.
602 Embryonic requests has no associated sockets,
603 so that user have no control over it and
604 cannot not only to set reply options, but
605 even to know, that someone wants to connect
606 without success. :-(
607
608 For now we need to test the engine, so that I created
609 temporary (or permanent) backdoor.
610 If listening socket set IPV6_RTHDR to 2, then we invert header.
1ab1457c 611 --ANK (980729)
1da177e4
LT
612 */
613
614struct ipv6_txoptions *
615ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
616{
617 /* Received rthdr:
618
619 [ H1 -> H2 -> ... H_prev ] daddr=ME
620
621 Inverted result:
622 [ H_prev -> ... -> H1 ] daddr =sender
623
624 Note, that IP output engine will rewrite this rthdr
625 by rotating it left by one addr.
626 */
627
628 int n, i;
629 struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
630 struct rt0_hdr *irthdr;
631 struct ipv6_txoptions *opt;
632 int hdrlen = ipv6_optlen(hdr);
633
634 if (hdr->segments_left ||
635 hdr->type != IPV6_SRCRT_TYPE_0 ||
636 hdr->hdrlen & 0x01)
637 return NULL;
638
639 n = hdr->hdrlen >> 1;
640 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
641 if (opt == NULL)
642 return NULL;
643 memset(opt, 0, sizeof(*opt));
644 opt->tot_len = sizeof(*opt) + hdrlen;
645 opt->srcrt = (void*)(opt+1);
646 opt->opt_nflen = hdrlen;
647
648 memcpy(opt->srcrt, hdr, sizeof(*hdr));
649 irthdr = (struct rt0_hdr*)opt->srcrt;
e6df439b 650 irthdr->reserved = 0;
1da177e4
LT
651 opt->srcrt->segments_left = n;
652 for (i=0; i<n; i++)
653 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
654 return opt;
655}
656
3cf3dc6c
ACM
657EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
658
1da177e4
LT
659/**********************************
660 Hop-by-hop options.
661 **********************************/
662
e76b2b25
YH
663/*
664 * Note: we cannot rely on skb->dst before we assign it in ip6_route_input().
665 */
666static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
667{
668 return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev);
669}
670
1da177e4
LT
671/* Router Alert as of RFC 2711 */
672
a80ff03e 673static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
1da177e4 674{
a80ff03e 675 struct sk_buff *skb = *skbp;
d56f90a7 676 const unsigned char *nh = skb_network_header(skb);
a80ff03e 677
d56f90a7 678 if (nh[optoff + 1] == 2) {
1da177e4
LT
679 IP6CB(skb)->ra = optoff;
680 return 1;
681 }
64ce2073 682 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
d56f90a7 683 nh[optoff + 1]);
1da177e4
LT
684 kfree_skb(skb);
685 return 0;
686}
687
688/* Jumbo payload */
689
a80ff03e 690static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
1da177e4 691{
a80ff03e 692 struct sk_buff *skb = *skbp;
d56f90a7 693 const unsigned char *nh = skb_network_header(skb);
1da177e4
LT
694 u32 pkt_len;
695
d56f90a7 696 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
64ce2073 697 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
d56f90a7 698 nh[optoff+1]);
e76b2b25 699 IP6_INC_STATS_BH(ipv6_skb_idev(skb),
a11d206d 700 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
701 goto drop;
702 }
703
d56f90a7 704 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
1da177e4 705 if (pkt_len <= IPV6_MAXPLEN) {
e76b2b25 706 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
707 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
708 return 0;
709 }
0660e03f 710 if (ipv6_hdr(skb)->payload_len) {
e76b2b25 711 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
712 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
713 return 0;
714 }
715
716 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
e76b2b25 717 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS);
1da177e4
LT
718 goto drop;
719 }
42ca89c1
SH
720
721 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
722 goto drop;
723
1da177e4
LT
724 return 1;
725
726drop:
727 kfree_skb(skb);
728 return 0;
729}
730
731static struct tlvtype_proc tlvprochopopt_lst[] = {
732 {
733 .type = IPV6_TLV_ROUTERALERT,
734 .func = ipv6_hop_ra,
735 },
736 {
737 .type = IPV6_TLV_JUMBO,
738 .func = ipv6_hop_jumbo,
739 },
740 { -1, }
741};
742
a80ff03e 743int ipv6_parse_hopopts(struct sk_buff **skbp)
1da177e4 744{
a80ff03e 745 struct sk_buff *skb = *skbp;
951dbc8a
PM
746 struct inet6_skb_parm *opt = IP6CB(skb);
747
ec670095 748 /*
d56f90a7 749 * skb_network_header(skb) is equal to skb->data, and
cfe1fc77 750 * skb_network_header_len(skb) is always equal to
ec670095
YH
751 * sizeof(struct ipv6hdr) by definition of
752 * hop-by-hop options.
753 */
754 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
9c70220b
ACM
755 !pskb_may_pull(skb, (sizeof(struct ipv6hdr) +
756 ((skb_transport_header(skb)[1] + 1) << 3)))) {
ec670095
YH
757 kfree_skb(skb);
758 return -1;
759 }
760
951dbc8a 761 opt->hop = sizeof(struct ipv6hdr);
a80ff03e
MN
762 if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
763 skb = *skbp;
b0e380b1 764 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
dc435e6d 765 opt = IP6CB(skb);
951dbc8a 766 opt->nhoff = sizeof(struct ipv6hdr);
b809739a 767 return 1;
951dbc8a 768 }
1da177e4
LT
769 return -1;
770}
771
772/*
773 * Creating outbound headers.
774 *
775 * "build" functions work when skb is filled from head to tail (datagram)
776 * "push" functions work when headers are added from tail to head (tcp)
777 *
778 * In both cases we assume, that caller reserved enough room
779 * for headers.
780 */
781
782static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
783 struct ipv6_rt_hdr *opt,
784 struct in6_addr **addr_p)
785{
786 struct rt0_hdr *phdr, *ihdr;
787 int hops;
788
789 ihdr = (struct rt0_hdr *) opt;
1ab1457c 790
1da177e4
LT
791 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
792 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
793
794 hops = ihdr->rt_hdr.hdrlen >> 1;
795
796 if (hops > 1)
797 memcpy(phdr->addr, ihdr->addr + 1,
798 (hops - 1) * sizeof(struct in6_addr));
799
800 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
801 *addr_p = ihdr->addr;
802
803 phdr->rt_hdr.nexthdr = *proto;
804 *proto = NEXTHDR_ROUTING;
805}
806
807static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
808{
809 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
810
811 memcpy(h, opt, ipv6_optlen(opt));
812 h->nexthdr = *proto;
813 *proto = type;
814}
815
816void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
817 u8 *proto,
818 struct in6_addr **daddr)
819{
333fad53 820 if (opt->srcrt) {
1da177e4 821 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
333fad53
YH
822 /*
823 * IPV6_RTHDRDSTOPTS is ignored
824 * unless IPV6_RTHDR is set (RFC3542).
825 */
826 if (opt->dst0opt)
827 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
828 }
1da177e4
LT
829 if (opt->hopopt)
830 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
831}
832
7159039a
YH
833EXPORT_SYMBOL(ipv6_push_nfrag_opts);
834
1da177e4
LT
835void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
836{
837 if (opt->dst1opt)
838 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
839}
840
841struct ipv6_txoptions *
842ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
843{
844 struct ipv6_txoptions *opt2;
845
846 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
847 if (opt2) {
848 long dif = (char*)opt2 - (char*)opt;
849 memcpy(opt2, opt, opt->tot_len);
850 if (opt2->hopopt)
851 *((char**)&opt2->hopopt) += dif;
852 if (opt2->dst0opt)
853 *((char**)&opt2->dst0opt) += dif;
854 if (opt2->dst1opt)
855 *((char**)&opt2->dst1opt) += dif;
856 if (opt2->srcrt)
857 *((char**)&opt2->srcrt) += dif;
858 }
859 return opt2;
860}
333fad53 861
3cf3dc6c
ACM
862EXPORT_SYMBOL_GPL(ipv6_dup_options);
863
333fad53
YH
864static int ipv6_renew_option(void *ohdr,
865 struct ipv6_opt_hdr __user *newopt, int newoptlen,
866 int inherit,
867 struct ipv6_opt_hdr **hdr,
868 char **p)
869{
870 if (inherit) {
871 if (ohdr) {
872 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
873 *hdr = (struct ipv6_opt_hdr *)*p;
874 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
875 }
876 } else {
877 if (newopt) {
878 if (copy_from_user(*p, newopt, newoptlen))
879 return -EFAULT;
880 *hdr = (struct ipv6_opt_hdr *)*p;
881 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
882 return -EINVAL;
883 *p += CMSG_ALIGN(newoptlen);
884 }
885 }
886 return 0;
887}
888
889struct ipv6_txoptions *
890ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
891 int newtype,
892 struct ipv6_opt_hdr __user *newopt, int newoptlen)
893{
894 int tot_len = 0;
895 char *p;
896 struct ipv6_txoptions *opt2;
897 int err;
898
99c7bc01
YH
899 if (opt) {
900 if (newtype != IPV6_HOPOPTS && opt->hopopt)
901 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
902 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
903 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
904 if (newtype != IPV6_RTHDR && opt->srcrt)
905 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
906 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
907 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
908 }
909
333fad53
YH
910 if (newopt && newoptlen)
911 tot_len += CMSG_ALIGN(newoptlen);
912
913 if (!tot_len)
914 return NULL;
915
8b8aa4b5 916 tot_len += sizeof(*opt2);
333fad53
YH
917 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
918 if (!opt2)
919 return ERR_PTR(-ENOBUFS);
920
921 memset(opt2, 0, tot_len);
922
923 opt2->tot_len = tot_len;
924 p = (char *)(opt2 + 1);
925
99c7bc01 926 err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
333fad53
YH
927 newtype != IPV6_HOPOPTS,
928 &opt2->hopopt, &p);
929 if (err)
930 goto out;
931
99c7bc01 932 err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
333fad53
YH
933 newtype != IPV6_RTHDRDSTOPTS,
934 &opt2->dst0opt, &p);
935 if (err)
936 goto out;
937
99c7bc01 938 err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
333fad53 939 newtype != IPV6_RTHDR,
99c7bc01 940 (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
333fad53
YH
941 if (err)
942 goto out;
943
99c7bc01 944 err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
333fad53
YH
945 newtype != IPV6_DSTOPTS,
946 &opt2->dst1opt, &p);
947 if (err)
948 goto out;
949
950 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
951 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
952 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
953 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
954
955 return opt2;
956out:
8b8aa4b5 957 sock_kfree_s(sk, opt2, opt2->tot_len);
333fad53
YH
958 return ERR_PTR(err);
959}
960
df9890c3
YH
961struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
962 struct ipv6_txoptions *opt)
963{
964 /*
965 * ignore the dest before srcrt unless srcrt is being included.
966 * --yoshfuji
967 */
968 if (opt && opt->dst0opt && !opt->srcrt) {
969 if (opt_space != opt) {
970 memcpy(opt_space, opt, sizeof(*opt_space));
971 opt = opt_space;
972 }
973 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
974 opt->dst0opt = NULL;
975 }
976
977 return opt;
978}
979
This page took 0.46553 seconds and 5 git commands to generate.