linux/net/ipv6/ipv6_sockglue.c
<<
>>
Prefs
   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#include <linux/slab.h>
  40
  41#include <net/sock.h>
  42#include <net/snmp.h>
  43#include <net/ipv6.h>
  44#include <net/ndisc.h>
  45#include <net/protocol.h>
  46#include <net/transp_v6.h>
  47#include <net/ip6_route.h>
  48#include <net/addrconf.h>
  49#include <net/inet_common.h>
  50#include <net/tcp.h>
  51#include <net/udp.h>
  52#include <net/udplite.h>
  53#include <net/xfrm.h>
  54#include <net/compat.h>
  55#include <net/seg6.h>
  56
  57#include <linux/uaccess.h>
  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)->inet_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) {
  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
 102struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
 103                                           struct ipv6_txoptions *opt)
 104{
 105        if (inet_sk(sk)->is_icsk) {
 106                if (opt &&
 107                    !((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
 108                    inet_sk(sk)->inet_daddr != LOOPBACK4_IPV6) {
 109                        struct inet_connection_sock *icsk = inet_csk(sk);
 110                        icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen;
 111                        icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
 112                }
 113        }
 114        opt = xchg((__force struct ipv6_txoptions **)&inet6_sk(sk)->opt,
 115                   opt);
 116        sk_dst_reset(sk);
 117
 118        return opt;
 119}
 120
 121static bool setsockopt_needs_rtnl(int optname)
 122{
 123        switch (optname) {
 124        case IPV6_ADDRFORM:
 125        case IPV6_ADD_MEMBERSHIP:
 126        case IPV6_DROP_MEMBERSHIP:
 127        case IPV6_JOIN_ANYCAST:
 128        case IPV6_LEAVE_ANYCAST:
 129        case MCAST_JOIN_GROUP:
 130        case MCAST_LEAVE_GROUP:
 131        case MCAST_JOIN_SOURCE_GROUP:
 132        case MCAST_LEAVE_SOURCE_GROUP:
 133        case MCAST_BLOCK_SOURCE:
 134        case MCAST_UNBLOCK_SOURCE:
 135        case MCAST_MSFILTER:
 136                return true;
 137        }
 138        return false;
 139}
 140
 141static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
 142                    char __user *optval, unsigned int optlen)
 143{
 144        struct ipv6_pinfo *np = inet6_sk(sk);
 145        struct net *net = sock_net(sk);
 146        int val, valbool;
 147        int retv = -ENOPROTOOPT;
 148        bool needs_rtnl = setsockopt_needs_rtnl(optname);
 149
 150        if (!optval)
 151                val = 0;
 152        else {
 153                if (optlen >= sizeof(int)) {
 154                        if (get_user(val, (int __user *) optval))
 155                                return -EFAULT;
 156                } else
 157                        val = 0;
 158        }
 159
 160        valbool = (val != 0);
 161
 162        if (ip6_mroute_opt(optname))
 163                return ip6_mroute_setsockopt(sk, optname, optval, optlen);
 164
 165        if (needs_rtnl)
 166                rtnl_lock();
 167        lock_sock(sk);
 168
 169        switch (optname) {
 170
 171        case IPV6_ADDRFORM:
 172                if (optlen < sizeof(int))
 173                        goto e_inval;
 174                if (val == PF_INET) {
 175                        struct ipv6_txoptions *opt;
 176                        struct sk_buff *pktopt;
 177
 178                        if (sk->sk_type == SOCK_RAW)
 179                                break;
 180
 181                        if (sk->sk_protocol == IPPROTO_UDP ||
 182                            sk->sk_protocol == IPPROTO_UDPLITE) {
 183                                struct udp_sock *up = udp_sk(sk);
 184                                if (up->pending == AF_INET6) {
 185                                        retv = -EBUSY;
 186                                        break;
 187                                }
 188                        } else if (sk->sk_protocol != IPPROTO_TCP)
 189                                break;
 190
 191                        if (sk->sk_state != TCP_ESTABLISHED) {
 192                                retv = -ENOTCONN;
 193                                break;
 194                        }
 195
 196                        if (ipv6_only_sock(sk) ||
 197                            !ipv6_addr_v4mapped(&sk->sk_v6_daddr)) {
 198                                retv = -EADDRNOTAVAIL;
 199                                break;
 200                        }
 201
 202                        fl6_free_socklist(sk);
 203                        __ipv6_sock_mc_close(sk);
 204
 205                        /*
 206                         * Sock is moving from IPv6 to IPv4 (sk_prot), so
 207                         * remove it from the refcnt debug socks count in the
 208                         * original family...
 209                         */
 210                        sk_refcnt_debug_dec(sk);
 211
 212                        if (sk->sk_protocol == IPPROTO_TCP) {
 213                                struct inet_connection_sock *icsk = inet_csk(sk);
 214                                local_bh_disable();
 215                                sock_prot_inuse_add(net, sk->sk_prot, -1);
 216                                sock_prot_inuse_add(net, &tcp_prot, 1);
 217                                local_bh_enable();
 218                                sk->sk_prot = &tcp_prot;
 219                                icsk->icsk_af_ops = &ipv4_specific;
 220                                sk->sk_socket->ops = &inet_stream_ops;
 221                                sk->sk_family = PF_INET;
 222                                tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
 223                        } else {
 224                                struct proto *prot = &udp_prot;
 225
 226                                if (sk->sk_protocol == IPPROTO_UDPLITE)
 227                                        prot = &udplite_prot;
 228                                local_bh_disable();
 229                                sock_prot_inuse_add(net, sk->sk_prot, -1);
 230                                sock_prot_inuse_add(net, prot, 1);
 231                                local_bh_enable();
 232                                sk->sk_prot = prot;
 233                                sk->sk_socket->ops = &inet_dgram_ops;
 234                                sk->sk_family = PF_INET;
 235                        }
 236                        opt = xchg((__force struct ipv6_txoptions **)&np->opt,
 237                                   NULL);
 238                        if (opt) {
 239                                atomic_sub(opt->tot_len, &sk->sk_omem_alloc);
 240                                txopt_put(opt);
 241                        }
 242                        pktopt = xchg(&np->pktoptions, NULL);
 243                        kfree_skb(pktopt);
 244
 245                        /*
 246                         * ... and add it to the refcnt debug socks count
 247                         * in the new family. -acme
 248                         */
 249                        sk_refcnt_debug_inc(sk);
 250                        module_put(THIS_MODULE);
 251                        retv = 0;
 252                        break;
 253                }
 254                goto e_inval;
 255
 256        case IPV6_V6ONLY:
 257                if (optlen < sizeof(int) ||
 258                    inet_sk(sk)->inet_num)
 259                        goto e_inval;
 260                sk->sk_ipv6only = valbool;
 261                retv = 0;
 262                break;
 263
 264        case IPV6_RECVPKTINFO:
 265                if (optlen < sizeof(int))
 266                        goto e_inval;
 267                np->rxopt.bits.rxinfo = valbool;
 268                retv = 0;
 269                break;
 270
 271        case IPV6_2292PKTINFO:
 272                if (optlen < sizeof(int))
 273                        goto e_inval;
 274                np->rxopt.bits.rxoinfo = valbool;
 275                retv = 0;
 276                break;
 277
 278        case IPV6_RECVHOPLIMIT:
 279                if (optlen < sizeof(int))
 280                        goto e_inval;
 281                np->rxopt.bits.rxhlim = valbool;
 282                retv = 0;
 283                break;
 284
 285        case IPV6_2292HOPLIMIT:
 286                if (optlen < sizeof(int))
 287                        goto e_inval;
 288                np->rxopt.bits.rxohlim = valbool;
 289                retv = 0;
 290                break;
 291
 292        case IPV6_RECVRTHDR:
 293                if (optlen < sizeof(int))
 294                        goto e_inval;
 295                np->rxopt.bits.srcrt = valbool;
 296                retv = 0;
 297                break;
 298
 299        case IPV6_2292RTHDR:
 300                if (optlen < sizeof(int))
 301                        goto e_inval;
 302                np->rxopt.bits.osrcrt = valbool;
 303                retv = 0;
 304                break;
 305
 306        case IPV6_RECVHOPOPTS:
 307                if (optlen < sizeof(int))
 308                        goto e_inval;
 309                np->rxopt.bits.hopopts = valbool;
 310                retv = 0;
 311                break;
 312
 313        case IPV6_2292HOPOPTS:
 314                if (optlen < sizeof(int))
 315                        goto e_inval;
 316                np->rxopt.bits.ohopopts = valbool;
 317                retv = 0;
 318                break;
 319
 320        case IPV6_RECVDSTOPTS:
 321                if (optlen < sizeof(int))
 322                        goto e_inval;
 323                np->rxopt.bits.dstopts = valbool;
 324                retv = 0;
 325                break;
 326
 327        case IPV6_2292DSTOPTS:
 328                if (optlen < sizeof(int))
 329                        goto e_inval;
 330                np->rxopt.bits.odstopts = valbool;
 331                retv = 0;
 332                break;
 333
 334        case IPV6_TCLASS:
 335                if (optlen < sizeof(int))
 336                        goto e_inval;
 337                if (val < -1 || val > 0xff)
 338                        goto e_inval;
 339                /* RFC 3542, 6.5: default traffic class of 0x0 */
 340                if (val == -1)
 341                        val = 0;
 342                np->tclass = val;
 343                retv = 0;
 344                break;
 345
 346        case IPV6_RECVTCLASS:
 347                if (optlen < sizeof(int))
 348                        goto e_inval;
 349                np->rxopt.bits.rxtclass = valbool;
 350                retv = 0;
 351                break;
 352
 353        case IPV6_FLOWINFO:
 354                if (optlen < sizeof(int))
 355                        goto e_inval;
 356                np->rxopt.bits.rxflow = valbool;
 357                retv = 0;
 358                break;
 359
 360        case IPV6_RECVPATHMTU:
 361                if (optlen < sizeof(int))
 362                        goto e_inval;
 363                np->rxopt.bits.rxpmtu = valbool;
 364                retv = 0;
 365                break;
 366
 367        case IPV6_TRANSPARENT:
 368                if (valbool && !ns_capable(net->user_ns, CAP_NET_ADMIN) &&
 369                    !ns_capable(net->user_ns, CAP_NET_RAW)) {
 370                        retv = -EPERM;
 371                        break;
 372                }
 373                if (optlen < sizeof(int))
 374                        goto e_inval;
 375                /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
 376                inet_sk(sk)->transparent = valbool;
 377                retv = 0;
 378                break;
 379
 380        case IPV6_FREEBIND:
 381                if (optlen < sizeof(int))
 382                        goto e_inval;
 383                /* we also don't have a separate freebind bit for IPV6 */
 384                inet_sk(sk)->freebind = valbool;
 385                retv = 0;
 386                break;
 387
 388        case IPV6_RECVORIGDSTADDR:
 389                if (optlen < sizeof(int))
 390                        goto e_inval;
 391                np->rxopt.bits.rxorigdstaddr = valbool;
 392                retv = 0;
 393                break;
 394
 395        case IPV6_HOPOPTS:
 396        case IPV6_RTHDRDSTOPTS:
 397        case IPV6_RTHDR:
 398        case IPV6_DSTOPTS:
 399        {
 400                struct ipv6_txoptions *opt;
 401
 402                /* remove any sticky options header with a zero option
 403                 * length, per RFC3542.
 404                 */
 405                if (optlen == 0)
 406                        optval = NULL;
 407                else if (!optval)
 408                        goto e_inval;
 409                else if (optlen < sizeof(struct ipv6_opt_hdr) ||
 410                         optlen & 0x7 || optlen > 8 * 255)
 411                        goto e_inval;
 412
 413                /* hop-by-hop / destination options are privileged option */
 414                retv = -EPERM;
 415                if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW))
 416                        break;
 417
 418                opt = rcu_dereference_protected(np->opt,
 419                                                lockdep_sock_is_held(sk));
 420                opt = ipv6_renew_options(sk, opt, optname,
 421                                         (struct ipv6_opt_hdr __user *)optval,
 422                                         optlen);
 423                if (IS_ERR(opt)) {
 424                        retv = PTR_ERR(opt);
 425                        break;
 426                }
 427
 428                /* routing header option needs extra check */
 429                retv = -EINVAL;
 430                if (optname == IPV6_RTHDR && opt && opt->srcrt) {
 431                        struct ipv6_rt_hdr *rthdr = opt->srcrt;
 432                        switch (rthdr->type) {
 433#if IS_ENABLED(CONFIG_IPV6_MIP6)
 434                        case IPV6_SRCRT_TYPE_2:
 435                                if (rthdr->hdrlen != 2 ||
 436                                    rthdr->segments_left != 1)
 437                                        goto sticky_done;
 438
 439                                break;
 440#endif
 441                        case IPV6_SRCRT_TYPE_4:
 442                        {
 443                                struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)
 444                                                          opt->srcrt;
 445
 446                                if (!seg6_validate_srh(srh, optlen))
 447                                        goto sticky_done;
 448                                break;
 449                        }
 450                        default:
 451                                goto sticky_done;
 452                        }
 453                }
 454
 455                retv = 0;
 456                opt = ipv6_update_options(sk, opt);
 457sticky_done:
 458                if (opt) {
 459                        atomic_sub(opt->tot_len, &sk->sk_omem_alloc);
 460                        txopt_put(opt);
 461                }
 462                break;
 463        }
 464
 465        case IPV6_PKTINFO:
 466        {
 467                struct in6_pktinfo pkt;
 468
 469                if (optlen == 0)
 470                        goto e_inval;
 471                else if (optlen < sizeof(struct in6_pktinfo) || !optval)
 472                        goto e_inval;
 473
 474                if (copy_from_user(&pkt, optval, sizeof(struct in6_pktinfo))) {
 475                                retv = -EFAULT;
 476                                break;
 477                }
 478                if (sk->sk_bound_dev_if && pkt.ipi6_ifindex != sk->sk_bound_dev_if)
 479                        goto e_inval;
 480
 481                np->sticky_pktinfo.ipi6_ifindex = pkt.ipi6_ifindex;
 482                np->sticky_pktinfo.ipi6_addr = pkt.ipi6_addr;
 483                retv = 0;
 484                break;
 485        }
 486
 487        case IPV6_2292PKTOPTIONS:
 488        {
 489                struct ipv6_txoptions *opt = NULL;
 490                struct msghdr msg;
 491                struct flowi6 fl6;
 492                struct sockcm_cookie sockc_junk;
 493                struct ipcm6_cookie ipc6;
 494
 495                memset(&fl6, 0, sizeof(fl6));
 496                fl6.flowi6_oif = sk->sk_bound_dev_if;
 497                fl6.flowi6_mark = sk->sk_mark;
 498
 499                if (optlen == 0)
 500                        goto update;
 501
 502                /* 1K is probably excessive
 503                 * 1K is surely not enough, 2K per standard header is 16K.
 504                 */
 505                retv = -EINVAL;
 506                if (optlen > 64*1024)
 507                        break;
 508
 509                opt = sock_kmalloc(sk, sizeof(*opt) + optlen, GFP_KERNEL);
 510                retv = -ENOBUFS;
 511                if (!opt)
 512                        break;
 513
 514                memset(opt, 0, sizeof(*opt));
 515                refcount_set(&opt->refcnt, 1);
 516                opt->tot_len = sizeof(*opt) + optlen;
 517                retv = -EFAULT;
 518                if (copy_from_user(opt+1, optval, optlen))
 519                        goto done;
 520
 521                msg.msg_controllen = optlen;
 522                msg.msg_control = (void *)(opt+1);
 523                ipc6.opt = opt;
 524
 525                retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, &ipc6, &sockc_junk);
 526                if (retv)
 527                        goto done;
 528update:
 529                retv = 0;
 530                opt = ipv6_update_options(sk, opt);
 531done:
 532                if (opt) {
 533                        atomic_sub(opt->tot_len, &sk->sk_omem_alloc);
 534                        txopt_put(opt);
 535                }
 536                break;
 537        }
 538        case IPV6_UNICAST_HOPS:
 539                if (optlen < sizeof(int))
 540                        goto e_inval;
 541                if (val > 255 || val < -1)
 542                        goto e_inval;
 543                np->hop_limit = val;
 544                retv = 0;
 545                break;
 546
 547        case IPV6_MULTICAST_HOPS:
 548                if (sk->sk_type == SOCK_STREAM)
 549                        break;
 550                if (optlen < sizeof(int))
 551                        goto e_inval;
 552                if (val > 255 || val < -1)
 553                        goto e_inval;
 554                np->mcast_hops = (val == -1 ? IPV6_DEFAULT_MCASTHOPS : val);
 555                retv = 0;
 556                break;
 557
 558        case IPV6_MULTICAST_LOOP:
 559                if (optlen < sizeof(int))
 560                        goto e_inval;
 561                if (val != valbool)
 562                        goto e_inval;
 563                np->mc_loop = valbool;
 564                retv = 0;
 565                break;
 566
 567        case IPV6_UNICAST_IF:
 568        {
 569                struct net_device *dev = NULL;
 570                int ifindex;
 571
 572                if (optlen != sizeof(int))
 573                        goto e_inval;
 574
 575                ifindex = (__force int)ntohl((__force __be32)val);
 576                if (ifindex == 0) {
 577                        np->ucast_oif = 0;
 578                        retv = 0;
 579                        break;
 580                }
 581
 582                dev = dev_get_by_index(net, ifindex);
 583                retv = -EADDRNOTAVAIL;
 584                if (!dev)
 585                        break;
 586                dev_put(dev);
 587
 588                retv = -EINVAL;
 589                if (sk->sk_bound_dev_if)
 590                        break;
 591
 592                np->ucast_oif = ifindex;
 593                retv = 0;
 594                break;
 595        }
 596
 597        case IPV6_MULTICAST_IF:
 598                if (sk->sk_type == SOCK_STREAM)
 599                        break;
 600                if (optlen < sizeof(int))
 601                        goto e_inval;
 602
 603                if (val) {
 604                        struct net_device *dev;
 605                        int midx;
 606
 607                        rcu_read_lock();
 608
 609                        dev = dev_get_by_index_rcu(net, val);
 610                        if (!dev) {
 611                                rcu_read_unlock();
 612                                retv = -ENODEV;
 613                                break;
 614                        }
 615                        midx = l3mdev_master_ifindex_rcu(dev);
 616
 617                        rcu_read_unlock();
 618
 619                        if (sk->sk_bound_dev_if &&
 620                            sk->sk_bound_dev_if != val &&
 621                            (!midx || midx != sk->sk_bound_dev_if))
 622                                goto e_inval;
 623                }
 624                np->mcast_oif = val;
 625                retv = 0;
 626                break;
 627        case IPV6_ADD_MEMBERSHIP:
 628        case IPV6_DROP_MEMBERSHIP:
 629        {
 630                struct ipv6_mreq mreq;
 631
 632                if (optlen < sizeof(struct ipv6_mreq))
 633                        goto e_inval;
 634
 635                retv = -EPROTO;
 636                if (inet_sk(sk)->is_icsk)
 637                        break;
 638
 639                retv = -EFAULT;
 640                if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq)))
 641                        break;
 642
 643                if (optname == IPV6_ADD_MEMBERSHIP)
 644                        retv = ipv6_sock_mc_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
 645                else
 646                        retv = ipv6_sock_mc_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
 647                break;
 648        }
 649        case IPV6_JOIN_ANYCAST:
 650        case IPV6_LEAVE_ANYCAST:
 651        {
 652                struct ipv6_mreq mreq;
 653
 654                if (optlen < sizeof(struct ipv6_mreq))
 655                        goto e_inval;
 656
 657                retv = -EFAULT;
 658                if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq)))
 659                        break;
 660
 661                if (optname == IPV6_JOIN_ANYCAST)
 662                        retv = ipv6_sock_ac_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr);
 663                else
 664                        retv = ipv6_sock_ac_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr);
 665                break;
 666        }
 667        case MCAST_JOIN_GROUP:
 668        case MCAST_LEAVE_GROUP:
 669        {
 670                struct group_req greq;
 671                struct sockaddr_in6 *psin6;
 672
 673                if (optlen < sizeof(struct group_req))
 674                        goto e_inval;
 675
 676                retv = -EFAULT;
 677                if (copy_from_user(&greq, optval, sizeof(struct group_req)))
 678                        break;
 679                if (greq.gr_group.ss_family != AF_INET6) {
 680                        retv = -EADDRNOTAVAIL;
 681                        break;
 682                }
 683                psin6 = (struct sockaddr_in6 *)&greq.gr_group;
 684                if (optname == MCAST_JOIN_GROUP)
 685                        retv = ipv6_sock_mc_join(sk, greq.gr_interface,
 686                                                 &psin6->sin6_addr);
 687                else
 688                        retv = ipv6_sock_mc_drop(sk, greq.gr_interface,
 689                                                 &psin6->sin6_addr);
 690                break;
 691        }
 692        case MCAST_JOIN_SOURCE_GROUP:
 693        case MCAST_LEAVE_SOURCE_GROUP:
 694        case MCAST_BLOCK_SOURCE:
 695        case MCAST_UNBLOCK_SOURCE:
 696        {
 697                struct group_source_req greqs;
 698                int omode, add;
 699
 700                if (optlen < sizeof(struct group_source_req))
 701                        goto e_inval;
 702                if (copy_from_user(&greqs, optval, sizeof(greqs))) {
 703                        retv = -EFAULT;
 704                        break;
 705                }
 706                if (greqs.gsr_group.ss_family != AF_INET6 ||
 707                    greqs.gsr_source.ss_family != AF_INET6) {
 708                        retv = -EADDRNOTAVAIL;
 709                        break;
 710                }
 711                if (optname == MCAST_BLOCK_SOURCE) {
 712                        omode = MCAST_EXCLUDE;
 713                        add = 1;
 714                } else if (optname == MCAST_UNBLOCK_SOURCE) {
 715                        omode = MCAST_EXCLUDE;
 716                        add = 0;
 717                } else if (optname == MCAST_JOIN_SOURCE_GROUP) {
 718                        struct sockaddr_in6 *psin6;
 719
 720                        psin6 = (struct sockaddr_in6 *)&greqs.gsr_group;
 721                        retv = ipv6_sock_mc_join(sk, greqs.gsr_interface,
 722                                                 &psin6->sin6_addr);
 723                        /* prior join w/ different source is ok */
 724                        if (retv && retv != -EADDRINUSE)
 725                                break;
 726                        omode = MCAST_INCLUDE;
 727                        add = 1;
 728                } else /* MCAST_LEAVE_SOURCE_GROUP */ {
 729                        omode = MCAST_INCLUDE;
 730                        add = 0;
 731                }
 732                retv = ip6_mc_source(add, omode, sk, &greqs);
 733                break;
 734        }
 735        case MCAST_MSFILTER:
 736        {
 737                struct group_filter *gsf;
 738
 739                if (optlen < GROUP_FILTER_SIZE(0))
 740                        goto e_inval;
 741                if (optlen > sysctl_optmem_max) {
 742                        retv = -ENOBUFS;
 743                        break;
 744                }
 745                gsf = memdup_user(optval, optlen);
 746                if (IS_ERR(gsf)) {
 747                        retv = PTR_ERR(gsf);
 748                        break;
 749                }
 750                /* numsrc >= (4G-140)/128 overflow in 32 bits */
 751                if (gsf->gf_numsrc >= 0x1ffffffU ||
 752                    gsf->gf_numsrc > sysctl_mld_max_msf) {
 753                        kfree(gsf);
 754                        retv = -ENOBUFS;
 755                        break;
 756                }
 757                if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
 758                        kfree(gsf);
 759                        retv = -EINVAL;
 760                        break;
 761                }
 762                retv = ip6_mc_msfilter(sk, gsf);
 763                kfree(gsf);
 764
 765                break;
 766        }
 767        case IPV6_ROUTER_ALERT:
 768                if (optlen < sizeof(int))
 769                        goto e_inval;
 770                retv = ip6_ra_control(sk, val);
 771                break;
 772        case IPV6_MTU_DISCOVER:
 773                if (optlen < sizeof(int))
 774                        goto e_inval;
 775                if (val < IPV6_PMTUDISC_DONT || val > IPV6_PMTUDISC_OMIT)
 776                        goto e_inval;
 777                np->pmtudisc = val;
 778                retv = 0;
 779                break;
 780        case IPV6_MTU:
 781                if (optlen < sizeof(int))
 782                        goto e_inval;
 783                if (val && val < IPV6_MIN_MTU)
 784                        goto e_inval;
 785                np->frag_size = val;
 786                retv = 0;
 787                break;
 788        case IPV6_RECVERR:
 789                if (optlen < sizeof(int))
 790                        goto e_inval;
 791                np->recverr = valbool;
 792                if (!val)
 793                        skb_queue_purge(&sk->sk_error_queue);
 794                retv = 0;
 795                break;
 796        case IPV6_FLOWINFO_SEND:
 797                if (optlen < sizeof(int))
 798                        goto e_inval;
 799                np->sndflow = valbool;
 800                retv = 0;
 801                break;
 802        case IPV6_FLOWLABEL_MGR:
 803                retv = ipv6_flowlabel_opt(sk, optval, optlen);
 804                break;
 805        case IPV6_IPSEC_POLICY:
 806        case IPV6_XFRM_POLICY:
 807                retv = -EPERM;
 808                if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 809                        break;
 810                retv = xfrm_user_policy(sk, optname, optval, optlen);
 811                break;
 812
 813        case IPV6_ADDR_PREFERENCES:
 814            {
 815                unsigned int pref = 0;
 816                unsigned int prefmask = ~0;
 817
 818                if (optlen < sizeof(int))
 819                        goto e_inval;
 820
 821                retv = -EINVAL;
 822
 823                /* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */
 824                switch (val & (IPV6_PREFER_SRC_PUBLIC|
 825                               IPV6_PREFER_SRC_TMP|
 826                               IPV6_PREFER_SRC_PUBTMP_DEFAULT)) {
 827                case IPV6_PREFER_SRC_PUBLIC:
 828                        pref |= IPV6_PREFER_SRC_PUBLIC;
 829                        break;
 830                case IPV6_PREFER_SRC_TMP:
 831                        pref |= IPV6_PREFER_SRC_TMP;
 832                        break;
 833                case IPV6_PREFER_SRC_PUBTMP_DEFAULT:
 834                        break;
 835                case 0:
 836                        goto pref_skip_pubtmp;
 837                default:
 838                        goto e_inval;
 839                }
 840
 841                prefmask &= ~(IPV6_PREFER_SRC_PUBLIC|
 842                              IPV6_PREFER_SRC_TMP);
 843pref_skip_pubtmp:
 844
 845                /* check HOME/COA conflicts */
 846                switch (val & (IPV6_PREFER_SRC_HOME|IPV6_PREFER_SRC_COA)) {
 847                case IPV6_PREFER_SRC_HOME:
 848                        break;
 849                case IPV6_PREFER_SRC_COA:
 850                        pref |= IPV6_PREFER_SRC_COA;
 851                case 0:
 852                        goto pref_skip_coa;
 853                default:
 854                        goto e_inval;
 855                }
 856
 857                prefmask &= ~IPV6_PREFER_SRC_COA;
 858pref_skip_coa:
 859
 860                /* check CGA/NONCGA conflicts */
 861                switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) {
 862                case IPV6_PREFER_SRC_CGA:
 863                case IPV6_PREFER_SRC_NONCGA:
 864                case 0:
 865                        break;
 866                default:
 867                        goto e_inval;
 868                }
 869
 870                np->srcprefs = (np->srcprefs & prefmask) | pref;
 871                retv = 0;
 872
 873                break;
 874            }
 875        case IPV6_MINHOPCOUNT:
 876                if (optlen < sizeof(int))
 877                        goto e_inval;
 878                if (val < 0 || val > 255)
 879                        goto e_inval;
 880                np->min_hopcount = val;
 881                retv = 0;
 882                break;
 883        case IPV6_DONTFRAG:
 884                np->dontfrag = valbool;
 885                retv = 0;
 886                break;
 887        case IPV6_AUTOFLOWLABEL:
 888                np->autoflowlabel = valbool;
 889                np->autoflowlabel_set = 1;
 890                retv = 0;
 891                break;
 892        case IPV6_RECVFRAGSIZE:
 893                np->rxopt.bits.recvfragsize = valbool;
 894                retv = 0;
 895                break;
 896        }
 897
 898        release_sock(sk);
 899        if (needs_rtnl)
 900                rtnl_unlock();
 901
 902        return retv;
 903
 904e_inval:
 905        release_sock(sk);
 906        if (needs_rtnl)
 907                rtnl_unlock();
 908        return -EINVAL;
 909}
 910
 911int ipv6_setsockopt(struct sock *sk, int level, int optname,
 912                    char __user *optval, unsigned int optlen)
 913{
 914        int err;
 915
 916        if (level == SOL_IP && sk->sk_type != SOCK_RAW)
 917                return udp_prot.setsockopt(sk, level, optname, optval, optlen);
 918
 919        if (level != SOL_IPV6)
 920                return -ENOPROTOOPT;
 921
 922        err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
 923#ifdef CONFIG_NETFILTER
 924        /* we need to exclude all possible ENOPROTOOPTs except default case */
 925        if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
 926                        optname != IPV6_XFRM_POLICY)
 927                err = nf_setsockopt(sk, PF_INET6, optname, optval, optlen);
 928#endif
 929        return err;
 930}
 931EXPORT_SYMBOL(ipv6_setsockopt);
 932
 933#ifdef CONFIG_COMPAT
 934int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
 935                           char __user *optval, unsigned int optlen)
 936{
 937        int err;
 938
 939        if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
 940                if (udp_prot.compat_setsockopt != NULL)
 941                        return udp_prot.compat_setsockopt(sk, level, optname,
 942                                                          optval, optlen);
 943                return udp_prot.setsockopt(sk, level, optname, optval, optlen);
 944        }
 945
 946        if (level != SOL_IPV6)
 947                return -ENOPROTOOPT;
 948
 949        if (optname >= MCAST_JOIN_GROUP && optname <= MCAST_MSFILTER)
 950                return compat_mc_setsockopt(sk, level, optname, optval, optlen,
 951                        ipv6_setsockopt);
 952
 953        err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
 954#ifdef CONFIG_NETFILTER
 955        /* we need to exclude all possible ENOPROTOOPTs except default case */
 956        if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
 957            optname != IPV6_XFRM_POLICY)
 958                err = compat_nf_setsockopt(sk, PF_INET6, optname, optval,
 959                                           optlen);
 960#endif
 961        return err;
 962}
 963EXPORT_SYMBOL(compat_ipv6_setsockopt);
 964#endif
 965
 966static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
 967                                  int optname, char __user *optval, int len)
 968{
 969        struct ipv6_opt_hdr *hdr;
 970
 971        if (!opt)
 972                return 0;
 973
 974        switch (optname) {
 975        case IPV6_HOPOPTS:
 976                hdr = opt->hopopt;
 977                break;
 978        case IPV6_RTHDRDSTOPTS:
 979                hdr = opt->dst0opt;
 980                break;
 981        case IPV6_RTHDR:
 982                hdr = (struct ipv6_opt_hdr *)opt->srcrt;
 983                break;
 984        case IPV6_DSTOPTS:
 985                hdr = opt->dst1opt;
 986                break;
 987        default:
 988                return -EINVAL; /* should not happen */
 989        }
 990
 991        if (!hdr)
 992                return 0;
 993
 994        len = min_t(unsigned int, len, ipv6_optlen(hdr));
 995        if (copy_to_user(optval, hdr, len))
 996                return -EFAULT;
 997        return len;
 998}
 999
1000static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
1001                    char __user *optval, int __user *optlen, unsigned int flags)
1002{
1003        struct ipv6_pinfo *np = inet6_sk(sk);
1004        int len;
1005        int val;
1006
1007        if (ip6_mroute_opt(optname))
1008                return ip6_mroute_getsockopt(sk, optname, optval, optlen);
1009
1010        if (get_user(len, optlen))
1011                return -EFAULT;
1012        switch (optname) {
1013        case IPV6_ADDRFORM:
1014                if (sk->sk_protocol != IPPROTO_UDP &&
1015                    sk->sk_protocol != IPPROTO_UDPLITE &&
1016                    sk->sk_protocol != IPPROTO_TCP)
1017                        return -ENOPROTOOPT;
1018                if (sk->sk_state != TCP_ESTABLISHED)
1019                        return -ENOTCONN;
1020                val = sk->sk_family;
1021                break;
1022        case MCAST_MSFILTER:
1023        {
1024                struct group_filter gsf;
1025                int err;
1026
1027                if (len < GROUP_FILTER_SIZE(0))
1028                        return -EINVAL;
1029                if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0)))
1030                        return -EFAULT;
1031                if (gsf.gf_group.ss_family != AF_INET6)
1032                        return -EADDRNOTAVAIL;
1033                lock_sock(sk);
1034                err = ip6_mc_msfget(sk, &gsf,
1035                        (struct group_filter __user *)optval, optlen);
1036                release_sock(sk);
1037                return err;
1038        }
1039
1040        case IPV6_2292PKTOPTIONS:
1041        {
1042                struct msghdr msg;
1043                struct sk_buff *skb;
1044
1045                if (sk->sk_type != SOCK_STREAM)
1046                        return -ENOPROTOOPT;
1047
1048                msg.msg_control = optval;
1049                msg.msg_controllen = len;
1050                msg.msg_flags = flags;
1051
1052                lock_sock(sk);
1053                skb = np->pktoptions;
1054                if (skb)
1055                        ip6_datagram_recv_ctl(sk, &msg, skb);
1056                release_sock(sk);
1057                if (!skb) {
1058                        if (np->rxopt.bits.rxinfo) {
1059                                struct in6_pktinfo src_info;
1060                                src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
1061                                        np->sticky_pktinfo.ipi6_ifindex;
1062                                src_info.ipi6_addr = np->mcast_oif ? sk->sk_v6_daddr : np->sticky_pktinfo.ipi6_addr;
1063                                put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info);
1064                        }
1065                        if (np->rxopt.bits.rxhlim) {
1066                                int hlim = np->mcast_hops;
1067                                put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim);
1068                        }
1069                        if (np->rxopt.bits.rxtclass) {
1070                                int tclass = (int)ip6_tclass(np->rcv_flowinfo);
1071
1072                                put_cmsg(&msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass);
1073                        }
1074                        if (np->rxopt.bits.rxoinfo) {
1075                                struct in6_pktinfo src_info;
1076                                src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
1077                                        np->sticky_pktinfo.ipi6_ifindex;
1078                                src_info.ipi6_addr = np->mcast_oif ? sk->sk_v6_daddr :
1079                                                                     np->sticky_pktinfo.ipi6_addr;
1080                                put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info);
1081                        }
1082                        if (np->rxopt.bits.rxohlim) {
1083                                int hlim = np->mcast_hops;
1084                                put_cmsg(&msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim);
1085                        }
1086                        if (np->rxopt.bits.rxflow) {
1087                                __be32 flowinfo = np->rcv_flowinfo;
1088
1089                                put_cmsg(&msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo);
1090                        }
1091                }
1092                len -= msg.msg_controllen;
1093                return put_user(len, optlen);
1094        }
1095        case IPV6_MTU:
1096        {
1097                struct dst_entry *dst;
1098
1099                val = 0;
1100                rcu_read_lock();
1101                dst = __sk_dst_get(sk);
1102                if (dst)
1103                        val = dst_mtu(dst);
1104                rcu_read_unlock();
1105                if (!val)
1106                        return -ENOTCONN;
1107                break;
1108        }
1109
1110        case IPV6_V6ONLY:
1111                val = sk->sk_ipv6only;
1112                break;
1113
1114        case IPV6_RECVPKTINFO:
1115                val = np->rxopt.bits.rxinfo;
1116                break;
1117
1118        case IPV6_2292PKTINFO:
1119                val = np->rxopt.bits.rxoinfo;
1120                break;
1121
1122        case IPV6_RECVHOPLIMIT:
1123                val = np->rxopt.bits.rxhlim;
1124                break;
1125
1126        case IPV6_2292HOPLIMIT:
1127                val = np->rxopt.bits.rxohlim;
1128                break;
1129
1130        case IPV6_RECVRTHDR:
1131                val = np->rxopt.bits.srcrt;
1132                break;
1133
1134        case IPV6_2292RTHDR:
1135                val = np->rxopt.bits.osrcrt;
1136                break;
1137
1138        case IPV6_HOPOPTS:
1139        case IPV6_RTHDRDSTOPTS:
1140        case IPV6_RTHDR:
1141        case IPV6_DSTOPTS:
1142        {
1143                struct ipv6_txoptions *opt;
1144
1145                lock_sock(sk);
1146                opt = rcu_dereference_protected(np->opt,
1147                                                lockdep_sock_is_held(sk));
1148                len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len);
1149                release_sock(sk);
1150                /* check if ipv6_getsockopt_sticky() returns err code */
1151                if (len < 0)
1152                        return len;
1153                return put_user(len, optlen);
1154        }
1155
1156        case IPV6_RECVHOPOPTS:
1157                val = np->rxopt.bits.hopopts;
1158                break;
1159
1160        case IPV6_2292HOPOPTS:
1161                val = np->rxopt.bits.ohopopts;
1162                break;
1163
1164        case IPV6_RECVDSTOPTS:
1165                val = np->rxopt.bits.dstopts;
1166                break;
1167
1168        case IPV6_2292DSTOPTS:
1169                val = np->rxopt.bits.odstopts;
1170                break;
1171
1172        case IPV6_TCLASS:
1173                val = np->tclass;
1174                break;
1175
1176        case IPV6_RECVTCLASS:
1177                val = np->rxopt.bits.rxtclass;
1178                break;
1179
1180        case IPV6_FLOWINFO:
1181                val = np->rxopt.bits.rxflow;
1182                break;
1183
1184        case IPV6_RECVPATHMTU:
1185                val = np->rxopt.bits.rxpmtu;
1186                break;
1187
1188        case IPV6_PATHMTU:
1189        {
1190                struct dst_entry *dst;
1191                struct ip6_mtuinfo mtuinfo;
1192
1193                if (len < sizeof(mtuinfo))
1194                        return -EINVAL;
1195
1196                len = sizeof(mtuinfo);
1197                memset(&mtuinfo, 0, sizeof(mtuinfo));
1198
1199                rcu_read_lock();
1200                dst = __sk_dst_get(sk);
1201                if (dst)
1202                        mtuinfo.ip6m_mtu = dst_mtu(dst);
1203                rcu_read_unlock();
1204                if (!mtuinfo.ip6m_mtu)
1205                        return -ENOTCONN;
1206
1207                if (put_user(len, optlen))
1208                        return -EFAULT;
1209                if (copy_to_user(optval, &mtuinfo, len))
1210                        return -EFAULT;
1211
1212                return 0;
1213        }
1214
1215        case IPV6_TRANSPARENT:
1216                val = inet_sk(sk)->transparent;
1217                break;
1218
1219        case IPV6_FREEBIND:
1220                val = inet_sk(sk)->freebind;
1221                break;
1222
1223        case IPV6_RECVORIGDSTADDR:
1224                val = np->rxopt.bits.rxorigdstaddr;
1225                break;
1226
1227        case IPV6_UNICAST_HOPS:
1228        case IPV6_MULTICAST_HOPS:
1229        {
1230                struct dst_entry *dst;
1231
1232                if (optname == IPV6_UNICAST_HOPS)
1233                        val = np->hop_limit;
1234                else
1235                        val = np->mcast_hops;
1236
1237                if (val < 0) {
1238                        rcu_read_lock();
1239                        dst = __sk_dst_get(sk);
1240                        if (dst)
1241                                val = ip6_dst_hoplimit(dst);
1242                        rcu_read_unlock();
1243                }
1244
1245                if (val < 0)
1246                        val = sock_net(sk)->ipv6.devconf_all->hop_limit;
1247                break;
1248        }
1249
1250        case IPV6_MULTICAST_LOOP:
1251                val = np->mc_loop;
1252                break;
1253
1254        case IPV6_MULTICAST_IF:
1255                val = np->mcast_oif;
1256                break;
1257
1258        case IPV6_UNICAST_IF:
1259                val = (__force int)htonl((__u32) np->ucast_oif);
1260                break;
1261
1262        case IPV6_MTU_DISCOVER:
1263                val = np->pmtudisc;
1264                break;
1265
1266        case IPV6_RECVERR:
1267                val = np->recverr;
1268                break;
1269
1270        case IPV6_FLOWINFO_SEND:
1271                val = np->sndflow;
1272                break;
1273
1274        case IPV6_FLOWLABEL_MGR:
1275        {
1276                struct in6_flowlabel_req freq;
1277                int flags;
1278
1279                if (len < sizeof(freq))
1280                        return -EINVAL;
1281
1282                if (copy_from_user(&freq, optval, sizeof(freq)))
1283                        return -EFAULT;
1284
1285                if (freq.flr_action != IPV6_FL_A_GET)
1286                        return -EINVAL;
1287
1288                len = sizeof(freq);
1289                flags = freq.flr_flags;
1290
1291                memset(&freq, 0, sizeof(freq));
1292
1293                val = ipv6_flowlabel_opt_get(sk, &freq, flags);
1294                if (val < 0)
1295                        return val;
1296
1297                if (put_user(len, optlen))
1298                        return -EFAULT;
1299                if (copy_to_user(optval, &freq, len))
1300                        return -EFAULT;
1301
1302                return 0;
1303        }
1304
1305        case IPV6_ADDR_PREFERENCES:
1306                val = 0;
1307
1308                if (np->srcprefs & IPV6_PREFER_SRC_TMP)
1309                        val |= IPV6_PREFER_SRC_TMP;
1310                else if (np->srcprefs & IPV6_PREFER_SRC_PUBLIC)
1311                        val |= IPV6_PREFER_SRC_PUBLIC;
1312                else {
1313                        /* XXX: should we return system default? */
1314                        val |= IPV6_PREFER_SRC_PUBTMP_DEFAULT;
1315                }
1316
1317                if (np->srcprefs & IPV6_PREFER_SRC_COA)
1318                        val |= IPV6_PREFER_SRC_COA;
1319                else
1320                        val |= IPV6_PREFER_SRC_HOME;
1321                break;
1322
1323        case IPV6_MINHOPCOUNT:
1324                val = np->min_hopcount;
1325                break;
1326
1327        case IPV6_DONTFRAG:
1328                val = np->dontfrag;
1329                break;
1330
1331        case IPV6_AUTOFLOWLABEL:
1332                val = ip6_autoflowlabel(sock_net(sk), np);
1333                break;
1334
1335        case IPV6_RECVFRAGSIZE:
1336                val = np->rxopt.bits.recvfragsize;
1337                break;
1338
1339        default:
1340                return -ENOPROTOOPT;
1341        }
1342        len = min_t(unsigned int, sizeof(int), len);
1343        if (put_user(len, optlen))
1344                return -EFAULT;
1345        if (copy_to_user(optval, &val, len))
1346                return -EFAULT;
1347        return 0;
1348}
1349
1350int ipv6_getsockopt(struct sock *sk, int level, int optname,
1351                    char __user *optval, int __user *optlen)
1352{
1353        int err;
1354
1355        if (level == SOL_IP && sk->sk_type != SOCK_RAW)
1356                return udp_prot.getsockopt(sk, level, optname, optval, optlen);
1357
1358        if (level != SOL_IPV6)
1359                return -ENOPROTOOPT;
1360
1361        err = do_ipv6_getsockopt(sk, level, optname, optval, optlen, 0);
1362#ifdef CONFIG_NETFILTER
1363        /* we need to exclude all possible ENOPROTOOPTs except default case */
1364        if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
1365                int len;
1366
1367                if (get_user(len, optlen))
1368                        return -EFAULT;
1369
1370                err = nf_getsockopt(sk, PF_INET6, optname, optval, &len);
1371                if (err >= 0)
1372                        err = put_user(len, optlen);
1373        }
1374#endif
1375        return err;
1376}
1377EXPORT_SYMBOL(ipv6_getsockopt);
1378
1379#ifdef CONFIG_COMPAT
1380int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
1381                           char __user *optval, int __user *optlen)
1382{
1383        int err;
1384
1385        if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
1386                if (udp_prot.compat_getsockopt != NULL)
1387                        return udp_prot.compat_getsockopt(sk, level, optname,
1388                                                          optval, optlen);
1389                return udp_prot.getsockopt(sk, level, optname, optval, optlen);
1390        }
1391
1392        if (level != SOL_IPV6)
1393                return -ENOPROTOOPT;
1394
1395        if (optname == MCAST_MSFILTER)
1396                return compat_mc_getsockopt(sk, level, optname, optval, optlen,
1397                        ipv6_getsockopt);
1398
1399        err = do_ipv6_getsockopt(sk, level, optname, optval, optlen,
1400                                 MSG_CMSG_COMPAT);
1401#ifdef CONFIG_NETFILTER
1402        /* we need to exclude all possible ENOPROTOOPTs except default case */
1403        if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
1404                int len;
1405
1406                if (get_user(len, optlen))
1407                        return -EFAULT;
1408
1409                err = compat_nf_getsockopt(sk, PF_INET6, optname, optval, &len);
1410                if (err >= 0)
1411                        err = put_user(len, optlen);
1412        }
1413#endif
1414        return err;
1415}
1416EXPORT_SYMBOL(compat_ipv6_getsockopt);
1417#endif
1418