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: 19 * yoshfuji : ensure not to overrun while parsing 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> 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> 45 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 46 #include <net/xfrm.h> 47 #endif 48 49 #include <asm/uaccess.h> 50 51 int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) 52 { 53 const unsigned char *nh = skb_network_header(skb); 54 int packet_len = skb->tail - skb->network_header; 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 *)(nh + 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 = nh[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 = nh[offset + 1] + 2; 82 if (optlen > len) 83 goto bad; 84 break; 85 } 86 offset += optlen; 87 len -= optlen; 88 } 89 /* not_found */ 90 bad: 91 return -1; 92 } 93 EXPORT_SYMBOL_GPL(ipv6_find_tlv); 94 95 /* 96 * Parsing tlv encoded headers. 97 * 98 * Parsing function "func" returns 1, if parsing succeed 99 * and 0, if it failed. 100 * It MUST NOT touch skb->h. 101 */ 102 103 struct tlvtype_proc { 104 int type; 105 int (*func)(struct sk_buff *skb, int offset); 106 }; 107 108 /********************* 109 Generic functions 110 *********************/ 111 112 /* An unknown option is detected, decide what to do */ 113 114 static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff) 115 { 116 switch ((skb_network_header(skb)[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(&ipv6_hdr(skb)->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 140 static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb) 141 { 142 struct tlvtype_proc *curr; 143 const unsigned char *nh = skb_network_header(skb); 144 int off = skb_network_header_len(skb); 145 int len = (skb_transport_header(skb)[1] + 1) << 3; 146 147 if (skb_transport_offset(skb) + len > skb_headlen(skb)) 148 goto bad; 149 150 off += 2; 151 len -= 2; 152 153 while (len > 0) { 154 int optlen = nh[off + 1] + 2; 155 156 switch (nh[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 == nh[off]) { 169 /* type specific length/alignment 170 checks will be performed in the 171 func(). */ 172 if (curr->func(skb, off) == 0) 173 return 0; 174 break; 175 } 176 } 177 if (curr->type < 0) { 178 if (ip6_tlvopt_unknown(skb, off) == 0) 179 return 0; 180 } 181 break; 182 } 183 off += optlen; 184 len -= optlen; 185 } 186 if (len == 0) 187 return 1; 188 bad: 189 kfree_skb(skb); 190 return 0; 191 } 192 193 /***************************** 194 Destination options header. 195 *****************************/ 196 197 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 198 static int ipv6_dest_hao(struct sk_buff *skb, int optoff) 199 { 200 struct ipv6_destopt_hao *hao; 201 struct inet6_skb_parm *opt = IP6CB(skb); 202 struct ipv6hdr *ipv6h = ipv6_hdr(skb); 203 struct in6_addr tmp_addr; 204 int ret; 205 206 if (opt->dsthao) { 207 LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n"); 208 goto discard; 209 } 210 opt->dsthao = opt->dst1; 211 opt->dst1 = 0; 212 213 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff); 214 215 if (hao->length != 16) { 216 LIMIT_NETDEBUG( 217 KERN_DEBUG "hao invalid option length = %d\n", hao->length); 218 goto discard; 219 } 220 221 if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) { 222 LIMIT_NETDEBUG( 223 KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr)); 224 goto discard; 225 } 226 227 ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr, 228 (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS); 229 if (unlikely(ret < 0)) 230 goto discard; 231 232 if (skb_cloned(skb)) { 233 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) 234 goto discard; 235 236 /* update all variable using below by copied skbuff */ 237 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + 238 optoff); 239 ipv6h = ipv6_hdr(skb); 240 } 241 242 if (skb->ip_summed == CHECKSUM_COMPLETE) 243 skb->ip_summed = CHECKSUM_NONE; 244 245 ipv6_addr_copy(&tmp_addr, &ipv6h->saddr); 246 ipv6_addr_copy(&ipv6h->saddr, &hao->addr); 247 ipv6_addr_copy(&hao->addr, &tmp_addr); 248 249 if (skb->tstamp.tv64 == 0) 250 __net_timestamp(skb); 251 252 return 1; 253 254 discard: 255 kfree_skb(skb); 256 return 0; 257 } 258 #endif 259 260 static struct tlvtype_proc tlvprocdestopt_lst[] = { 261 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 262 { 263 .type = IPV6_TLV_HAO, 264 .func = ipv6_dest_hao, 265 }, 266 #endif 267 {-1, NULL} 268 }; 269 270 static int ipv6_destopt_rcv(struct sk_buff *skb) 271 { 272 struct inet6_skb_parm *opt = IP6CB(skb); 273 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 274 __u16 dstbuf; 275 #endif 276 struct dst_entry *dst; 277 278 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || 279 !pskb_may_pull(skb, (skb_transport_offset(skb) + 280 ((skb_transport_header(skb)[1] + 1) << 3)))) { 281 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 282 IPSTATS_MIB_INHDRERRORS); 283 kfree_skb(skb); 284 return -1; 285 } 286 287 opt->lastopt = opt->dst1 = skb_network_header_len(skb); 288 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 289 dstbuf = opt->dst1; 290 #endif 291 292 dst = dst_clone(skb->dst); 293 if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { 294 dst_release(dst); 295 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; 296 opt = IP6CB(skb); 297 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 298 opt->nhoff = dstbuf; 299 #else 300 opt->nhoff = opt->dst1; 301 #endif 302 return 1; 303 } 304 305 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); 306 dst_release(dst); 307 return -1; 308 } 309 310 static struct inet6_protocol destopt_protocol = { 311 .handler = ipv6_destopt_rcv, 312 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR, 313 }; 314 315 void __init ipv6_destopt_init(void) 316 { 317 if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0) 318 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n"); 319 } 320 321 /******************************** 322 NONE header. No data in packet. 323 ********************************/ 324 325 static int ipv6_nodata_rcv(struct sk_buff *skb) 326 { 327 kfree_skb(skb); 328 return 0; 329 } 330 331 static struct inet6_protocol nodata_protocol = { 332 .handler = ipv6_nodata_rcv, 333 .flags = INET6_PROTO_NOPOLICY, 334 }; 335 336 void __init ipv6_nodata_init(void) 337 { 338 if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0) 339 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n"); 340 } 341 342 /******************************** 343 Routing header. 344 ********************************/ 345 346 static int ipv6_rthdr_rcv(struct sk_buff *skb) 347 { 348 struct inet6_skb_parm *opt = IP6CB(skb); 349 struct in6_addr *addr = NULL; 350 struct in6_addr daddr; 351 struct inet6_dev *idev; 352 int n, i; 353 struct ipv6_rt_hdr *hdr; 354 struct rt0_hdr *rthdr; 355 int accept_source_route = ipv6_devconf.accept_source_route; 356 357 idev = in6_dev_get(skb->dev); 358 if (idev) { 359 if (accept_source_route > idev->cnf.accept_source_route) 360 accept_source_route = idev->cnf.accept_source_route; 361 in6_dev_put(idev); 362 } 363 364 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || 365 !pskb_may_pull(skb, (skb_transport_offset(skb) + 366 ((skb_transport_header(skb)[1] + 1) << 3)))) { 367 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 368 IPSTATS_MIB_INHDRERRORS); 369 kfree_skb(skb); 370 return -1; 371 } 372 373 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb); 374 375 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) || 376 skb->pkt_type != PACKET_HOST) { 377 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 378 IPSTATS_MIB_INADDRERRORS); 379 kfree_skb(skb); 380 return -1; 381 } 382 383 looped_back: 384 if (hdr->segments_left == 0) { 385 switch (hdr->type) { 386 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 387 case IPV6_SRCRT_TYPE_2: 388 /* Silently discard type 2 header unless it was 389 * processed by own 390 */ 391 if (!addr) { 392 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 393 IPSTATS_MIB_INADDRERRORS); 394 kfree_skb(skb); 395 return -1; 396 } 397 break; 398 #endif 399 default: 400 break; 401 } 402 403 opt->lastopt = opt->srcrt = skb_network_header_len(skb); 404 skb->transport_header += (hdr->hdrlen + 1) << 3; 405 opt->dst0 = opt->dst1; 406 opt->dst1 = 0; 407 opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb); 408 return 1; 409 } 410 411 switch (hdr->type) { 412 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 413 case IPV6_SRCRT_TYPE_2: 414 if (accept_source_route < 0) 415 goto unknown_rh; 416 /* Silently discard invalid RTH type 2 */ 417 if (hdr->hdrlen != 2 || hdr->segments_left != 1) { 418 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 419 IPSTATS_MIB_INHDRERRORS); 420 kfree_skb(skb); 421 return -1; 422 } 423 break; 424 #endif 425 default: 426 goto unknown_rh; 427 } 428 429 /* 430 * This is the routing header forwarding algorithm from 431 * RFC 2460, page 16. 432 */ 433 434 n = hdr->hdrlen >> 1; 435 436 if (hdr->segments_left > n) { 437 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 438 IPSTATS_MIB_INHDRERRORS); 439 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, 440 ((&hdr->segments_left) - 441 skb_network_header(skb))); 442 return -1; 443 } 444 445 /* We are about to mangle packet header. Be careful! 446 Do not damage packets queued somewhere. 447 */ 448 if (skb_cloned(skb)) { 449 /* the copy is a forwarded packet */ 450 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { 451 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 452 IPSTATS_MIB_OUTDISCARDS); 453 kfree_skb(skb); 454 return -1; 455 } 456 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb); 457 } 458 459 if (skb->ip_summed == CHECKSUM_COMPLETE) 460 skb->ip_summed = CHECKSUM_NONE; 461 462 i = n - --hdr->segments_left; 463 464 rthdr = (struct rt0_hdr *) hdr; 465 addr = rthdr->addr; 466 addr += i - 1; 467 468 switch (hdr->type) { 469 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 470 case IPV6_SRCRT_TYPE_2: 471 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, 472 (xfrm_address_t *)&ipv6_hdr(skb)->saddr, 473 IPPROTO_ROUTING) < 0) { 474 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 475 IPSTATS_MIB_INADDRERRORS); 476 kfree_skb(skb); 477 return -1; 478 } 479 if (!ipv6_chk_home_addr(addr)) { 480 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 481 IPSTATS_MIB_INADDRERRORS); 482 kfree_skb(skb); 483 return -1; 484 } 485 break; 486 #endif 487 default: 488 break; 489 } 490 491 if (ipv6_addr_is_multicast(addr)) { 492 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 493 IPSTATS_MIB_INADDRERRORS); 494 kfree_skb(skb); 495 return -1; 496 } 497 498 ipv6_addr_copy(&daddr, addr); 499 ipv6_addr_copy(addr, &ipv6_hdr(skb)->daddr); 500 ipv6_addr_copy(&ipv6_hdr(skb)->daddr, &daddr); 501 502 dst_release(xchg(&skb->dst, NULL)); 503 ip6_route_input(skb); 504 if (skb->dst->error) { 505 skb_push(skb, skb->data - skb_network_header(skb)); 506 dst_input(skb); 507 return -1; 508 } 509 510 if (skb->dst->dev->flags&IFF_LOOPBACK) { 511 if (ipv6_hdr(skb)->hop_limit <= 1) { 512 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 513 IPSTATS_MIB_INHDRERRORS); 514 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 515 0, skb->dev); 516 kfree_skb(skb); 517 return -1; 518 } 519 ipv6_hdr(skb)->hop_limit--; 520 goto looped_back; 521 } 522 523 skb_push(skb, skb->data - skb_network_header(skb)); 524 dst_input(skb); 525 return -1; 526 527 unknown_rh: 528 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); 529 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, 530 (&hdr->type) - skb_network_header(skb)); 531 return -1; 532 } 533 534 static struct inet6_protocol rthdr_protocol = { 535 .handler = ipv6_rthdr_rcv, 536 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR, 537 }; 538 539 void __init ipv6_rthdr_init(void) 540 { 541 if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0) 542 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n"); 543 }; 544 545 /********************************** 546 Hop-by-hop options. 547 **********************************/ 548 549 /* 550 * Note: we cannot rely on skb->dst before we assign it in ip6_route_input(). 551 */ 552 static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb) 553 { 554 return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev); 555 } 556 557 /* Router Alert as of RFC 2711 */ 558 559 static int ipv6_hop_ra(struct sk_buff *skb, int optoff) 560 { 561 const unsigned char *nh = skb_network_header(skb); 562 563 if (nh[optoff + 1] == 2) { 564 IP6CB(skb)->ra = optoff; 565 return 1; 566 } 567 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", 568 nh[optoff + 1]); 569 kfree_skb(skb); 570 return 0; 571 } 572 573 /* Jumbo payload */ 574 575 static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) 576 { 577 const unsigned char *nh = skb_network_header(skb); 578 u32 pkt_len; 579 580 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) { 581 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", 582 nh[optoff+1]); 583 IP6_INC_STATS_BH(ipv6_skb_idev(skb), 584 IPSTATS_MIB_INHDRERRORS); 585 goto drop; 586 } 587 588 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); 589 if (pkt_len <= IPV6_MAXPLEN) { 590 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS); 591 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); 592 return 0; 593 } 594 if (ipv6_hdr(skb)->payload_len) { 595 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS); 596 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); 597 return 0; 598 } 599 600 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { 601 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS); 602 goto drop; 603 } 604 605 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) 606 goto drop; 607 608 return 1; 609 610 drop: 611 kfree_skb(skb); 612 return 0; 613 } 614 615 static struct tlvtype_proc tlvprochopopt_lst[] = { 616 { 617 .type = IPV6_TLV_ROUTERALERT, 618 .func = ipv6_hop_ra, 619 }, 620 { 621 .type = IPV6_TLV_JUMBO, 622 .func = ipv6_hop_jumbo, 623 }, 624 { -1, } 625 }; 626 627 int ipv6_parse_hopopts(struct sk_buff *skb) 628 { 629 struct inet6_skb_parm *opt = IP6CB(skb); 630 631 /* 632 * skb_network_header(skb) is equal to skb->data, and 633 * skb_network_header_len(skb) is always equal to 634 * sizeof(struct ipv6hdr) by definition of 635 * hop-by-hop options. 636 */ 637 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) || 638 !pskb_may_pull(skb, (sizeof(struct ipv6hdr) + 639 ((skb_transport_header(skb)[1] + 1) << 3)))) { 640 kfree_skb(skb); 641 return -1; 642 } 643 644 opt->hop = sizeof(struct ipv6hdr); 645 if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { 646 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; 647 opt = IP6CB(skb); 648 opt->nhoff = sizeof(struct ipv6hdr); 649 return 1; 650 } 651 return -1; 652 } 653 654 /* 655 * Creating outbound headers. 656 * 657 * "build" functions work when skb is filled from head to tail (datagram) 658 * "push" functions work when headers are added from tail to head (tcp) 659 * 660 * In both cases we assume, that caller reserved enough room 661 * for headers. 662 */ 663 664 static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto, 665 struct ipv6_rt_hdr *opt, 666 struct in6_addr **addr_p) 667 { 668 struct rt0_hdr *phdr, *ihdr; 669 int hops; 670 671 ihdr = (struct rt0_hdr *) opt; 672 673 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3); 674 memcpy(phdr, ihdr, sizeof(struct rt0_hdr)); 675 676 hops = ihdr->rt_hdr.hdrlen >> 1; 677 678 if (hops > 1) 679 memcpy(phdr->addr, ihdr->addr + 1, 680 (hops - 1) * sizeof(struct in6_addr)); 681 682 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p); 683 *addr_p = ihdr->addr; 684 685 phdr->rt_hdr.nexthdr = *proto; 686 *proto = NEXTHDR_ROUTING; 687 } 688 689 static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt) 690 { 691 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt)); 692 693 memcpy(h, opt, ipv6_optlen(opt)); 694 h->nexthdr = *proto; 695 *proto = type; 696 } 697 698 void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, 699 u8 *proto, 700 struct in6_addr **daddr) 701 { 702 if (opt->srcrt) { 703 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr); 704 /* 705 * IPV6_RTHDRDSTOPTS is ignored 706 * unless IPV6_RTHDR is set (RFC3542). 707 */ 708 if (opt->dst0opt) 709 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt); 710 } 711 if (opt->hopopt) 712 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt); 713 } 714 715 EXPORT_SYMBOL(ipv6_push_nfrag_opts); 716 717 void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto) 718 { 719 if (opt->dst1opt) 720 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt); 721 } 722 723 struct ipv6_txoptions * 724 ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt) 725 { 726 struct ipv6_txoptions *opt2; 727 728 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC); 729 if (opt2) { 730 long dif = (char*)opt2 - (char*)opt; 731 memcpy(opt2, opt, opt->tot_len); 732 if (opt2->hopopt) 733 *((char**)&opt2->hopopt) += dif; 734 if (opt2->dst0opt) 735 *((char**)&opt2->dst0opt) += dif; 736 if (opt2->dst1opt) 737 *((char**)&opt2->dst1opt) += dif; 738 if (opt2->srcrt) 739 *((char**)&opt2->srcrt) += dif; 740 } 741 return opt2; 742 } 743 744 EXPORT_SYMBOL_GPL(ipv6_dup_options); 745 746 static int ipv6_renew_option(void *ohdr, 747 struct ipv6_opt_hdr __user *newopt, int newoptlen, 748 int inherit, 749 struct ipv6_opt_hdr **hdr, 750 char **p) 751 { 752 if (inherit) { 753 if (ohdr) { 754 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr)); 755 *hdr = (struct ipv6_opt_hdr *)*p; 756 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr)); 757 } 758 } else { 759 if (newopt) { 760 if (copy_from_user(*p, newopt, newoptlen)) 761 return -EFAULT; 762 *hdr = (struct ipv6_opt_hdr *)*p; 763 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen) 764 return -EINVAL; 765 *p += CMSG_ALIGN(newoptlen); 766 } 767 } 768 return 0; 769 } 770 771 struct ipv6_txoptions * 772 ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, 773 int newtype, 774 struct ipv6_opt_hdr __user *newopt, int newoptlen) 775 { 776 int tot_len = 0; 777 char *p; 778 struct ipv6_txoptions *opt2; 779 int err; 780 781 if (opt) { 782 if (newtype != IPV6_HOPOPTS && opt->hopopt) 783 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt)); 784 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt) 785 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt)); 786 if (newtype != IPV6_RTHDR && opt->srcrt) 787 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt)); 788 if (newtype != IPV6_DSTOPTS && opt->dst1opt) 789 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt)); 790 } 791 792 if (newopt && newoptlen) 793 tot_len += CMSG_ALIGN(newoptlen); 794 795 if (!tot_len) 796 return NULL; 797 798 tot_len += sizeof(*opt2); 799 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC); 800 if (!opt2) 801 return ERR_PTR(-ENOBUFS); 802 803 memset(opt2, 0, tot_len); 804 805 opt2->tot_len = tot_len; 806 p = (char *)(opt2 + 1); 807 808 err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen, 809 newtype != IPV6_HOPOPTS, 810 &opt2->hopopt, &p); 811 if (err) 812 goto out; 813 814 err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen, 815 newtype != IPV6_RTHDRDSTOPTS, 816 &opt2->dst0opt, &p); 817 if (err) 818 goto out; 819 820 err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen, 821 newtype != IPV6_RTHDR, 822 (struct ipv6_opt_hdr **)&opt2->srcrt, &p); 823 if (err) 824 goto out; 825 826 err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen, 827 newtype != IPV6_DSTOPTS, 828 &opt2->dst1opt, &p); 829 if (err) 830 goto out; 831 832 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) + 833 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) + 834 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0); 835 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0); 836 837 return opt2; 838 out: 839 sock_kfree_s(sk, opt2, opt2->tot_len); 840 return ERR_PTR(err); 841 } 842 843 struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space, 844 struct ipv6_txoptions *opt) 845 { 846 /* 847 * ignore the dest before srcrt unless srcrt is being included. 848 * --yoshfuji 849 */ 850 if (opt && opt->dst0opt && !opt->srcrt) { 851 if (opt_space != opt) { 852 memcpy(opt_space, opt, sizeof(*opt_space)); 853 opt = opt_space; 854 } 855 opt->opt_nflen -= ipv6_optlen(opt->dst0opt); 856 opt->dst0opt = NULL; 857 } 858 859 return opt; 860 } 861 862