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