Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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