1 /* 2 * IPv6 BSD socket options interface 3 * Linux INET6 implementation 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * Based on linux/net/ipv4/ip_sockglue.c 9 * 10 * $Id: ipv6_sockglue.c,v 1.41 2002/02/01 22:01:04 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 * FIXME: Make the setsockopt code POSIX compliant: That is 18 * 19 * o Return -EINVAL for setsockopt of short lengths 20 * o Truncate getsockopt returns 21 * o Return an optlen of the truncated length if need be 22 * 23 * Changes: 24 * David L Stevens <dlstevens@us.ibm.com>: 25 * - added multicast source filtering API for MLDv2 26 */ 27 28 #include <linux/module.h> 29 #include <linux/capability.h> 30 #include <linux/config.h> 31 #include <linux/errno.h> 32 #include <linux/types.h> 33 #include <linux/socket.h> 34 #include <linux/sockios.h> 35 #include <linux/sched.h> 36 #include <linux/net.h> 37 #include <linux/in6.h> 38 #include <linux/netdevice.h> 39 #include <linux/if_arp.h> 40 #include <linux/init.h> 41 #include <linux/sysctl.h> 42 #include <linux/netfilter.h> 43 44 #include <net/sock.h> 45 #include <net/snmp.h> 46 #include <net/ipv6.h> 47 #include <net/ndisc.h> 48 #include <net/protocol.h> 49 #include <net/transp_v6.h> 50 #include <net/ip6_route.h> 51 #include <net/addrconf.h> 52 #include <net/inet_common.h> 53 #include <net/tcp.h> 54 #include <net/udp.h> 55 #include <net/xfrm.h> 56 57 #include <asm/uaccess.h> 58 59 DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly; 60 61 static struct packet_type ipv6_packet_type = { 62 .type = __constant_htons(ETH_P_IPV6), 63 .func = ipv6_rcv, 64 }; 65 66 struct ip6_ra_chain *ip6_ra_chain; 67 DEFINE_RWLOCK(ip6_ra_lock); 68 69 int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) 70 { 71 struct ip6_ra_chain *ra, *new_ra, **rap; 72 73 /* RA packet may be delivered ONLY to IPPROTO_RAW socket */ 74 if (sk->sk_type != SOCK_RAW || inet_sk(sk)->num != IPPROTO_RAW) 75 return -EINVAL; 76 77 new_ra = (sel>=0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; 78 79 write_lock_bh(&ip6_ra_lock); 80 for (rap = &ip6_ra_chain; (ra=*rap) != NULL; rap = &ra->next) { 81 if (ra->sk == sk) { 82 if (sel>=0) { 83 write_unlock_bh(&ip6_ra_lock); 84 kfree(new_ra); 85 return -EADDRINUSE; 86 } 87 88 *rap = ra->next; 89 write_unlock_bh(&ip6_ra_lock); 90 91 if (ra->destructor) 92 ra->destructor(sk); 93 sock_put(sk); 94 kfree(ra); 95 return 0; 96 } 97 } 98 if (new_ra == NULL) { 99 write_unlock_bh(&ip6_ra_lock); 100 return -ENOBUFS; 101 } 102 new_ra->sk = sk; 103 new_ra->sel = sel; 104 new_ra->destructor = destructor; 105 new_ra->next = ra; 106 *rap = new_ra; 107 sock_hold(sk); 108 write_unlock_bh(&ip6_ra_lock); 109 return 0; 110 } 111 112 static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, 113 char __user *optval, int optlen) 114 { 115 struct ipv6_pinfo *np = inet6_sk(sk); 116 int val, valbool; 117 int retv = -ENOPROTOOPT; 118 119 if (optval == NULL) 120 val=0; 121 else if (get_user(val, (int __user *) optval)) 122 return -EFAULT; 123 124 valbool = (val!=0); 125 126 lock_sock(sk); 127 128 switch (optname) { 129 130 case IPV6_ADDRFORM: 131 if (val == PF_INET) { 132 struct ipv6_txoptions *opt; 133 struct sk_buff *pktopt; 134 135 if (sk->sk_protocol != IPPROTO_UDP && 136 sk->sk_protocol != IPPROTO_TCP) 137 break; 138 139 if (sk->sk_state != TCP_ESTABLISHED) { 140 retv = -ENOTCONN; 141 break; 142 } 143 144 if (ipv6_only_sock(sk) || 145 !(ipv6_addr_type(&np->daddr) & IPV6_ADDR_MAPPED)) { 146 retv = -EADDRNOTAVAIL; 147 break; 148 } 149 150 fl6_free_socklist(sk); 151 ipv6_sock_mc_close(sk); 152 153 /* 154 * Sock is moving from IPv6 to IPv4 (sk_prot), so 155 * remove it from the refcnt debug socks count in the 156 * original family... 157 */ 158 sk_refcnt_debug_dec(sk); 159 160 if (sk->sk_protocol == IPPROTO_TCP) { 161 struct inet_connection_sock *icsk = inet_csk(sk); 162 163 local_bh_disable(); 164 sock_prot_dec_use(sk->sk_prot); 165 sock_prot_inc_use(&tcp_prot); 166 local_bh_enable(); 167 sk->sk_prot = &tcp_prot; 168 icsk->icsk_af_ops = &ipv4_specific; 169 sk->sk_socket->ops = &inet_stream_ops; 170 sk->sk_family = PF_INET; 171 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); 172 } else { 173 local_bh_disable(); 174 sock_prot_dec_use(sk->sk_prot); 175 sock_prot_inc_use(&udp_prot); 176 local_bh_enable(); 177 sk->sk_prot = &udp_prot; 178 sk->sk_socket->ops = &inet_dgram_ops; 179 sk->sk_family = PF_INET; 180 } 181 opt = xchg(&np->opt, NULL); 182 if (opt) 183 sock_kfree_s(sk, opt, opt->tot_len); 184 pktopt = xchg(&np->pktoptions, NULL); 185 if (pktopt) 186 kfree_skb(pktopt); 187 188 sk->sk_destruct = inet_sock_destruct; 189 /* 190 * ... and add it to the refcnt debug socks count 191 * in the new family. -acme 192 */ 193 sk_refcnt_debug_inc(sk); 194 module_put(THIS_MODULE); 195 retv = 0; 196 break; 197 } 198 goto e_inval; 199 200 case IPV6_V6ONLY: 201 if (inet_sk(sk)->num) 202 goto e_inval; 203 np->ipv6only = valbool; 204 retv = 0; 205 break; 206 207 case IPV6_RECVPKTINFO: 208 np->rxopt.bits.rxinfo = valbool; 209 retv = 0; 210 break; 211 212 case IPV6_2292PKTINFO: 213 np->rxopt.bits.rxoinfo = valbool; 214 retv = 0; 215 break; 216 217 case IPV6_RECVHOPLIMIT: 218 np->rxopt.bits.rxhlim = valbool; 219 retv = 0; 220 break; 221 222 case IPV6_2292HOPLIMIT: 223 np->rxopt.bits.rxohlim = valbool; 224 retv = 0; 225 break; 226 227 case IPV6_RECVRTHDR: 228 if (val < 0 || val > 2) 229 goto e_inval; 230 np->rxopt.bits.srcrt = val; 231 retv = 0; 232 break; 233 234 case IPV6_2292RTHDR: 235 if (val < 0 || val > 2) 236 goto e_inval; 237 np->rxopt.bits.osrcrt = val; 238 retv = 0; 239 break; 240 241 case IPV6_RECVHOPOPTS: 242 np->rxopt.bits.hopopts = valbool; 243 retv = 0; 244 break; 245 246 case IPV6_2292HOPOPTS: 247 np->rxopt.bits.ohopopts = valbool; 248 retv = 0; 249 break; 250 251 case IPV6_RECVDSTOPTS: 252 np->rxopt.bits.dstopts = valbool; 253 retv = 0; 254 break; 255 256 case IPV6_2292DSTOPTS: 257 np->rxopt.bits.odstopts = valbool; 258 retv = 0; 259 break; 260 261 case IPV6_TCLASS: 262 if (val < 0 || val > 0xff) 263 goto e_inval; 264 np->tclass = val; 265 retv = 0; 266 break; 267 268 case IPV6_RECVTCLASS: 269 np->rxopt.bits.rxtclass = valbool; 270 retv = 0; 271 break; 272 273 case IPV6_FLOWINFO: 274 np->rxopt.bits.rxflow = valbool; 275 retv = 0; 276 break; 277 278 case IPV6_HOPOPTS: 279 case IPV6_RTHDRDSTOPTS: 280 case IPV6_RTHDR: 281 case IPV6_DSTOPTS: 282 { 283 struct ipv6_txoptions *opt; 284 if (optlen == 0) 285 optval = NULL; 286 287 /* hop-by-hop / destination options are privileged option */ 288 retv = -EPERM; 289 if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) 290 break; 291 292 retv = -EINVAL; 293 if (optlen & 0x7 || optlen > 8 * 255) 294 break; 295 296 opt = ipv6_renew_options(sk, np->opt, optname, 297 (struct ipv6_opt_hdr __user *)optval, 298 optlen); 299 if (IS_ERR(opt)) { 300 retv = PTR_ERR(opt); 301 break; 302 } 303 304 /* routing header option needs extra check */ 305 if (optname == IPV6_RTHDR && opt->srcrt) { 306 struct ipv6_rt_hdr *rthdr = opt->srcrt; 307 if (rthdr->type) 308 goto sticky_done; 309 if ((rthdr->hdrlen & 1) || 310 (rthdr->hdrlen >> 1) != rthdr->segments_left) 311 goto sticky_done; 312 } 313 314 retv = 0; 315 if (inet_sk(sk)->is_icsk) { 316 if (opt) { 317 struct inet_connection_sock *icsk = inet_csk(sk); 318 if (!((1 << sk->sk_state) & 319 (TCPF_LISTEN | TCPF_CLOSE)) 320 && inet_sk(sk)->daddr != LOOPBACK4_IPV6) { 321 icsk->icsk_ext_hdr_len = 322 opt->opt_flen + opt->opt_nflen; 323 icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); 324 } 325 } 326 opt = xchg(&np->opt, opt); 327 sk_dst_reset(sk); 328 } else { 329 write_lock(&sk->sk_dst_lock); 330 opt = xchg(&np->opt, opt); 331 write_unlock(&sk->sk_dst_lock); 332 sk_dst_reset(sk); 333 } 334 sticky_done: 335 if (opt) 336 sock_kfree_s(sk, opt, opt->tot_len); 337 break; 338 } 339 340 case IPV6_2292PKTOPTIONS: 341 { 342 struct ipv6_txoptions *opt = NULL; 343 struct msghdr msg; 344 struct flowi fl; 345 int junk; 346 347 fl.fl6_flowlabel = 0; 348 fl.oif = sk->sk_bound_dev_if; 349 350 if (optlen == 0) 351 goto update; 352 353 /* 1K is probably excessive 354 * 1K is surely not enough, 2K per standard header is 16K. 355 */ 356 retv = -EINVAL; 357 if (optlen > 64*1024) 358 break; 359 360 opt = sock_kmalloc(sk, sizeof(*opt) + optlen, GFP_KERNEL); 361 retv = -ENOBUFS; 362 if (opt == NULL) 363 break; 364 365 memset(opt, 0, sizeof(*opt)); 366 opt->tot_len = sizeof(*opt) + optlen; 367 retv = -EFAULT; 368 if (copy_from_user(opt+1, optval, optlen)) 369 goto done; 370 371 msg.msg_controllen = optlen; 372 msg.msg_control = (void*)(opt+1); 373 374 retv = datagram_send_ctl(&msg, &fl, opt, &junk, &junk); 375 if (retv) 376 goto done; 377 update: 378 retv = 0; 379 if (inet_sk(sk)->is_icsk) { 380 if (opt) { 381 struct inet_connection_sock *icsk = inet_csk(sk); 382 if (!((1 << sk->sk_state) & 383 (TCPF_LISTEN | TCPF_CLOSE)) 384 && inet_sk(sk)->daddr != LOOPBACK4_IPV6) { 385 icsk->icsk_ext_hdr_len = 386 opt->opt_flen + opt->opt_nflen; 387 icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); 388 } 389 } 390 opt = xchg(&np->opt, opt); 391 sk_dst_reset(sk); 392 } else { 393 write_lock(&sk->sk_dst_lock); 394 opt = xchg(&np->opt, opt); 395 write_unlock(&sk->sk_dst_lock); 396 sk_dst_reset(sk); 397 } 398 399 done: 400 if (opt) 401 sock_kfree_s(sk, opt, opt->tot_len); 402 break; 403 } 404 case IPV6_UNICAST_HOPS: 405 if (val > 255 || val < -1) 406 goto e_inval; 407 np->hop_limit = val; 408 retv = 0; 409 break; 410 411 case IPV6_MULTICAST_HOPS: 412 if (sk->sk_type == SOCK_STREAM) 413 goto e_inval; 414 if (val > 255 || val < -1) 415 goto e_inval; 416 np->mcast_hops = val; 417 retv = 0; 418 break; 419 420 case IPV6_MULTICAST_LOOP: 421 np->mc_loop = valbool; 422 retv = 0; 423 break; 424 425 case IPV6_MULTICAST_IF: 426 if (sk->sk_type == SOCK_STREAM) 427 goto e_inval; 428 if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) 429 goto e_inval; 430 431 if (__dev_get_by_index(val) == NULL) { 432 retv = -ENODEV; 433 break; 434 } 435 np->mcast_oif = val; 436 retv = 0; 437 break; 438 case IPV6_ADD_MEMBERSHIP: 439 case IPV6_DROP_MEMBERSHIP: 440 { 441 struct ipv6_mreq mreq; 442 443 retv = -EFAULT; 444 if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq))) 445 break; 446 447 if (optname == IPV6_ADD_MEMBERSHIP) 448 retv = ipv6_sock_mc_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr); 449 else 450 retv = ipv6_sock_mc_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr); 451 break; 452 } 453 case IPV6_JOIN_ANYCAST: 454 case IPV6_LEAVE_ANYCAST: 455 { 456 struct ipv6_mreq mreq; 457 458 if (optlen != sizeof(struct ipv6_mreq)) 459 goto e_inval; 460 461 retv = -EFAULT; 462 if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq))) 463 break; 464 465 if (optname == IPV6_JOIN_ANYCAST) 466 retv = ipv6_sock_ac_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr); 467 else 468 retv = ipv6_sock_ac_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr); 469 break; 470 } 471 case MCAST_JOIN_GROUP: 472 case MCAST_LEAVE_GROUP: 473 { 474 struct group_req greq; 475 struct sockaddr_in6 *psin6; 476 477 retv = -EFAULT; 478 if (copy_from_user(&greq, optval, sizeof(struct group_req))) 479 break; 480 if (greq.gr_group.ss_family != AF_INET6) { 481 retv = -EADDRNOTAVAIL; 482 break; 483 } 484 psin6 = (struct sockaddr_in6 *)&greq.gr_group; 485 if (optname == MCAST_JOIN_GROUP) 486 retv = ipv6_sock_mc_join(sk, greq.gr_interface, 487 &psin6->sin6_addr); 488 else 489 retv = ipv6_sock_mc_drop(sk, greq.gr_interface, 490 &psin6->sin6_addr); 491 break; 492 } 493 case MCAST_JOIN_SOURCE_GROUP: 494 case MCAST_LEAVE_SOURCE_GROUP: 495 case MCAST_BLOCK_SOURCE: 496 case MCAST_UNBLOCK_SOURCE: 497 { 498 struct group_source_req greqs; 499 int omode, add; 500 501 if (optlen != sizeof(struct group_source_req)) 502 goto e_inval; 503 if (copy_from_user(&greqs, optval, sizeof(greqs))) { 504 retv = -EFAULT; 505 break; 506 } 507 if (greqs.gsr_group.ss_family != AF_INET6 || 508 greqs.gsr_source.ss_family != AF_INET6) { 509 retv = -EADDRNOTAVAIL; 510 break; 511 } 512 if (optname == MCAST_BLOCK_SOURCE) { 513 omode = MCAST_EXCLUDE; 514 add = 1; 515 } else if (optname == MCAST_UNBLOCK_SOURCE) { 516 omode = MCAST_EXCLUDE; 517 add = 0; 518 } else if (optname == MCAST_JOIN_SOURCE_GROUP) { 519 struct sockaddr_in6 *psin6; 520 521 psin6 = (struct sockaddr_in6 *)&greqs.gsr_group; 522 retv = ipv6_sock_mc_join(sk, greqs.gsr_interface, 523 &psin6->sin6_addr); 524 /* prior join w/ different source is ok */ 525 if (retv && retv != -EADDRINUSE) 526 break; 527 omode = MCAST_INCLUDE; 528 add = 1; 529 } else /* MCAST_LEAVE_SOURCE_GROUP */ { 530 omode = MCAST_INCLUDE; 531 add = 0; 532 } 533 retv = ip6_mc_source(add, omode, sk, &greqs); 534 break; 535 } 536 case MCAST_MSFILTER: 537 { 538 extern int sysctl_mld_max_msf; 539 struct group_filter *gsf; 540 541 if (optlen < GROUP_FILTER_SIZE(0)) 542 goto e_inval; 543 if (optlen > sysctl_optmem_max) { 544 retv = -ENOBUFS; 545 break; 546 } 547 gsf = kmalloc(optlen,GFP_KERNEL); 548 if (gsf == 0) { 549 retv = -ENOBUFS; 550 break; 551 } 552 retv = -EFAULT; 553 if (copy_from_user(gsf, optval, optlen)) { 554 kfree(gsf); 555 break; 556 } 557 /* numsrc >= (4G-140)/128 overflow in 32 bits */ 558 if (gsf->gf_numsrc >= 0x1ffffffU || 559 gsf->gf_numsrc > sysctl_mld_max_msf) { 560 kfree(gsf); 561 retv = -ENOBUFS; 562 break; 563 } 564 if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) { 565 kfree(gsf); 566 retv = -EINVAL; 567 break; 568 } 569 retv = ip6_mc_msfilter(sk, gsf); 570 kfree(gsf); 571 572 break; 573 } 574 case IPV6_ROUTER_ALERT: 575 retv = ip6_ra_control(sk, val, NULL); 576 break; 577 case IPV6_MTU_DISCOVER: 578 if (val<0 || val>2) 579 goto e_inval; 580 np->pmtudisc = val; 581 retv = 0; 582 break; 583 case IPV6_MTU: 584 if (val && val < IPV6_MIN_MTU) 585 goto e_inval; 586 np->frag_size = val; 587 retv = 0; 588 break; 589 case IPV6_RECVERR: 590 np->recverr = valbool; 591 if (!val) 592 skb_queue_purge(&sk->sk_error_queue); 593 retv = 0; 594 break; 595 case IPV6_FLOWINFO_SEND: 596 np->sndflow = valbool; 597 retv = 0; 598 break; 599 case IPV6_FLOWLABEL_MGR: 600 retv = ipv6_flowlabel_opt(sk, optval, optlen); 601 break; 602 case IPV6_IPSEC_POLICY: 603 case IPV6_XFRM_POLICY: 604 retv = -EPERM; 605 if (!capable(CAP_NET_ADMIN)) 606 break; 607 retv = xfrm_user_policy(sk, optname, optval, optlen); 608 break; 609 610 } 611 release_sock(sk); 612 613 return retv; 614 615 e_inval: 616 release_sock(sk); 617 return -EINVAL; 618 } 619 620 int ipv6_setsockopt(struct sock *sk, int level, int optname, 621 char __user *optval, int optlen) 622 { 623 int err; 624 625 if (level == SOL_IP && sk->sk_type != SOCK_RAW) 626 return udp_prot.setsockopt(sk, level, optname, optval, optlen); 627 628 if (level != SOL_IPV6) 629 return -ENOPROTOOPT; 630 631 err = do_ipv6_setsockopt(sk, level, optname, optval, optlen); 632 #ifdef CONFIG_NETFILTER 633 /* we need to exclude all possible ENOPROTOOPTs except default case */ 634 if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && 635 optname != IPV6_XFRM_POLICY) { 636 lock_sock(sk); 637 err = nf_setsockopt(sk, PF_INET6, optname, optval, 638 optlen); 639 release_sock(sk); 640 } 641 #endif 642 return err; 643 } 644 645 646 #ifdef CONFIG_COMPAT 647 int compat_ipv6_setsockopt(struct sock *sk, int level, int optname, 648 char __user *optval, int optlen) 649 { 650 int err; 651 652 if (level == SOL_IP && sk->sk_type != SOCK_RAW) { 653 if (udp_prot.compat_setsockopt != NULL) 654 return udp_prot.compat_setsockopt(sk, level, optname, 655 optval, optlen); 656 return udp_prot.setsockopt(sk, level, optname, optval, optlen); 657 } 658 659 if (level != SOL_IPV6) 660 return -ENOPROTOOPT; 661 662 err = do_ipv6_setsockopt(sk, level, optname, optval, optlen); 663 #ifdef CONFIG_NETFILTER 664 /* we need to exclude all possible ENOPROTOOPTs except default case */ 665 if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && 666 optname != IPV6_XFRM_POLICY) { 667 lock_sock(sk); 668 err = compat_nf_setsockopt(sk, PF_INET6, optname, 669 optval, optlen); 670 release_sock(sk); 671 } 672 #endif 673 return err; 674 } 675 676 EXPORT_SYMBOL(compat_ipv6_setsockopt); 677 #endif 678 679 static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, 680 char __user *optval, int len) 681 { 682 if (!hdr) 683 return 0; 684 len = min_t(int, len, ipv6_optlen(hdr)); 685 if (copy_to_user(optval, hdr, ipv6_optlen(hdr))) 686 return -EFAULT; 687 return len; 688 } 689 690 static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, 691 char __user *optval, int __user *optlen) 692 { 693 struct ipv6_pinfo *np = inet6_sk(sk); 694 int len; 695 int val; 696 697 if (get_user(len, optlen)) 698 return -EFAULT; 699 switch (optname) { 700 case IPV6_ADDRFORM: 701 if (sk->sk_protocol != IPPROTO_UDP && 702 sk->sk_protocol != IPPROTO_TCP) 703 return -EINVAL; 704 if (sk->sk_state != TCP_ESTABLISHED) 705 return -ENOTCONN; 706 val = sk->sk_family; 707 break; 708 case MCAST_MSFILTER: 709 { 710 struct group_filter gsf; 711 int err; 712 713 if (len < GROUP_FILTER_SIZE(0)) 714 return -EINVAL; 715 if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) 716 return -EFAULT; 717 lock_sock(sk); 718 err = ip6_mc_msfget(sk, &gsf, 719 (struct group_filter __user *)optval, optlen); 720 release_sock(sk); 721 return err; 722 } 723 724 case IPV6_2292PKTOPTIONS: 725 { 726 struct msghdr msg; 727 struct sk_buff *skb; 728 729 if (sk->sk_type != SOCK_STREAM) 730 return -ENOPROTOOPT; 731 732 msg.msg_control = optval; 733 msg.msg_controllen = len; 734 msg.msg_flags = 0; 735 736 lock_sock(sk); 737 skb = np->pktoptions; 738 if (skb) 739 atomic_inc(&skb->users); 740 release_sock(sk); 741 742 if (skb) { 743 int err = datagram_recv_ctl(sk, &msg, skb); 744 kfree_skb(skb); 745 if (err) 746 return err; 747 } else { 748 if (np->rxopt.bits.rxinfo) { 749 struct in6_pktinfo src_info; 750 src_info.ipi6_ifindex = np->mcast_oif; 751 ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr); 752 put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); 753 } 754 if (np->rxopt.bits.rxhlim) { 755 int hlim = np->mcast_hops; 756 put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); 757 } 758 if (np->rxopt.bits.rxoinfo) { 759 struct in6_pktinfo src_info; 760 src_info.ipi6_ifindex = np->mcast_oif; 761 ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr); 762 put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); 763 } 764 if (np->rxopt.bits.rxohlim) { 765 int hlim = np->mcast_hops; 766 put_cmsg(&msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim); 767 } 768 } 769 len -= msg.msg_controllen; 770 return put_user(len, optlen); 771 } 772 case IPV6_MTU: 773 { 774 struct dst_entry *dst; 775 val = 0; 776 lock_sock(sk); 777 dst = sk_dst_get(sk); 778 if (dst) { 779 val = dst_mtu(dst); 780 dst_release(dst); 781 } 782 release_sock(sk); 783 if (!val) 784 return -ENOTCONN; 785 break; 786 } 787 788 case IPV6_V6ONLY: 789 val = np->ipv6only; 790 break; 791 792 case IPV6_RECVPKTINFO: 793 val = np->rxopt.bits.rxinfo; 794 break; 795 796 case IPV6_2292PKTINFO: 797 val = np->rxopt.bits.rxoinfo; 798 break; 799 800 case IPV6_RECVHOPLIMIT: 801 val = np->rxopt.bits.rxhlim; 802 break; 803 804 case IPV6_2292HOPLIMIT: 805 val = np->rxopt.bits.rxohlim; 806 break; 807 808 case IPV6_RECVRTHDR: 809 val = np->rxopt.bits.srcrt; 810 break; 811 812 case IPV6_2292RTHDR: 813 val = np->rxopt.bits.osrcrt; 814 break; 815 816 case IPV6_HOPOPTS: 817 case IPV6_RTHDRDSTOPTS: 818 case IPV6_RTHDR: 819 case IPV6_DSTOPTS: 820 { 821 822 lock_sock(sk); 823 len = ipv6_getsockopt_sticky(sk, np->opt->hopopt, 824 optval, len); 825 release_sock(sk); 826 return put_user(len, optlen); 827 } 828 829 case IPV6_RECVHOPOPTS: 830 val = np->rxopt.bits.hopopts; 831 break; 832 833 case IPV6_2292HOPOPTS: 834 val = np->rxopt.bits.ohopopts; 835 break; 836 837 case IPV6_RECVDSTOPTS: 838 val = np->rxopt.bits.dstopts; 839 break; 840 841 case IPV6_2292DSTOPTS: 842 val = np->rxopt.bits.odstopts; 843 break; 844 845 case IPV6_TCLASS: 846 val = np->tclass; 847 break; 848 849 case IPV6_RECVTCLASS: 850 val = np->rxopt.bits.rxtclass; 851 break; 852 853 case IPV6_FLOWINFO: 854 val = np->rxopt.bits.rxflow; 855 break; 856 857 case IPV6_UNICAST_HOPS: 858 val = np->hop_limit; 859 break; 860 861 case IPV6_MULTICAST_HOPS: 862 val = np->mcast_hops; 863 break; 864 865 case IPV6_MULTICAST_LOOP: 866 val = np->mc_loop; 867 break; 868 869 case IPV6_MULTICAST_IF: 870 val = np->mcast_oif; 871 break; 872 873 case IPV6_MTU_DISCOVER: 874 val = np->pmtudisc; 875 break; 876 877 case IPV6_RECVERR: 878 val = np->recverr; 879 break; 880 881 case IPV6_FLOWINFO_SEND: 882 val = np->sndflow; 883 break; 884 885 default: 886 return -EINVAL; 887 } 888 len = min_t(unsigned int, sizeof(int), len); 889 if(put_user(len, optlen)) 890 return -EFAULT; 891 if(copy_to_user(optval,&val,len)) 892 return -EFAULT; 893 return 0; 894 } 895 896 int ipv6_getsockopt(struct sock *sk, int level, int optname, 897 char __user *optval, int __user *optlen) 898 { 899 int err; 900 901 if (level == SOL_IP && sk->sk_type != SOCK_RAW) 902 return udp_prot.getsockopt(sk, level, optname, optval, optlen); 903 904 if(level != SOL_IPV6) 905 return -ENOPROTOOPT; 906 907 err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); 908 #ifdef CONFIG_NETFILTER 909 /* we need to exclude all possible EINVALs except default case */ 910 if (err == -EINVAL && optname != IPV6_ADDRFORM && 911 optname != MCAST_MSFILTER) { 912 int len; 913 914 if (get_user(len, optlen)) 915 return -EFAULT; 916 917 lock_sock(sk); 918 err = nf_getsockopt(sk, PF_INET6, optname, optval, 919 &len); 920 release_sock(sk); 921 if (err >= 0) 922 err = put_user(len, optlen); 923 } 924 #endif 925 return err; 926 } 927 928 #ifdef CONFIG_COMPAT 929 int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, 930 char __user *optval, int __user *optlen) 931 { 932 int err; 933 934 if (level == SOL_IP && sk->sk_type != SOCK_RAW) { 935 if (udp_prot.compat_getsockopt != NULL) 936 return udp_prot.compat_getsockopt(sk, level, optname, 937 optval, optlen); 938 return udp_prot.getsockopt(sk, level, optname, optval, optlen); 939 } 940 941 if (level != SOL_IPV6) 942 return -ENOPROTOOPT; 943 944 err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); 945 #ifdef CONFIG_NETFILTER 946 /* we need to exclude all possible EINVALs except default case */ 947 if (err == -EINVAL && optname != IPV6_ADDRFORM && 948 optname != MCAST_MSFILTER) { 949 int len; 950 951 if (get_user(len, optlen)) 952 return -EFAULT; 953 954 lock_sock(sk); 955 err = compat_nf_getsockopt(sk, PF_INET6, 956 optname, optval, &len); 957 release_sock(sk); 958 if (err >= 0) 959 err = put_user(len, optlen); 960 } 961 #endif 962 return err; 963 } 964 965 EXPORT_SYMBOL(compat_ipv6_getsockopt); 966 #endif 967 968 void __init ipv6_packet_init(void) 969 { 970 dev_add_pack(&ipv6_packet_type); 971 } 972 973 void ipv6_packet_cleanup(void) 974 { 975 dev_remove_pack(&ipv6_packet_type); 976 } 977