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.1.1.1 2008/10/15 03:27:34 james26_jang 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: 19 * yoshfuji : ensure not to overrun while parsing 20 * tlv options. 21 */ 22 23#include <linux/errno.h> 24#include <linux/types.h> 25#include <linux/socket.h> 26#include <linux/sockios.h> 27#include <linux/sched.h> 28#include <linux/net.h> 29#include <linux/netdevice.h> 30#include <linux/in6.h> 31#include <linux/icmpv6.h> 32 33#include <net/sock.h> 34#include <net/snmp.h> 35 36#include <net/ipv6.h> 37#include <net/protocol.h> 38#include <net/transp_v6.h> 39#include <net/rawv6.h> 40#include <net/ndisc.h> 41#include <net/ip6_route.h> 42#include <net/addrconf.h> 43 44#include <asm/uaccess.h> 45 46/* 47 * Parsing inbound headers. 48 * 49 * Parsing function "func" returns offset wrt skb->nh of the place, 50 * where next nexthdr value is stored or NULL, if parsing 51 * failed. It should also update skb->h tp point at the next header. 52 */ 53 54struct hdrtype_proc 55{ 56 int type; 57 int (*func) (struct sk_buff **, int offset); 58}; 59 60/* 61 * Parsing tlv encoded headers. 62 * 63 * Parsing function "func" returns 1, if parsing succeed 64 * and 0, if it failed. 65 * It MUST NOT touch skb->h. 66 */ 67 68struct tlvtype_proc 69{ 70 int type; 71 int (*func) (struct sk_buff *, int offset); 72}; 73 74/********************* 75 Generic functions 76 *********************/ 77 78/* An unknown option is detected, decide what to do */ 79 80int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff) 81{ 82 switch ((skb->nh.raw[optoff] & 0xC0) >> 6) { 83 case 0: /* ignore */ 84 return 1; 85 86 case 1: /* drop packet */ 87 break; 88 89 case 3: /* Send ICMP if not a multicast address and drop packet */ 90 /* Actually, it is redundant check. icmp_send 91 will recheck in any case. 92 */ 93 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) 94 break; 95 case 2: /* send ICMP PARM PROB regardless and drop packet */ 96 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff); 97 return 0; 98 }; 99 100 kfree_skb(skb); 101 return 0; 102} 103 104/* Parse tlv encoded option header (hop-by-hop or destination) */ 105 106static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb) 107{ 108 struct tlvtype_proc *curr; 109 int off = skb->h.raw - skb->nh.raw; 110 int len = ((skb->h.raw[1]+1)<<3); 111 112 if ((skb->h.raw + len) - skb->data > skb_headlen(skb)) 113 goto bad; 114 115 off += 2; 116 len -= 2; 117 118 while (len > 0) { 119 int optlen = skb->nh.raw[off+1]+2; 120 121 switch (skb->nh.raw[off]) { 122 case IPV6_TLV_PAD0: 123 optlen = 1; 124 break; 125 126 case IPV6_TLV_PADN: 127 break; 128 129 default: /* Other TLV code so scan list */ 130 if (optlen > len) 131 goto bad; 132 for (curr=procs; curr->type >= 0; curr++) { 133 if (curr->type == skb->nh.raw[off]) { 134 /* type specific length/alignment 135 checks will be perfomed in the 136 func(). */ 137 if (curr->func(skb, off) == 0) 138 return 0; 139 break; 140 } 141 } 142 if (curr->type < 0) { 143 if (ip6_tlvopt_unknown(skb, off) == 0) 144 return 0; 145 } 146 break; 147 } 148 off += optlen; 149 len -= optlen; 150 } 151 if (len == 0) 152 return 1; 153bad: 154 kfree_skb(skb); 155 return 0; 156} 157 158/***************************** 159 Destination options header. 160 *****************************/ 161 162struct tlvtype_proc tlvprocdestopt_lst[] = { 163 /* No destination options are defined now */ 164 {-1, NULL} 165}; 166 167static int ipv6_dest_opt(struct sk_buff **skb_ptr, int nhoff) 168{ 169 struct sk_buff *skb=*skb_ptr; 170 struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; 171 172 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || 173 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { 174 kfree_skb(skb); 175 return -1; 176 } 177 178 opt->dst1 = skb->h.raw - skb->nh.raw; 179 180 if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { 181 skb->h.raw += ((skb->h.raw[1]+1)<<3); 182 return opt->dst1; 183 } 184 185 return -1; 186} 187 188/******************************** 189 NONE header. No data in packet. 190 ********************************/ 191 192static int ipv6_nodata(struct sk_buff **skb_ptr, int nhoff) 193{ 194 kfree_skb(*skb_ptr); 195 return -1; 196} 197 198/******************************** 199 Routing header. 200 ********************************/ 201 202static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff) 203{ 204 struct sk_buff *skb = *skb_ptr; 205 struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; 206 struct in6_addr *addr; 207 struct in6_addr daddr; 208 int addr_type; 209 int n, i; 210 211 struct ipv6_rt_hdr *hdr; 212 struct rt0_hdr *rthdr; 213 214 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || 215 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { 216 IP6_INC_STATS_BH(Ip6InHdrErrors); 217 kfree_skb(skb); 218 return -1; 219 } 220 221 hdr = (struct ipv6_rt_hdr *) skb->h.raw; 222 223 if ((ipv6_addr_type(&skb->nh.ipv6h->daddr)&IPV6_ADDR_MULTICAST) || 224 skb->pkt_type != PACKET_HOST) { 225 kfree_skb(skb); 226 return -1; 227 } 228 229looped_back: 230 if (hdr->segments_left == 0) { 231 opt->srcrt = skb->h.raw - skb->nh.raw; 232 skb->h.raw += (hdr->hdrlen + 1) << 3; 233 opt->dst0 = opt->dst1; 234 opt->dst1 = 0; 235 return (&hdr->nexthdr) - skb->nh.raw; 236 } 237 238 if (hdr->type != IPV6_SRCRT_TYPE_0 || (hdr->hdrlen & 0x01)) { 239 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, hdr->type != IPV6_SRCRT_TYPE_0 ? 2 : 1); 240 return -1; 241 } 242 243 /* 244 * This is the routing header forwarding algorithm from 245 * RFC 1883, page 17. 246 */ 247 248 n = hdr->hdrlen >> 1; 249 250 if (hdr->segments_left > n) { 251 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); 252 return -1; 253 } 254 255 /* We are about to mangle packet header. Be careful! 256 Do not damage packets queued somewhere. 257 */ 258 if (skb_cloned(skb)) { 259 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); 260 kfree_skb(skb); 261 if (skb2 == NULL) 262 return -1; 263 *skb_ptr = skb = skb2; 264 opt = (struct inet6_skb_parm *)skb2->cb; 265 hdr = (struct ipv6_rt_hdr *) skb2->h.raw; 266 } 267 268 if (skb->ip_summed == CHECKSUM_HW) 269 skb->ip_summed = CHECKSUM_NONE; 270 271 i = n - --hdr->segments_left; 272 273 rthdr = (struct rt0_hdr *) hdr; 274 addr = rthdr->addr; 275 addr += i - 1; 276 277 addr_type = ipv6_addr_type(addr); 278 279 if (addr_type&IPV6_ADDR_MULTICAST) { 280 kfree_skb(skb); 281 return -1; 282 } 283 284 ipv6_addr_copy(&daddr, addr); 285 ipv6_addr_copy(addr, &skb->nh.ipv6h->daddr); 286 ipv6_addr_copy(&skb->nh.ipv6h->daddr, &daddr); 287 288 dst_release(xchg(&skb->dst, NULL)); 289 ip6_route_input(skb); 290 if (skb->dst->error) { 291 skb->dst->input(skb); 292 return -1; 293 } 294 if (skb->dst->dev->flags&IFF_LOOPBACK) { 295 if (skb->nh.ipv6h->hop_limit <= 1) { 296 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 297 0, skb->dev); 298 kfree_skb(skb); 299 return -1; 300 } 301 skb->nh.ipv6h->hop_limit--; 302 goto looped_back; 303 } 304 305 skb->dst->input(skb); 306 return -1; 307} 308 309/* 310 This function inverts received rthdr. 311 NOTE: specs allow to make it automatically only if 312 packet authenticated. 313 314 I will not discuss it here (though, I am really pissed off at 315 this stupid requirement making rthdr idea useless) 316 317 Actually, it creates severe problems for us. 318 Embrionic requests has no associated sockets, 319 so that user have no control over it and 320 cannot not only to set reply options, but 321 even to know, that someone wants to connect 322 without success. :-( 323 324 For now we need to test the engine, so that I created 325 temporary (or permanent) backdoor. 326 If listening socket set IPV6_RTHDR to 2, then we invert header. 327 --ANK (980729) 328 */ 329 330struct ipv6_txoptions * 331ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr) 332{ 333 /* Received rthdr: 334 335 [ H1 -> H2 -> ... H_prev ] daddr=ME 336 337 Inverted result: 338 [ H_prev -> ... -> H1 ] daddr =sender 339 340 Note, that IP output engine will rewrire this rthdr 341 by rotating it left by one addr. 342 */ 343 344 int n, i; 345 struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr; 346 struct rt0_hdr *irthdr; 347 struct ipv6_txoptions *opt; 348 int hdrlen = ipv6_optlen(hdr); 349 350 if (hdr->segments_left || 351 hdr->type != IPV6_SRCRT_TYPE_0 || 352 hdr->hdrlen & 0x01) 353 return NULL; 354 355 n = hdr->hdrlen >> 1; 356 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC); 357 if (opt == NULL) 358 return NULL; 359 memset(opt, 0, sizeof(*opt)); 360 opt->tot_len = sizeof(*opt) + hdrlen; 361 opt->srcrt = (void*)(opt+1); 362 opt->opt_nflen = hdrlen; 363 364 memcpy(opt->srcrt, hdr, sizeof(*hdr)); 365 irthdr = (struct rt0_hdr*)opt->srcrt; 366 /* Obsolete field, MBZ, when originated by us */ 367 irthdr->bitmap = 0; 368 opt->srcrt->segments_left = n; 369 for (i=0; i<n; i++) 370 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16); 371 return opt; 372} 373 374/******************************** 375 AUTH header. 376 ********************************/ 377 378/* 379 rfc1826 said, that if a host does not implement AUTH header 380 it MAY ignore it. We use this hole 8) 381 382 Actually, now we can implement OSPFv6 without kernel IPsec. 383 Authentication for poors may be done in user space with the same success. 384 385 Yes, it means, that we allow application to send/receive 386 raw authentication header. Apparently, we suppose, that it knows 387 what it does and calculates authentication data correctly. 388 Certainly, it is possible only for udp and raw sockets, but not for tcp. 389 390 AUTH header has 4byte granular length, which kills all the idea 391 behind AUTOMATIC 64bit alignment of IPv6. Now we will lose 392 cpu ticks, checking that sender did not something stupid 393 and opt->hdrlen is even. Shit! --ANK (980730) 394 */ 395 396static int ipv6_auth_hdr(struct sk_buff **skb_ptr, int nhoff) 397{ 398 struct sk_buff *skb=*skb_ptr; 399 struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; 400 int len; 401 402 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8)) 403 goto fail; 404 405 len = (skb->h.raw[1]+1)<<2; 406 407 if (len&7) 408 goto fail; 409 410 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+len)) 411 goto fail; 412 413 opt->auth = skb->h.raw - skb->nh.raw; 414 skb->h.raw += len; 415 return opt->auth; 416 417fail: 418 kfree_skb(skb); 419 return -1; 420} 421 422/* This list MUST NOT contain entry for NEXTHDR_HOP. 423 It is parsed immediately after packet received 424 and if it occurs somewhere in another place we must 425 generate error. 426 */ 427 428struct hdrtype_proc hdrproc_lst[] = { 429 {NEXTHDR_FRAGMENT, ipv6_reassembly}, 430 {NEXTHDR_ROUTING, ipv6_routing_header}, 431 {NEXTHDR_DEST, ipv6_dest_opt}, 432 {NEXTHDR_NONE, ipv6_nodata}, 433 {NEXTHDR_AUTH, ipv6_auth_hdr}, 434 /* 435 {NEXTHDR_ESP, ipv6_esp_hdr}, 436 */ 437 {-1, NULL} 438}; 439 440int ipv6_parse_exthdrs(struct sk_buff **skb_in, int nhoff) 441{ 442 struct hdrtype_proc *hdrt; 443 u8 nexthdr = (*skb_in)->nh.raw[nhoff]; 444 445restart: 446 for (hdrt=hdrproc_lst; hdrt->type >= 0; hdrt++) { 447 if (hdrt->type == nexthdr) { 448 if ((nhoff = hdrt->func(skb_in, nhoff)) >= 0) { 449 nexthdr = (*skb_in)->nh.raw[nhoff]; 450 goto restart; 451 } 452 return -1; 453 } 454 } 455 return nhoff; 456} 457 458 459/********************************** 460 Hop-by-hop options. 461 **********************************/ 462 463/* Router Alert as of draft-ietf-ipngwg-ipv6router-alert-04 */ 464 465static int ipv6_hop_ra(struct sk_buff *skb, int optoff) 466{ 467 if (skb->nh.raw[optoff+1] == 2) { 468 ((struct inet6_skb_parm*)skb->cb)->ra = optoff; 469 return 1; 470 } 471 if (net_ratelimit()) 472 printk(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", skb->nh.raw[optoff+1]); 473 kfree_skb(skb); 474 return 0; 475} 476 477/* Jumbo payload */ 478 479static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) 480{ 481 u32 pkt_len; 482 483 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { 484 if (net_ratelimit()) 485 printk(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1]); 486 goto drop; 487 } 488 489 pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2)); 490 if (pkt_len < 0x10000) { 491 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); 492 return 0; 493 } 494 if (skb->nh.ipv6h->payload_len) { 495 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); 496 return 0; 497 } 498 499 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { 500 IP6_INC_STATS_BH(Ip6InTruncatedPkts); 501 goto drop; 502 } 503 if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { 504 __pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr)); 505 if (skb->ip_summed == CHECKSUM_HW) 506 skb->ip_summed = CHECKSUM_NONE; 507 } 508 return 1; 509 510drop: 511 kfree_skb(skb); 512 return 0; 513} 514 515struct tlvtype_proc tlvprochopopt_lst[] = { 516 {IPV6_TLV_ROUTERALERT, ipv6_hop_ra}, 517 {IPV6_TLV_JUMBO, ipv6_hop_jumbo}, 518 {-1, NULL} 519}; 520 521int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff) 522{ 523 ((struct inet6_skb_parm*)skb->cb)->hop = sizeof(struct ipv6hdr); 524 if (ip6_parse_tlv(tlvprochopopt_lst, skb)) 525 return sizeof(struct ipv6hdr); 526 return -1; 527} 528 529/* 530 * Creating outbound headers. 531 * 532 * "build" functions work when skb is filled from head to tail (datagram) 533 * "push" functions work when headers are added from tail to head (tcp) 534 * 535 * In both cases we assume, that caller reserved enough room 536 * for headers. 537 */ 538 539u8 *ipv6_build_rthdr(struct sk_buff *skb, u8 *prev_hdr, 540 struct ipv6_rt_hdr *opt, struct in6_addr *addr) 541{ 542 struct rt0_hdr *phdr, *ihdr; 543 int hops; 544 545 ihdr = (struct rt0_hdr *) opt; 546 547 phdr = (struct rt0_hdr *) skb_put(skb, (ihdr->rt_hdr.hdrlen + 1) << 3); 548 memcpy(phdr, ihdr, sizeof(struct rt0_hdr)); 549 550 hops = ihdr->rt_hdr.hdrlen >> 1; 551 552 if (hops > 1) 553 memcpy(phdr->addr, ihdr->addr + 1, 554 (hops - 1) * sizeof(struct in6_addr)); 555 556 ipv6_addr_copy(phdr->addr + (hops - 1), addr); 557 558 phdr->rt_hdr.nexthdr = *prev_hdr; 559 *prev_hdr = NEXTHDR_ROUTING; 560 return &phdr->rt_hdr.nexthdr; 561} 562 563static u8 *ipv6_build_exthdr(struct sk_buff *skb, u8 *prev_hdr, u8 type, struct ipv6_opt_hdr *opt) 564{ 565 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_put(skb, ipv6_optlen(opt)); 566 567 memcpy(h, opt, ipv6_optlen(opt)); 568 h->nexthdr = *prev_hdr; 569 *prev_hdr = type; 570 return &h->nexthdr; 571} 572 573static u8 *ipv6_build_authhdr(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_opt_hdr *opt) 574{ 575 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_put(skb, (opt->hdrlen+2)<<2); 576 577 memcpy(h, opt, (opt->hdrlen+2)<<2); 578 h->nexthdr = *prev_hdr; 579 *prev_hdr = NEXTHDR_AUTH; 580 return &h->nexthdr; 581} 582 583 584u8 *ipv6_build_nfrag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt, 585 struct in6_addr *daddr, u32 jumbolen) 586{ 587 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb->data; 588 589 if (opt && opt->hopopt) 590 prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_HOP, opt->hopopt); 591 592 if (jumbolen) { 593 u8 *jumboopt = (u8 *)skb_put(skb, 8); 594 595 if (opt && opt->hopopt) { 596 *jumboopt++ = IPV6_TLV_PADN; 597 *jumboopt++ = 0; 598 h->hdrlen++; 599 } else { 600 h = (struct ipv6_opt_hdr *)jumboopt; 601 h->nexthdr = *prev_hdr; 602 h->hdrlen = 0; 603 jumboopt += 2; 604 *prev_hdr = NEXTHDR_HOP; 605 prev_hdr = &h->nexthdr; 606 } 607 jumboopt[0] = IPV6_TLV_JUMBO; 608 jumboopt[1] = 4; 609 *(u32*)(jumboopt+2) = htonl(jumbolen); 610 } 611 if (opt) { 612 if (opt->dst0opt) 613 prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst0opt); 614 if (opt->srcrt) 615 prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr); 616 } 617 return prev_hdr; 618} 619 620u8 *ipv6_build_frag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt) 621{ 622 if (opt->auth) 623 prev_hdr = ipv6_build_authhdr(skb, prev_hdr, opt->auth); 624 if (opt->dst1opt) 625 prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst1opt); 626 return prev_hdr; 627} 628 629static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto, 630 struct ipv6_rt_hdr *opt, 631 struct in6_addr **addr_p) 632{ 633 struct rt0_hdr *phdr, *ihdr; 634 int hops; 635 636 ihdr = (struct rt0_hdr *) opt; 637 638 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3); 639 memcpy(phdr, ihdr, sizeof(struct rt0_hdr)); 640 641 hops = ihdr->rt_hdr.hdrlen >> 1; 642 643 if (hops > 1) 644 memcpy(phdr->addr, ihdr->addr + 1, 645 (hops - 1) * sizeof(struct in6_addr)); 646 647 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p); 648 *addr_p = ihdr->addr; 649 650 phdr->rt_hdr.nexthdr = *proto; 651 *proto = NEXTHDR_ROUTING; 652} 653 654static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt) 655{ 656 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt)); 657 658 memcpy(h, opt, ipv6_optlen(opt)); 659 h->nexthdr = *proto; 660 *proto = type; 661} 662 663static void ipv6_push_authhdr(struct sk_buff *skb, u8 *proto, struct ipv6_opt_hdr *opt) 664{ 665 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, (opt->hdrlen+2)<<2); 666 667 memcpy(h, opt, (opt->hdrlen+2)<<2); 668 h->nexthdr = *proto; 669 *proto = NEXTHDR_AUTH; 670} 671 672void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, 673 u8 *proto, 674 struct in6_addr **daddr) 675{ 676 if (opt->srcrt) 677 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr); 678 if (opt->dst0opt) 679 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt); 680 if (opt->hopopt) 681 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt); 682} 683 684void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto) 685{ 686 if (opt->dst1opt) 687 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt); 688 if (opt->auth) 689 ipv6_push_authhdr(skb, proto, opt->auth); 690} 691 692struct ipv6_txoptions * 693ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt) 694{ 695 struct ipv6_txoptions *opt2; 696 697 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC); 698 if (opt2) { 699 long dif = (char*)opt2 - (char*)opt; 700 memcpy(opt2, opt, opt->tot_len); 701 if (opt2->hopopt) 702 *((char**)&opt2->hopopt) += dif; 703 if (opt2->dst0opt) 704 *((char**)&opt2->dst0opt) += dif; 705 if (opt2->dst1opt) 706 *((char**)&opt2->dst1opt) += dif; 707 if (opt2->auth) 708 *((char**)&opt2->auth) += dif; 709 if (opt2->srcrt) 710 *((char**)&opt2->srcrt) += dif; 711 } 712 return opt2; 713} 714 715 716/* 717 * find out if nexthdr is a well-known extension header or a protocol 718 */ 719 720int ipv6_ext_hdr(u8 nexthdr) 721{ 722 /* 723 * find out if nexthdr is an extension header or a protocol 724 */ 725 return ( (nexthdr == NEXTHDR_HOP) || 726 (nexthdr == NEXTHDR_ROUTING) || 727 (nexthdr == NEXTHDR_FRAGMENT) || 728 (nexthdr == NEXTHDR_AUTH) || 729 (nexthdr == NEXTHDR_NONE) || 730 (nexthdr == NEXTHDR_DEST) ); 731} 732 733/* 734 * Skip any extension headers. This is used by the ICMP module. 735 * 736 * Note that strictly speaking this conflicts with RFC1883 4.0: 737 * ...The contents and semantics of each extension header determine whether 738 * or not to proceed to the next header. Therefore, extension headers must 739 * be processed strictly in the order they appear in the packet; a 740 * receiver must not, for example, scan through a packet looking for a 741 * particular kind of extension header and process that header prior to 742 * processing all preceding ones. 743 * 744 * We do exactly this. This is a protocol bug. We can't decide after a 745 * seeing an unknown discard-with-error flavour TLV option if it's a 746 * ICMP error message or not (errors should never be send in reply to 747 * ICMP error messages). 748 * 749 * But I see no other way to do this. This might need to be reexamined 750 * when Linux implements ESP (and maybe AUTH) headers. 751 * --AK 752 * 753 * This function parses (probably truncated) exthdr set "hdr" 754 * of length "len". "nexthdrp" initially points to some place, 755 * where type of the first header can be found. 756 * 757 * It skips all well-known exthdrs, and returns pointer to the start 758 * of unparsable area i.e. the first header with unknown type. 759 * If it is not NULL *nexthdr is updated by type/protocol of this header. 760 * 761 * NOTES: - if packet terminated with NEXTHDR_NONE it returns NULL. 762 * - it may return pointer pointing beyond end of packet, 763 * if the last recognized header is truncated in the middle. 764 * - if packet is truncated, so that all parsed headers are skipped, 765 * it returns NULL. 766 * - First fragment header is skipped, not-first ones 767 * are considered as unparsable. 768 * - ESP is unparsable for now and considered like 769 * normal payload protocol. 770 * - Note also special handling of AUTH header. Thanks to IPsec wizards. 771 * 772 * --ANK (980726) 773 */ 774 775int ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len) 776{ 777 u8 nexthdr = *nexthdrp; 778 779 while (ipv6_ext_hdr(nexthdr)) { 780 struct ipv6_opt_hdr hdr; 781 int hdrlen; 782 783 if (len < (int)sizeof(struct ipv6_opt_hdr)) 784 return -1; 785 if (nexthdr == NEXTHDR_NONE) 786 return -1; 787 if (skb_copy_bits(skb, start, &hdr, sizeof(hdr))) 788 BUG(); 789 if (nexthdr == NEXTHDR_FRAGMENT) { 790 struct frag_hdr *fhdr = (struct frag_hdr *) &hdr; 791 if (ntohs(fhdr->frag_off) & ~0x7) 792 break; 793 hdrlen = 8; 794 } else if (nexthdr == NEXTHDR_AUTH) 795 hdrlen = (hdr.hdrlen+2)<<2; 796 else 797 hdrlen = ipv6_optlen(&hdr); 798 799 nexthdr = hdr.nexthdr; 800 len -= hdrlen; 801 start += hdrlen; 802 } 803 804 *nexthdrp = nexthdr; 805 return start; 806} 807 808