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