ipv6_sockglue.c revision c29a0bc4dfc4d833eb702b1929cec96a3eeb9f7a
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 = sock_net(sk); 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 struct net *net = sock_net(sk); 159 160 local_bh_disable(); 161 sock_prot_inuse_add(net, sk->sk_prot, -1); 162 sock_prot_inuse_add(net, &tcp_prot, 1); 163 local_bh_enable(); 164 sk->sk_prot = &tcp_prot; 165 icsk->icsk_af_ops = &ipv4_specific; 166 sk->sk_socket->ops = &inet_stream_ops; 167 sk->sk_family = PF_INET; 168 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); 169 } else { 170 struct proto *prot = &udp_prot; 171 struct net *net = sock_net(sk); 172 173 if (sk->sk_protocol == IPPROTO_UDPLITE) 174 prot = &udplite_prot; 175 local_bh_disable(); 176 sock_prot_inuse_add(net, sk->sk_prot, -1); 177 sock_prot_inuse_add(net, prot, 1); 178 local_bh_enable(); 179 sk->sk_prot = prot; 180 sk->sk_socket->ops = &inet_dgram_ops; 181 sk->sk_family = PF_INET; 182 } 183 opt = xchg(&np->opt, NULL); 184 if (opt) 185 sock_kfree_s(sk, opt, opt->tot_len); 186 pktopt = xchg(&np->pktoptions, NULL); 187 if (pktopt) 188 kfree_skb(pktopt); 189 190 sk->sk_destruct = inet_sock_destruct; 191 /* 192 * ... and add it to the refcnt debug socks count 193 * in the new family. -acme 194 */ 195 sk_refcnt_debug_inc(sk); 196 module_put(THIS_MODULE); 197 retv = 0; 198 break; 199 } 200 goto e_inval; 201 202 case IPV6_V6ONLY: 203 if (inet_sk(sk)->num) 204 goto e_inval; 205 np->ipv6only = valbool; 206 retv = 0; 207 break; 208 209 case IPV6_RECVPKTINFO: 210 np->rxopt.bits.rxinfo = valbool; 211 retv = 0; 212 break; 213 214 case IPV6_2292PKTINFO: 215 np->rxopt.bits.rxoinfo = valbool; 216 retv = 0; 217 break; 218 219 case IPV6_RECVHOPLIMIT: 220 np->rxopt.bits.rxhlim = valbool; 221 retv = 0; 222 break; 223 224 case IPV6_2292HOPLIMIT: 225 np->rxopt.bits.rxohlim = valbool; 226 retv = 0; 227 break; 228 229 case IPV6_RECVRTHDR: 230 np->rxopt.bits.srcrt = valbool; 231 retv = 0; 232 break; 233 234 case IPV6_2292RTHDR: 235 np->rxopt.bits.osrcrt = valbool; 236 retv = 0; 237 break; 238 239 case IPV6_RECVHOPOPTS: 240 np->rxopt.bits.hopopts = valbool; 241 retv = 0; 242 break; 243 244 case IPV6_2292HOPOPTS: 245 np->rxopt.bits.ohopopts = valbool; 246 retv = 0; 247 break; 248 249 case IPV6_RECVDSTOPTS: 250 np->rxopt.bits.dstopts = valbool; 251 retv = 0; 252 break; 253 254 case IPV6_2292DSTOPTS: 255 np->rxopt.bits.odstopts = valbool; 256 retv = 0; 257 break; 258 259 case IPV6_TCLASS: 260 if (val < -1 || val > 0xff) 261 goto e_inval; 262 np->tclass = val; 263 retv = 0; 264 break; 265 266 case IPV6_RECVTCLASS: 267 np->rxopt.bits.rxtclass = valbool; 268 retv = 0; 269 break; 270 271 case IPV6_FLOWINFO: 272 np->rxopt.bits.rxflow = valbool; 273 retv = 0; 274 break; 275 276 case IPV6_HOPOPTS: 277 case IPV6_RTHDRDSTOPTS: 278 case IPV6_RTHDR: 279 case IPV6_DSTOPTS: 280 { 281 struct ipv6_txoptions *opt; 282 if (optlen == 0) 283 optval = NULL; 284 285 /* hop-by-hop / destination options are privileged option */ 286 retv = -EPERM; 287 if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) 288 break; 289 290 retv = -EINVAL; 291 if (optlen & 0x7 || optlen > 8 * 255) 292 break; 293 294 opt = ipv6_renew_options(sk, np->opt, optname, 295 (struct ipv6_opt_hdr __user *)optval, 296 optlen); 297 if (IS_ERR(opt)) { 298 retv = PTR_ERR(opt); 299 break; 300 } 301 302 /* routing header option needs extra check */ 303 if (optname == IPV6_RTHDR && opt && opt->srcrt) { 304 struct ipv6_rt_hdr *rthdr = opt->srcrt; 305 switch (rthdr->type) { 306#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 307 case IPV6_SRCRT_TYPE_2: 308 break; 309#endif 310 default: 311 goto sticky_done; 312 } 313 314 if ((rthdr->hdrlen & 1) || 315 (rthdr->hdrlen >> 1) != rthdr->segments_left) 316 goto sticky_done; 317 } 318 319 retv = 0; 320 if (inet_sk(sk)->is_icsk) { 321 if (opt) { 322 struct inet_connection_sock *icsk = inet_csk(sk); 323 if (!((1 << sk->sk_state) & 324 (TCPF_LISTEN | TCPF_CLOSE)) 325 && inet_sk(sk)->daddr != LOOPBACK4_IPV6) { 326 icsk->icsk_ext_hdr_len = 327 opt->opt_flen + opt->opt_nflen; 328 icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); 329 } 330 } 331 opt = xchg(&np->opt, opt); 332 sk_dst_reset(sk); 333 } else { 334 write_lock(&sk->sk_dst_lock); 335 opt = xchg(&np->opt, opt); 336 write_unlock(&sk->sk_dst_lock); 337 sk_dst_reset(sk); 338 } 339sticky_done: 340 if (opt) 341 sock_kfree_s(sk, opt, opt->tot_len); 342 break; 343 } 344 345 case IPV6_2292PKTOPTIONS: 346 { 347 struct ipv6_txoptions *opt = NULL; 348 struct msghdr msg; 349 struct flowi fl; 350 int junk; 351 352 fl.fl6_flowlabel = 0; 353 fl.oif = sk->sk_bound_dev_if; 354 355 if (optlen == 0) 356 goto update; 357 358 /* 1K is probably excessive 359 * 1K is surely not enough, 2K per standard header is 16K. 360 */ 361 retv = -EINVAL; 362 if (optlen > 64*1024) 363 break; 364 365 opt = sock_kmalloc(sk, sizeof(*opt) + optlen, GFP_KERNEL); 366 retv = -ENOBUFS; 367 if (opt == NULL) 368 break; 369 370 memset(opt, 0, sizeof(*opt)); 371 opt->tot_len = sizeof(*opt) + optlen; 372 retv = -EFAULT; 373 if (copy_from_user(opt+1, optval, optlen)) 374 goto done; 375 376 msg.msg_controllen = optlen; 377 msg.msg_control = (void*)(opt+1); 378 379 retv = datagram_send_ctl(&msg, &fl, opt, &junk, &junk); 380 if (retv) 381 goto done; 382update: 383 retv = 0; 384 if (inet_sk(sk)->is_icsk) { 385 if (opt) { 386 struct inet_connection_sock *icsk = inet_csk(sk); 387 if (!((1 << sk->sk_state) & 388 (TCPF_LISTEN | TCPF_CLOSE)) 389 && inet_sk(sk)->daddr != LOOPBACK4_IPV6) { 390 icsk->icsk_ext_hdr_len = 391 opt->opt_flen + opt->opt_nflen; 392 icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); 393 } 394 } 395 opt = xchg(&np->opt, opt); 396 sk_dst_reset(sk); 397 } else { 398 write_lock(&sk->sk_dst_lock); 399 opt = xchg(&np->opt, opt); 400 write_unlock(&sk->sk_dst_lock); 401 sk_dst_reset(sk); 402 } 403 404done: 405 if (opt) 406 sock_kfree_s(sk, opt, opt->tot_len); 407 break; 408 } 409 case IPV6_UNICAST_HOPS: 410 if (val > 255 || val < -1) 411 goto e_inval; 412 np->hop_limit = val; 413 retv = 0; 414 break; 415 416 case IPV6_MULTICAST_HOPS: 417 if (sk->sk_type == SOCK_STREAM) 418 goto e_inval; 419 if (val > 255 || val < -1) 420 goto e_inval; 421 np->mcast_hops = val; 422 retv = 0; 423 break; 424 425 case IPV6_MULTICAST_LOOP: 426 np->mc_loop = valbool; 427 retv = 0; 428 break; 429 430 case IPV6_MULTICAST_IF: 431 if (sk->sk_type == SOCK_STREAM) 432 goto e_inval; 433 434 if (val) { 435 if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) 436 goto e_inval; 437 438 if (__dev_get_by_index(net, val) == NULL) { 439 retv = -ENODEV; 440 break; 441 } 442 } 443 np->mcast_oif = val; 444 retv = 0; 445 break; 446 case IPV6_ADD_MEMBERSHIP: 447 case IPV6_DROP_MEMBERSHIP: 448 { 449 struct ipv6_mreq mreq; 450 451 retv = -EPROTO; 452 if (inet_sk(sk)->is_icsk) 453 break; 454 455 retv = -EFAULT; 456 if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq))) 457 break; 458 459 if (optname == IPV6_ADD_MEMBERSHIP) 460 retv = ipv6_sock_mc_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr); 461 else 462 retv = ipv6_sock_mc_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr); 463 break; 464 } 465 case IPV6_JOIN_ANYCAST: 466 case IPV6_LEAVE_ANYCAST: 467 { 468 struct ipv6_mreq mreq; 469 470 if (optlen != sizeof(struct ipv6_mreq)) 471 goto e_inval; 472 473 retv = -EFAULT; 474 if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq))) 475 break; 476 477 if (optname == IPV6_JOIN_ANYCAST) 478 retv = ipv6_sock_ac_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr); 479 else 480 retv = ipv6_sock_ac_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr); 481 break; 482 } 483 case MCAST_JOIN_GROUP: 484 case MCAST_LEAVE_GROUP: 485 { 486 struct group_req greq; 487 struct sockaddr_in6 *psin6; 488 489 retv = -EFAULT; 490 if (copy_from_user(&greq, optval, sizeof(struct group_req))) 491 break; 492 if (greq.gr_group.ss_family != AF_INET6) { 493 retv = -EADDRNOTAVAIL; 494 break; 495 } 496 psin6 = (struct sockaddr_in6 *)&greq.gr_group; 497 if (optname == MCAST_JOIN_GROUP) 498 retv = ipv6_sock_mc_join(sk, greq.gr_interface, 499 &psin6->sin6_addr); 500 else 501 retv = ipv6_sock_mc_drop(sk, greq.gr_interface, 502 &psin6->sin6_addr); 503 break; 504 } 505 case MCAST_JOIN_SOURCE_GROUP: 506 case MCAST_LEAVE_SOURCE_GROUP: 507 case MCAST_BLOCK_SOURCE: 508 case MCAST_UNBLOCK_SOURCE: 509 { 510 struct group_source_req greqs; 511 int omode, add; 512 513 if (optlen != sizeof(struct group_source_req)) 514 goto e_inval; 515 if (copy_from_user(&greqs, optval, sizeof(greqs))) { 516 retv = -EFAULT; 517 break; 518 } 519 if (greqs.gsr_group.ss_family != AF_INET6 || 520 greqs.gsr_source.ss_family != AF_INET6) { 521 retv = -EADDRNOTAVAIL; 522 break; 523 } 524 if (optname == MCAST_BLOCK_SOURCE) { 525 omode = MCAST_EXCLUDE; 526 add = 1; 527 } else if (optname == MCAST_UNBLOCK_SOURCE) { 528 omode = MCAST_EXCLUDE; 529 add = 0; 530 } else if (optname == MCAST_JOIN_SOURCE_GROUP) { 531 struct sockaddr_in6 *psin6; 532 533 psin6 = (struct sockaddr_in6 *)&greqs.gsr_group; 534 retv = ipv6_sock_mc_join(sk, greqs.gsr_interface, 535 &psin6->sin6_addr); 536 /* prior join w/ different source is ok */ 537 if (retv && retv != -EADDRINUSE) 538 break; 539 omode = MCAST_INCLUDE; 540 add = 1; 541 } else /* MCAST_LEAVE_SOURCE_GROUP */ { 542 omode = MCAST_INCLUDE; 543 add = 0; 544 } 545 retv = ip6_mc_source(add, omode, sk, &greqs); 546 break; 547 } 548 case MCAST_MSFILTER: 549 { 550 extern int sysctl_mld_max_msf; 551 struct group_filter *gsf; 552 553 if (optlen < GROUP_FILTER_SIZE(0)) 554 goto e_inval; 555 if (optlen > sysctl_optmem_max) { 556 retv = -ENOBUFS; 557 break; 558 } 559 gsf = kmalloc(optlen,GFP_KERNEL); 560 if (!gsf) { 561 retv = -ENOBUFS; 562 break; 563 } 564 retv = -EFAULT; 565 if (copy_from_user(gsf, optval, optlen)) { 566 kfree(gsf); 567 break; 568 } 569 /* numsrc >= (4G-140)/128 overflow in 32 bits */ 570 if (gsf->gf_numsrc >= 0x1ffffffU || 571 gsf->gf_numsrc > sysctl_mld_max_msf) { 572 kfree(gsf); 573 retv = -ENOBUFS; 574 break; 575 } 576 if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) { 577 kfree(gsf); 578 retv = -EINVAL; 579 break; 580 } 581 retv = ip6_mc_msfilter(sk, gsf); 582 kfree(gsf); 583 584 break; 585 } 586 case IPV6_ROUTER_ALERT: 587 retv = ip6_ra_control(sk, val, NULL); 588 break; 589 case IPV6_MTU_DISCOVER: 590 if (val<0 || val>3) 591 goto e_inval; 592 np->pmtudisc = val; 593 retv = 0; 594 break; 595 case IPV6_MTU: 596 if (val && val < IPV6_MIN_MTU) 597 goto e_inval; 598 np->frag_size = val; 599 retv = 0; 600 break; 601 case IPV6_RECVERR: 602 np->recverr = valbool; 603 if (!val) 604 skb_queue_purge(&sk->sk_error_queue); 605 retv = 0; 606 break; 607 case IPV6_FLOWINFO_SEND: 608 np->sndflow = valbool; 609 retv = 0; 610 break; 611 case IPV6_FLOWLABEL_MGR: 612 retv = ipv6_flowlabel_opt(sk, optval, optlen); 613 break; 614 case IPV6_IPSEC_POLICY: 615 case IPV6_XFRM_POLICY: 616 retv = -EPERM; 617 if (!capable(CAP_NET_ADMIN)) 618 break; 619 retv = xfrm_user_policy(sk, optname, optval, optlen); 620 break; 621 622 case IPV6_ADDR_PREFERENCES: 623 { 624 unsigned int pref = 0; 625 unsigned int prefmask = ~0; 626 627 retv = -EINVAL; 628 629 /* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */ 630 switch (val & (IPV6_PREFER_SRC_PUBLIC| 631 IPV6_PREFER_SRC_TMP| 632 IPV6_PREFER_SRC_PUBTMP_DEFAULT)) { 633 case IPV6_PREFER_SRC_PUBLIC: 634 pref |= IPV6_PREFER_SRC_PUBLIC; 635 break; 636 case IPV6_PREFER_SRC_TMP: 637 pref |= IPV6_PREFER_SRC_TMP; 638 break; 639 case IPV6_PREFER_SRC_PUBTMP_DEFAULT: 640 break; 641 case 0: 642 goto pref_skip_pubtmp; 643 default: 644 goto e_inval; 645 } 646 647 prefmask &= ~(IPV6_PREFER_SRC_PUBLIC| 648 IPV6_PREFER_SRC_TMP); 649pref_skip_pubtmp: 650 651 /* check HOME/COA conflicts */ 652 switch (val & (IPV6_PREFER_SRC_HOME|IPV6_PREFER_SRC_COA)) { 653 case IPV6_PREFER_SRC_HOME: 654 break; 655 case IPV6_PREFER_SRC_COA: 656 pref |= IPV6_PREFER_SRC_COA; 657 case 0: 658 goto pref_skip_coa; 659 default: 660 goto e_inval; 661 } 662 663 prefmask &= ~IPV6_PREFER_SRC_COA; 664pref_skip_coa: 665 666 /* check CGA/NONCGA conflicts */ 667 switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) { 668 case IPV6_PREFER_SRC_CGA: 669 case IPV6_PREFER_SRC_NONCGA: 670 case 0: 671 break; 672 default: 673 goto e_inval; 674 } 675 676 np->srcprefs = (np->srcprefs & prefmask) | pref; 677 retv = 0; 678 679 break; 680 } 681 } 682 683 release_sock(sk); 684 685 return retv; 686 687e_inval: 688 release_sock(sk); 689 return -EINVAL; 690} 691 692int ipv6_setsockopt(struct sock *sk, int level, int optname, 693 char __user *optval, int optlen) 694{ 695 int err; 696 697 if (level == SOL_IP && sk->sk_type != SOCK_RAW) 698 return udp_prot.setsockopt(sk, level, optname, optval, optlen); 699 700 if (level != SOL_IPV6) 701 return -ENOPROTOOPT; 702 703 err = do_ipv6_setsockopt(sk, level, optname, optval, optlen); 704#ifdef CONFIG_NETFILTER 705 /* we need to exclude all possible ENOPROTOOPTs except default case */ 706 if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && 707 optname != IPV6_XFRM_POLICY) { 708 lock_sock(sk); 709 err = nf_setsockopt(sk, PF_INET6, optname, optval, 710 optlen); 711 release_sock(sk); 712 } 713#endif 714 return err; 715} 716 717EXPORT_SYMBOL(ipv6_setsockopt); 718 719#ifdef CONFIG_COMPAT 720int compat_ipv6_setsockopt(struct sock *sk, int level, int optname, 721 char __user *optval, int optlen) 722{ 723 int err; 724 725 if (level == SOL_IP && sk->sk_type != SOCK_RAW) { 726 if (udp_prot.compat_setsockopt != NULL) 727 return udp_prot.compat_setsockopt(sk, level, optname, 728 optval, optlen); 729 return udp_prot.setsockopt(sk, level, optname, optval, optlen); 730 } 731 732 if (level != SOL_IPV6) 733 return -ENOPROTOOPT; 734 735 err = do_ipv6_setsockopt(sk, level, optname, optval, optlen); 736#ifdef CONFIG_NETFILTER 737 /* we need to exclude all possible ENOPROTOOPTs except default case */ 738 if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && 739 optname != IPV6_XFRM_POLICY) { 740 lock_sock(sk); 741 err = compat_nf_setsockopt(sk, PF_INET6, optname, 742 optval, optlen); 743 release_sock(sk); 744 } 745#endif 746 return err; 747} 748 749EXPORT_SYMBOL(compat_ipv6_setsockopt); 750#endif 751 752static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, 753 int optname, char __user *optval, int len) 754{ 755 struct ipv6_opt_hdr *hdr; 756 757 if (!opt) 758 return 0; 759 760 switch(optname) { 761 case IPV6_HOPOPTS: 762 hdr = opt->hopopt; 763 break; 764 case IPV6_RTHDRDSTOPTS: 765 hdr = opt->dst0opt; 766 break; 767 case IPV6_RTHDR: 768 hdr = (struct ipv6_opt_hdr *)opt->srcrt; 769 break; 770 case IPV6_DSTOPTS: 771 hdr = opt->dst1opt; 772 break; 773 default: 774 return -EINVAL; /* should not happen */ 775 } 776 777 if (!hdr) 778 return 0; 779 780 len = min_t(unsigned int, len, ipv6_optlen(hdr)); 781 if (copy_to_user(optval, hdr, len)) 782 return -EFAULT; 783 return ipv6_optlen(hdr); 784} 785 786static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, 787 char __user *optval, int __user *optlen) 788{ 789 struct ipv6_pinfo *np = inet6_sk(sk); 790 int len; 791 int val; 792 793 if (get_user(len, optlen)) 794 return -EFAULT; 795 switch (optname) { 796 case IPV6_ADDRFORM: 797 if (sk->sk_protocol != IPPROTO_UDP && 798 sk->sk_protocol != IPPROTO_UDPLITE && 799 sk->sk_protocol != IPPROTO_TCP) 800 return -EINVAL; 801 if (sk->sk_state != TCP_ESTABLISHED) 802 return -ENOTCONN; 803 val = sk->sk_family; 804 break; 805 case MCAST_MSFILTER: 806 { 807 struct group_filter gsf; 808 int err; 809 810 if (len < GROUP_FILTER_SIZE(0)) 811 return -EINVAL; 812 if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) 813 return -EFAULT; 814 lock_sock(sk); 815 err = ip6_mc_msfget(sk, &gsf, 816 (struct group_filter __user *)optval, optlen); 817 release_sock(sk); 818 return err; 819 } 820 821 case IPV6_2292PKTOPTIONS: 822 { 823 struct msghdr msg; 824 struct sk_buff *skb; 825 826 if (sk->sk_type != SOCK_STREAM) 827 return -ENOPROTOOPT; 828 829 msg.msg_control = optval; 830 msg.msg_controllen = len; 831 msg.msg_flags = 0; 832 833 lock_sock(sk); 834 skb = np->pktoptions; 835 if (skb) 836 atomic_inc(&skb->users); 837 release_sock(sk); 838 839 if (skb) { 840 int err = datagram_recv_ctl(sk, &msg, skb); 841 kfree_skb(skb); 842 if (err) 843 return err; 844 } else { 845 if (np->rxopt.bits.rxinfo) { 846 struct in6_pktinfo src_info; 847 src_info.ipi6_ifindex = np->mcast_oif; 848 ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr); 849 put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); 850 } 851 if (np->rxopt.bits.rxhlim) { 852 int hlim = np->mcast_hops; 853 put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); 854 } 855 if (np->rxopt.bits.rxoinfo) { 856 struct in6_pktinfo src_info; 857 src_info.ipi6_ifindex = np->mcast_oif; 858 ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr); 859 put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); 860 } 861 if (np->rxopt.bits.rxohlim) { 862 int hlim = np->mcast_hops; 863 put_cmsg(&msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim); 864 } 865 } 866 len -= msg.msg_controllen; 867 return put_user(len, optlen); 868 } 869 case IPV6_MTU: 870 { 871 struct dst_entry *dst; 872 val = 0; 873 lock_sock(sk); 874 dst = sk_dst_get(sk); 875 if (dst) { 876 val = dst_mtu(dst); 877 dst_release(dst); 878 } 879 release_sock(sk); 880 if (!val) 881 return -ENOTCONN; 882 break; 883 } 884 885 case IPV6_V6ONLY: 886 val = np->ipv6only; 887 break; 888 889 case IPV6_RECVPKTINFO: 890 val = np->rxopt.bits.rxinfo; 891 break; 892 893 case IPV6_2292PKTINFO: 894 val = np->rxopt.bits.rxoinfo; 895 break; 896 897 case IPV6_RECVHOPLIMIT: 898 val = np->rxopt.bits.rxhlim; 899 break; 900 901 case IPV6_2292HOPLIMIT: 902 val = np->rxopt.bits.rxohlim; 903 break; 904 905 case IPV6_RECVRTHDR: 906 val = np->rxopt.bits.srcrt; 907 break; 908 909 case IPV6_2292RTHDR: 910 val = np->rxopt.bits.osrcrt; 911 break; 912 913 case IPV6_HOPOPTS: 914 case IPV6_RTHDRDSTOPTS: 915 case IPV6_RTHDR: 916 case IPV6_DSTOPTS: 917 { 918 919 lock_sock(sk); 920 len = ipv6_getsockopt_sticky(sk, np->opt, 921 optname, optval, len); 922 release_sock(sk); 923 return put_user(len, optlen); 924 } 925 926 case IPV6_RECVHOPOPTS: 927 val = np->rxopt.bits.hopopts; 928 break; 929 930 case IPV6_2292HOPOPTS: 931 val = np->rxopt.bits.ohopopts; 932 break; 933 934 case IPV6_RECVDSTOPTS: 935 val = np->rxopt.bits.dstopts; 936 break; 937 938 case IPV6_2292DSTOPTS: 939 val = np->rxopt.bits.odstopts; 940 break; 941 942 case IPV6_TCLASS: 943 val = np->tclass; 944 if (val < 0) 945 val = 0; 946 break; 947 948 case IPV6_RECVTCLASS: 949 val = np->rxopt.bits.rxtclass; 950 break; 951 952 case IPV6_FLOWINFO: 953 val = np->rxopt.bits.rxflow; 954 break; 955 956 case IPV6_UNICAST_HOPS: 957 case IPV6_MULTICAST_HOPS: 958 { 959 struct dst_entry *dst; 960 961 if (optname == IPV6_UNICAST_HOPS) 962 val = np->hop_limit; 963 else 964 val = np->mcast_hops; 965 966 dst = sk_dst_get(sk); 967 if (dst) { 968 if (val < 0) 969 val = ip6_dst_hoplimit(dst); 970 dst_release(dst); 971 } 972 if (val < 0) 973 val = ipv6_devconf.hop_limit; 974 break; 975 } 976 977 case IPV6_MULTICAST_LOOP: 978 val = np->mc_loop; 979 break; 980 981 case IPV6_MULTICAST_IF: 982 val = np->mcast_oif; 983 break; 984 985 case IPV6_MTU_DISCOVER: 986 val = np->pmtudisc; 987 break; 988 989 case IPV6_RECVERR: 990 val = np->recverr; 991 break; 992 993 case IPV6_FLOWINFO_SEND: 994 val = np->sndflow; 995 break; 996 997 case IPV6_ADDR_PREFERENCES: 998 val = 0; 999 1000 if (np->srcprefs & IPV6_PREFER_SRC_TMP) 1001 val |= IPV6_PREFER_SRC_TMP; 1002 else if (np->srcprefs & IPV6_PREFER_SRC_PUBLIC) 1003 val |= IPV6_PREFER_SRC_PUBLIC; 1004 else { 1005 /* XXX: should we return system default? */ 1006 val |= IPV6_PREFER_SRC_PUBTMP_DEFAULT; 1007 } 1008 1009 if (np->srcprefs & IPV6_PREFER_SRC_COA) 1010 val |= IPV6_PREFER_SRC_COA; 1011 else 1012 val |= IPV6_PREFER_SRC_HOME; 1013 break; 1014 1015 default: 1016 return -ENOPROTOOPT; 1017 } 1018 len = min_t(unsigned int, sizeof(int), len); 1019 if(put_user(len, optlen)) 1020 return -EFAULT; 1021 if(copy_to_user(optval,&val,len)) 1022 return -EFAULT; 1023 return 0; 1024} 1025 1026int ipv6_getsockopt(struct sock *sk, int level, int optname, 1027 char __user *optval, int __user *optlen) 1028{ 1029 int err; 1030 1031 if (level == SOL_IP && sk->sk_type != SOCK_RAW) 1032 return udp_prot.getsockopt(sk, level, optname, optval, optlen); 1033 1034 if(level != SOL_IPV6) 1035 return -ENOPROTOOPT; 1036 1037 err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); 1038#ifdef CONFIG_NETFILTER 1039 /* we need to exclude all possible ENOPROTOOPTs except default case */ 1040 if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) { 1041 int len; 1042 1043 if (get_user(len, optlen)) 1044 return -EFAULT; 1045 1046 lock_sock(sk); 1047 err = nf_getsockopt(sk, PF_INET6, optname, optval, 1048 &len); 1049 release_sock(sk); 1050 if (err >= 0) 1051 err = put_user(len, optlen); 1052 } 1053#endif 1054 return err; 1055} 1056 1057EXPORT_SYMBOL(ipv6_getsockopt); 1058 1059#ifdef CONFIG_COMPAT 1060int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, 1061 char __user *optval, int __user *optlen) 1062{ 1063 int err; 1064 1065 if (level == SOL_IP && sk->sk_type != SOCK_RAW) { 1066 if (udp_prot.compat_getsockopt != NULL) 1067 return udp_prot.compat_getsockopt(sk, level, optname, 1068 optval, optlen); 1069 return udp_prot.getsockopt(sk, level, optname, optval, optlen); 1070 } 1071 1072 if (level != SOL_IPV6) 1073 return -ENOPROTOOPT; 1074 1075 err = do_ipv6_getsockopt(sk, level, optname, optval, optlen); 1076#ifdef CONFIG_NETFILTER 1077 /* we need to exclude all possible ENOPROTOOPTs except default case */ 1078 if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) { 1079 int len; 1080 1081 if (get_user(len, optlen)) 1082 return -EFAULT; 1083 1084 lock_sock(sk); 1085 err = compat_nf_getsockopt(sk, PF_INET6, 1086 optname, optval, &len); 1087 release_sock(sk); 1088 if (err >= 0) 1089 err = put_user(len, optlen); 1090 } 1091#endif 1092 return err; 1093} 1094 1095EXPORT_SYMBOL(compat_ipv6_getsockopt); 1096#endif 1097 1098