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                        sk->sk_destruct = inet_sock_destruct;
 246                        /*
 247                         * ... and add it to the refcnt debug socks count
 248                         * in the new family. -acme
 249                         */
 250                        sk_refcnt_debug_inc(sk);
 251                        module_put(THIS_MODULE);
 252                        retv = 0;
 253                        break;
 254                }
 255                goto e_inval;
 256
 257        case IPV6_V6ONLY:
 258                if (optlen < sizeof(int) ||
 259                    inet_sk(sk)->inet_num)
 260                        goto e_inval;
 261                sk->sk_ipv6only = valbool;
 262                retv = 0;
 263                break;
 264
 265        case IPV6_RECVPKTINFO:
 266                if (optlen < sizeof(int))
 267                        goto e_inval;
 268                np->rxopt.bits.rxinfo = valbool;
 269                retv = 0;
 270                break;
 271
 272        case IPV6_2292PKTINFO:
 273                if (optlen < sizeof(int))
 274                        goto e_inval;
 275                np->rxopt.bits.rxoinfo = valbool;
 276                retv = 0;
 277                break;
 278
 279        case IPV6_RECVHOPLIMIT:
 280                if (optlen < sizeof(int))
 281                        goto e_inval;
 282                np->rxopt.bits.rxhlim = valbool;
 283                retv = 0;
 284                break;
 285
 286        case IPV6_2292HOPLIMIT:
 287                if (optlen < sizeof(int))
 288                        goto e_inval;
 289                np->rxopt.bits.rxohlim = valbool;
 290                retv = 0;
 291                break;
 292
 293        case IPV6_RECVRTHDR:
 294                if (optlen < sizeof(int))
 295                        goto e_inval;
 296                np->rxopt.bits.srcrt = valbool;
 297                retv = 0;
 298                break;
 299
 300        case IPV6_2292RTHDR:
 301                if (optlen < sizeof(int))
 302                        goto e_inval;
 303                np->rxopt.bits.osrcrt = valbool;
 304                retv = 0;
 305                break;
 306
 307        case IPV6_RECVHOPOPTS:
 308                if (optlen < sizeof(int))
 309                        goto e_inval;
 310                np->rxopt.bits.hopopts = valbool;
 311                retv = 0;
 312                break;
 313
 314        case IPV6_2292HOPOPTS:
 315                if (optlen < sizeof(int))
 316                        goto e_inval;
 317                np->rxopt.bits.ohopopts = valbool;
 318                retv = 0;
 319                break;
 320
 321        case IPV6_RECVDSTOPTS:
 322                if (optlen < sizeof(int))
 323                        goto e_inval;
 324                np->rxopt.bits.dstopts = valbool;
 325                retv = 0;
 326                break;
 327
 328        case IPV6_2292DSTOPTS:
 329                if (optlen < sizeof(int))
 330                        goto e_inval;
 331                np->rxopt.bits.odstopts = valbool;
 332                retv = 0;
 333                break;
 334
 335        case IPV6_TCLASS:
 336                if (optlen < sizeof(int))
 337                        goto e_inval;
 338                if (val < -1 || val > 0xff)
 339                        goto e_inval;
 340                /* RFC 3542, 6.5: default traffic class of 0x0 */
 341                if (val == -1)
 342                        val = 0;
 343                np->tclass = val;
 344                retv = 0;
 345                break;
 346
 347        case IPV6_RECVTCLASS:
 348                if (optlen < sizeof(int))
 349                        goto e_inval;
 350                np->rxopt.bits.rxtclass = valbool;
 351                retv = 0;
 352                break;
 353
 354        case IPV6_FLOWINFO:
 355                if (optlen < sizeof(int))
 356                        goto e_inval;
 357                np->rxopt.bits.rxflow = valbool;
 358                retv = 0;
 359                break;
 360
 361        case IPV6_RECVPATHMTU:
 362                if (optlen < sizeof(int))
 363                        goto e_inval;
 364                np->rxopt.bits.rxpmtu = valbool;
 365                retv = 0;
 366                break;
 367
 368        case IPV6_TRANSPARENT:
 369                if (valbool && !ns_capable(net->user_ns, CAP_NET_ADMIN) &&
 370                    !ns_capable(net->user_ns, CAP_NET_RAW)) {
 371                        retv = -EPERM;
 372                        break;
 373                }
 374                if (optlen < sizeof(int))
 375                        goto e_inval;
 376                /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
 377                inet_sk(sk)->transparent = valbool;
 378                retv = 0;
 379                break;
 380
 381        case IPV6_RECVORIGDSTADDR:
 382                if (optlen < sizeof(int))
 383                        goto e_inval;
 384                np->rxopt.bits.rxorigdstaddr = valbool;
 385                retv = 0;
 386                break;
 387
 388        case IPV6_HOPOPTS:
 389        case IPV6_RTHDRDSTOPTS:
 390        case IPV6_RTHDR:
 391        case IPV6_DSTOPTS:
 392        {
 393                struct ipv6_txoptions *opt;
 394
 395                /* remove any sticky options header with a zero option
 396                 * length, per RFC3542.
 397                 */
 398                if (optlen == 0)
 399                        optval = NULL;
 400                else if (!optval)
 401                        goto e_inval;
 402                else if (optlen < sizeof(struct ipv6_opt_hdr) ||
 403                         optlen & 0x7 || optlen > 8 * 255)
 404                        goto e_inval;
 405
 406                /* hop-by-hop / destination options are privileged option */
 407                retv = -EPERM;
 408                if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW))
 409                        break;
 410
 411                opt = rcu_dereference_protected(np->opt,
 412                                                lockdep_sock_is_held(sk));
 413                opt = ipv6_renew_options(sk, opt, optname,
 414                                         (struct ipv6_opt_hdr __user *)optval,
 415                                         optlen);
 416                if (IS_ERR(opt)) {
 417                        retv = PTR_ERR(opt);
 418                        break;
 419                }
 420
 421                /* routing header option needs extra check */
 422                retv = -EINVAL;
 423                if (optname == IPV6_RTHDR && opt && opt->srcrt) {
 424                        struct ipv6_rt_hdr *rthdr = opt->srcrt;
 425                        switch (rthdr->type) {
 426#if IS_ENABLED(CONFIG_IPV6_MIP6)
 427                        case IPV6_SRCRT_TYPE_2:
 428                                if (rthdr->hdrlen != 2 ||
 429                                    rthdr->segments_left != 1)
 430                                        goto sticky_done;
 431
 432                                break;
 433#endif
 434                        case IPV6_SRCRT_TYPE_4:
 435                        {
 436                                struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)
 437                                                          opt->srcrt;
 438
 439                                if (!seg6_validate_srh(srh, optlen))
 440                                        goto sticky_done;
 441                                break;
 442                        }
 443                        default:
 444                                goto sticky_done;
 445                        }
 446                }
 447
 448                retv = 0;
 449                opt = ipv6_update_options(sk, opt);
 450sticky_done:
 451                if (opt) {
 452                        atomic_sub(opt->tot_len, &sk->sk_omem_alloc);
 453                        txopt_put(opt);
 454                }
 455                break;
 456        }
 457
 458        case IPV6_PKTINFO:
 459        {
 460                struct in6_pktinfo pkt;
 461
 462                if (optlen == 0)
 463                        goto e_inval;
 464                else if (optlen < sizeof(struct in6_pktinfo) || !optval)
 465                        goto e_inval;
 466
 467                if (copy_from_user(&pkt, optval, sizeof(struct in6_pktinfo))) {
 468                                retv = -EFAULT;
 469                                break;
 470                }
 471                if (sk->sk_bound_dev_if && pkt.ipi6_ifindex != sk->sk_bound_dev_if)
 472                        goto e_inval;
 473
 474                np->sticky_pktinfo.ipi6_ifindex = pkt.ipi6_ifindex;
 475                np->sticky_pktinfo.ipi6_addr = pkt.ipi6_addr;
 476                retv = 0;
 477                break;
 478        }
 479
 480        case IPV6_2292PKTOPTIONS:
 481        {
 482                struct ipv6_txoptions *opt = NULL;
 483                struct msghdr msg;
 484                struct flowi6 fl6;
 485                struct sockcm_cookie sockc_junk;
 486                struct ipcm6_cookie ipc6;
 487
 488                memset(&fl6, 0, sizeof(fl6));
 489                fl6.flowi6_oif = sk->sk_bound_dev_if;
 490                fl6.flowi6_mark = sk->sk_mark;
 491
 492                if (optlen == 0)
 493                        goto update;
 494
 495                /* 1K is probably excessive
 496                 * 1K is surely not enough, 2K per standard header is 16K.
 497                 */
 498                retv = -EINVAL;
 499                if (optlen > 64*1024)
 500                        break;
 501
 502                opt = sock_kmalloc(sk, sizeof(*opt) + optlen, GFP_KERNEL);
 503                retv = -ENOBUFS;
 504                if (!opt)
 505                        break;
 506
 507                memset(opt, 0, sizeof(*opt));
 508                atomic_set(&opt->refcnt, 1);
 509                opt->tot_len = sizeof(*opt) + optlen;
 510                retv = -EFAULT;
 511                if (copy_from_user(opt+1, optval, optlen))
 512                        goto done;
 513
 514                msg.msg_controllen = optlen;
 515                msg.msg_control = (void *)(opt+1);
 516                ipc6.opt = opt;
 517
 518                retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, &ipc6, &sockc_junk);
 519                if (retv)
 520                        goto done;
 521update:
 522                retv = 0;
 523                opt = ipv6_update_options(sk, opt);
 524done:
 525                if (opt) {
 526                        atomic_sub(opt->tot_len, &sk->sk_omem_alloc);
 527                        txopt_put(opt);
 528                }
 529                break;
 530        }
 531        case IPV6_UNICAST_HOPS:
 532                if (optlen < sizeof(int))
 533                        goto e_inval;
 534                if (val > 255 || val < -1)
 535                        goto e_inval;
 536                np->hop_limit = val;
 537                retv = 0;
 538                break;
 539
 540        case IPV6_MULTICAST_HOPS:
 541                if (sk->sk_type == SOCK_STREAM)
 542                        break;
 543                if (optlen < sizeof(int))
 544                        goto e_inval;
 545                if (val > 255 || val < -1)
 546                        goto e_inval;
 547                np->mcast_hops = (val == -1 ? IPV6_DEFAULT_MCASTHOPS : val);
 548                retv = 0;
 549                break;
 550
 551        case IPV6_MULTICAST_LOOP:
 552                if (optlen < sizeof(int))
 553                        goto e_inval;
 554                if (val != valbool)
 555                        goto e_inval;
 556                np->mc_loop = valbool;
 557                retv = 0;
 558                break;
 559
 560        case IPV6_UNICAST_IF:
 561        {
 562                struct net_device *dev = NULL;
 563                int ifindex;
 564
 565                if (optlen != sizeof(int))
 566                        goto e_inval;
 567
 568                ifindex = (__force int)ntohl((__force __be32)val);
 569                if (ifindex == 0) {
 570                        np->ucast_oif = 0;
 571                        retv = 0;
 572                        break;
 573                }
 574
 575                dev = dev_get_by_index(net, ifindex);
 576                retv = -EADDRNOTAVAIL;
 577                if (!dev)
 578                        break;
 579                dev_put(dev);
 580
 581                retv = -EINVAL;
 582                if (sk->sk_bound_dev_if)
 583                        break;
 584
 585                np->ucast_oif = ifindex;
 586                retv = 0;
 587                break;
 588        }
 589
 590        case IPV6_MULTICAST_IF:
 591                if (sk->sk_type == SOCK_STREAM)
 592                        break;
 593                if (optlen < sizeof(int))
 594                        goto e_inval;
 595
 596                if (val) {
 597                        struct net_device *dev;
 598                        int midx;
 599
 600                        rcu_read_lock();
 601
 602                        dev = dev_get_by_index_rcu(net, val);
 603                        if (!dev) {
 604                                rcu_read_unlock();
 605                                retv = -ENODEV;
 606                                break;
 607                        }
 608                        midx = l3mdev_master_ifindex_rcu(dev);
 609
 610                        rcu_read_unlock();
 611
 612                        if (sk->sk_bound_dev_if &&
 613                            sk->sk_bound_dev_if != val &&
 614                            (!midx || midx != sk->sk_bound_dev_if))
 615                                goto e_inval;
 616                }
 617                np->mcast_oif = val;
 618                retv = 0;
 619                break;
 620        case IPV6_ADD_MEMBERSHIP:
 621        case IPV6_DROP_MEMBERSHIP:
 622        {
 623                struct ipv6_mreq mreq;
 624
 625                if (optlen < sizeof(struct ipv6_mreq))
 626                        goto e_inval;
 627
 628                retv = -EPROTO;
 629                if (inet_sk(sk)->is_icsk)
 630                        break;
 631
 632                retv = -EFAULT;
 633                if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq)))
 634                        break;
 635
 636                if (optname == IPV6_ADD_MEMBERSHIP)
 637                        retv = ipv6_sock_mc_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
 638                else
 639                        retv = ipv6_sock_mc_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
 640                break;
 641        }
 642        case IPV6_JOIN_ANYCAST:
 643        case IPV6_LEAVE_ANYCAST:
 644        {
 645                struct ipv6_mreq mreq;
 646
 647                if (optlen < sizeof(struct ipv6_mreq))
 648                        goto e_inval;
 649
 650                retv = -EFAULT;
 651                if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq)))
 652                        break;
 653
 654                if (optname == IPV6_JOIN_ANYCAST)
 655                        retv = ipv6_sock_ac_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr);
 656                else
 657                        retv = ipv6_sock_ac_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr);
 658                break;
 659        }
 660        case MCAST_JOIN_GROUP:
 661        case MCAST_LEAVE_GROUP:
 662        {
 663                struct group_req greq;
 664                struct sockaddr_in6 *psin6;
 665
 666                if (optlen < sizeof(struct group_req))
 667                        goto e_inval;
 668
 669                retv = -EFAULT;
 670                if (copy_from_user(&greq, optval, sizeof(struct group_req)))
 671                        break;
 672                if (greq.gr_group.ss_family != AF_INET6) {
 673                        retv = -EADDRNOTAVAIL;
 674                        break;
 675                }
 676                psin6 = (struct sockaddr_in6 *)&greq.gr_group;
 677                if (optname == MCAST_JOIN_GROUP)
 678                        retv = ipv6_sock_mc_join(sk, greq.gr_interface,
 679                                                 &psin6->sin6_addr);
 680                else
 681                        retv = ipv6_sock_mc_drop(sk, greq.gr_interface,
 682                                                 &psin6->sin6_addr);
 683                break;
 684        }
 685        case MCAST_JOIN_SOURCE_GROUP:
 686        case MCAST_LEAVE_SOURCE_GROUP:
 687        case MCAST_BLOCK_SOURCE:
 688        case MCAST_UNBLOCK_SOURCE:
 689        {
 690                struct group_source_req greqs;
 691                int omode, add;
 692
 693                if (optlen < sizeof(struct group_source_req))
 694                        goto e_inval;
 695                if (copy_from_user(&greqs, optval, sizeof(greqs))) {
 696                        retv = -EFAULT;
 697                        break;
 698                }
 699                if (greqs.gsr_group.ss_family != AF_INET6 ||
 700                    greqs.gsr_source.ss_family != AF_INET6) {
 701                        retv = -EADDRNOTAVAIL;
 702                        break;
 703                }
 704                if (optname == MCAST_BLOCK_SOURCE) {
 705                        omode = MCAST_EXCLUDE;
 706                        add = 1;
 707                } else if (optname == MCAST_UNBLOCK_SOURCE) {
 708                        omode = MCAST_EXCLUDE;
 709                        add = 0;
 710                } else if (optname == MCAST_JOIN_SOURCE_GROUP) {
 711                        struct sockaddr_in6 *psin6;
 712
 713                        psin6 = (struct sockaddr_in6 *)&greqs.gsr_group;
 714                        retv = ipv6_sock_mc_join(sk, greqs.gsr_interface,
 715                                                 &psin6->sin6_addr);
 716                        /* prior join w/ different source is ok */
 717                        if (retv && retv != -EADDRINUSE)
 718                                break;
 719                        omode = MCAST_INCLUDE;
 720                        add = 1;
 721                } else /* MCAST_LEAVE_SOURCE_GROUP */ {
 722                        omode = MCAST_INCLUDE;
 723                        add = 0;
 724                }
 725                retv = ip6_mc_source(add, omode, sk, &greqs);
 726                break;
 727        }
 728        case MCAST_MSFILTER:
 729        {
 730                struct group_filter *gsf;
 731
 732                if (optlen < GROUP_FILTER_SIZE(0))
 733                        goto e_inval;
 734                if (optlen > sysctl_optmem_max) {
 735                        retv = -ENOBUFS;
 736                        break;
 737                }
 738                gsf = kmalloc(optlen, GFP_KERNEL);
 739                if (!gsf) {
 740                        retv = -ENOBUFS;
 741                        break;
 742                }
 743                retv = -EFAULT;
 744                if (copy_from_user(gsf, optval, optlen)) {
 745                        kfree(gsf);
 746                        break;
 747                }
 748                /* numsrc >= (4G-140)/128 overflow in 32 bits */
 749                if (gsf->gf_numsrc >= 0x1ffffffU ||
 750                    gsf->gf_numsrc > sysctl_mld_max_msf) {
 751                        kfree(gsf);
 752                        retv = -ENOBUFS;
 753                        break;
 754                }
 755                if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
 756                        kfree(gsf);
 757                        retv = -EINVAL;
 758                        break;
 759                }
 760                retv = ip6_mc_msfilter(sk, gsf);
 761                kfree(gsf);
 762
 763                break;
 764        }
 765        case IPV6_ROUTER_ALERT:
 766                if (optlen < sizeof(int))
 767                        goto e_inval;
 768                retv = ip6_ra_control(sk, val);
 769                break;
 770        case IPV6_MTU_DISCOVER:
 771                if (optlen < sizeof(int))
 772                        goto e_inval;
 773                if (val < IPV6_PMTUDISC_DONT || val > IPV6_PMTUDISC_OMIT)
 774                        goto e_inval;
 775                np->pmtudisc = val;
 776                retv = 0;
 777                break;
 778        case IPV6_MTU:
 779                if (optlen < sizeof(int))
 780                        goto e_inval;
 781                if (val && val < IPV6_MIN_MTU)
 782                        goto e_inval;
 783                np->frag_size = val;
 784                retv = 0;
 785                break;
 786        case IPV6_RECVERR:
 787                if (optlen < sizeof(int))
 788                        goto e_inval;
 789                np->recverr = valbool;
 790                if (!val)
 791                        skb_queue_purge(&sk->sk_error_queue);
 792                retv = 0;
 793                break;
 794        case IPV6_FLOWINFO_SEND:
 795                if (optlen < sizeof(int))
 796                        goto e_inval;
 797                np->sndflow = valbool;
 798                retv = 0;
 799                break;
 800        case IPV6_FLOWLABEL_MGR:
 801                retv = ipv6_flowlabel_opt(sk, optval, optlen);
 802                break;
 803        case IPV6_IPSEC_POLICY:
 804        case IPV6_XFRM_POLICY:
 805                retv = -EPERM;
 806                if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 807                        break;
 808                retv = xfrm_user_policy(sk, optname, optval, optlen);
 809                break;
 810
 811        case IPV6_ADDR_PREFERENCES:
 812            {
 813                unsigned int pref = 0;
 814                unsigned int prefmask = ~0;
 815
 816                if (optlen < sizeof(int))
 817                        goto e_inval;
 818
 819                retv = -EINVAL;
 820
 821                /* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */
 822                switch (val & (IPV6_PREFER_SRC_PUBLIC|
 823                               IPV6_PREFER_SRC_TMP|
 824                               IPV6_PREFER_SRC_PUBTMP_DEFAULT)) {
 825                case IPV6_PREFER_SRC_PUBLIC:
 826                        pref |= IPV6_PREFER_SRC_PUBLIC;
 827                        break;
 828                case IPV6_PREFER_SRC_TMP:
 829                        pref |= IPV6_PREFER_SRC_TMP;
 830                        break;
 831                case IPV6_PREFER_SRC_PUBTMP_DEFAULT:
 832                        break;
 833                case 0:
 834                        goto pref_skip_pubtmp;
 835                default:
 836                        goto e_inval;
 837                }
 838
 839                prefmask &= ~(IPV6_PREFER_SRC_PUBLIC|
 840                              IPV6_PREFER_SRC_TMP);
 841pref_skip_pubtmp:
 842
 843                /* check HOME/COA conflicts */
 844                switch (val & (IPV6_PREFER_SRC_HOME|IPV6_PREFER_SRC_COA)) {
 845                case IPV6_PREFER_SRC_HOME:
 846                        break;
 847                case IPV6_PREFER_SRC_COA:
 848                        pref |= IPV6_PREFER_SRC_COA;
 849                case 0:
 850                        goto pref_skip_coa;
 851                default:
 852                        goto e_inval;
 853                }
 854
 855                prefmask &= ~IPV6_PREFER_SRC_COA;
 856pref_skip_coa:
 857
 858                /* check CGA/NONCGA conflicts */
 859                switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) {
 860                case IPV6_PREFER_SRC_CGA:
 861                case IPV6_PREFER_SRC_NONCGA:
 862                case 0:
 863                        break;
 864                default:
 865                        goto e_inval;
 866                }
 867
 868                np->srcprefs = (np->srcprefs & prefmask) | pref;
 869                retv = 0;
 870
 871                break;
 872            }
 873        case IPV6_MINHOPCOUNT:
 874                if (optlen < sizeof(int))
 875                        goto e_inval;
 876                if (val < 0 || val > 255)
 877                        goto e_inval;
 878                np->min_hopcount = val;
 879                retv = 0;
 880                break;
 881        case IPV6_DONTFRAG:
 882                np->dontfrag = valbool;
 883                retv = 0;
 884                break;
 885        case IPV6_AUTOFLOWLABEL:
 886                np->autoflowlabel = valbool;
 887                retv = 0;
 888                break;
 889        case IPV6_RECVFRAGSIZE:
 890                np->rxopt.bits.recvfragsize = valbool;
 891                retv = 0;
 892                break;
 893        }
 894
 895        release_sock(sk);
 896        if (needs_rtnl)
 897                rtnl_unlock();
 898
 899        return retv;
 900
 901e_inval:
 902        release_sock(sk);
 903        if (needs_rtnl)
 904                rtnl_unlock();
 905        return -EINVAL;
 906}
 907
 908int ipv6_setsockopt(struct sock *sk, int level, int optname,
 909                    char __user *optval, unsigned int optlen)
 910{
 911        int err;
 912
 913        if (level == SOL_IP && sk->sk_type != SOCK_RAW)
 914                return udp_prot.setsockopt(sk, level, optname, optval, optlen);
 915
 916        if (level != SOL_IPV6)
 917                return -ENOPROTOOPT;
 918
 919        err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
 920#ifdef CONFIG_NETFILTER
 921        /* we need to exclude all possible ENOPROTOOPTs except default case */
 922        if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
 923                        optname != IPV6_XFRM_POLICY) {
 924                lock_sock(sk);
 925                err = nf_setsockopt(sk, PF_INET6, optname, optval,
 926                                optlen);
 927                release_sock(sk);
 928        }
 929#endif
 930        return err;
 931}
 932EXPORT_SYMBOL(ipv6_setsockopt);
 933
 934#ifdef CONFIG_COMPAT
 935int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
 936                           char __user *optval, unsigned int optlen)
 937{
 938        int err;
 939
 940        if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
 941                if (udp_prot.compat_setsockopt != NULL)
 942                        return udp_prot.compat_setsockopt(sk, level, optname,
 943                                                          optval, optlen);
 944                return udp_prot.setsockopt(sk, level, optname, optval, optlen);
 945        }
 946
 947        if (level != SOL_IPV6)
 948                return -ENOPROTOOPT;
 949
 950        if (optname >= MCAST_JOIN_GROUP && optname <= MCAST_MSFILTER)
 951                return compat_mc_setsockopt(sk, level, optname, optval, optlen,
 952                        ipv6_setsockopt);
 953
 954        err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
 955#ifdef CONFIG_NETFILTER
 956        /* we need to exclude all possible ENOPROTOOPTs except default case */
 957        if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
 958            optname != IPV6_XFRM_POLICY) {
 959                lock_sock(sk);
 960                err = compat_nf_setsockopt(sk, PF_INET6, optname,
 961                                           optval, optlen);
 962                release_sock(sk);
 963        }
 964#endif
 965        return err;
 966}
 967EXPORT_SYMBOL(compat_ipv6_setsockopt);
 968#endif
 969
 970static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
 971                                  int optname, char __user *optval, int len)
 972{
 973        struct ipv6_opt_hdr *hdr;
 974
 975        if (!opt)
 976                return 0;
 977
 978        switch (optname) {
 979        case IPV6_HOPOPTS:
 980                hdr = opt->hopopt;
 981                break;
 982        case IPV6_RTHDRDSTOPTS:
 983                hdr = opt->dst0opt;
 984                break;
 985        case IPV6_RTHDR:
 986                hdr = (struct ipv6_opt_hdr *)opt->srcrt;
 987                break;
 988        case IPV6_DSTOPTS:
 989                hdr = opt->dst1opt;
 990                break;
 991        default:
 992                return -EINVAL; /* should not happen */
 993        }
 994
 995        if (!hdr)
 996                return 0;
 997
 998        len = min_t(unsigned int, len, ipv6_optlen(hdr));
 999        if (copy_to_user(optval, hdr, len))
1000                return -EFAULT;
1001        return len;
1002}
1003
1004static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
1005                    char __user *optval, int __user *optlen, unsigned int flags)
1006{
1007        struct ipv6_pinfo *np = inet6_sk(sk);
1008        int len;
1009        int val;
1010
1011        if (ip6_mroute_opt(optname))
1012                return ip6_mroute_getsockopt(sk, optname, optval, optlen);
1013
1014        if (get_user(len, optlen))
1015                return -EFAULT;
1016        switch (optname) {
1017        case IPV6_ADDRFORM:
1018                if (sk->sk_protocol != IPPROTO_UDP &&
1019                    sk->sk_protocol != IPPROTO_UDPLITE &&
1020                    sk->sk_protocol != IPPROTO_TCP)
1021                        return -ENOPROTOOPT;
1022                if (sk->sk_state != TCP_ESTABLISHED)
1023                        return -ENOTCONN;
1024                val = sk->sk_family;
1025                break;
1026        case MCAST_MSFILTER:
1027        {
1028                struct group_filter gsf;
1029                int err;
1030
1031                if (len < GROUP_FILTER_SIZE(0))
1032                        return -EINVAL;
1033                if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0)))
1034                        return -EFAULT;
1035                if (gsf.gf_group.ss_family != AF_INET6)
1036                        return -EADDRNOTAVAIL;
1037                lock_sock(sk);
1038                err = ip6_mc_msfget(sk, &gsf,
1039                        (struct group_filter __user *)optval, optlen);
1040                release_sock(sk);
1041                return err;
1042        }
1043
1044        case IPV6_2292PKTOPTIONS:
1045        {
1046                struct msghdr msg;
1047                struct sk_buff *skb;
1048
1049                if (sk->sk_type != SOCK_STREAM)
1050                        return -ENOPROTOOPT;
1051
1052                msg.msg_control = optval;
1053                msg.msg_controllen = len;
1054                msg.msg_flags = flags;
1055
1056                lock_sock(sk);
1057                skb = np->pktoptions;
1058                if (skb)
1059                        ip6_datagram_recv_ctl(sk, &msg, skb);
1060                release_sock(sk);
1061                if (!skb) {
1062                        if (np->rxopt.bits.rxinfo) {
1063                                struct in6_pktinfo src_info;
1064                                src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
1065                                        np->sticky_pktinfo.ipi6_ifindex;
1066                                src_info.ipi6_addr = np->mcast_oif ? sk->sk_v6_daddr : np->sticky_pktinfo.ipi6_addr;
1067                                put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info);
1068                        }
1069                        if (np->rxopt.bits.rxhlim) {
1070                                int hlim = np->mcast_hops;
1071                                put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim);
1072                        }
1073                        if (np->rxopt.bits.rxtclass) {
1074                                int tclass = (int)ip6_tclass(np->rcv_flowinfo);
1075
1076                                put_cmsg(&msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass);
1077                        }
1078                        if (np->rxopt.bits.rxoinfo) {
1079                                struct in6_pktinfo src_info;
1080                                src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
1081                                        np->sticky_pktinfo.ipi6_ifindex;
1082                                src_info.ipi6_addr = np->mcast_oif ? sk->sk_v6_daddr :
1083                                                                     np->sticky_pktinfo.ipi6_addr;
1084                                put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info);
1085                        }
1086                        if (np->rxopt.bits.rxohlim) {
1087                                int hlim = np->mcast_hops;
1088                                put_cmsg(&msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim);
1089                        }
1090                        if (np->rxopt.bits.rxflow) {
1091                                __be32 flowinfo = np->rcv_flowinfo;
1092
1093                                put_cmsg(&msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo);
1094                        }
1095                }
1096                len -= msg.msg_controllen;
1097                return put_user(len, optlen);
1098        }
1099        case IPV6_MTU:
1100        {
1101                struct dst_entry *dst;
1102
1103                val = 0;
1104                rcu_read_lock();
1105                dst = __sk_dst_get(sk);
1106                if (dst)
1107                        val = dst_mtu(dst);
1108                rcu_read_unlock();
1109                if (!val)
1110                        return -ENOTCONN;
1111                break;
1112        }
1113
1114        case IPV6_V6ONLY:
1115                val = sk->sk_ipv6only;
1116                break;
1117
1118        case IPV6_RECVPKTINFO:
1119                val = np->rxopt.bits.rxinfo;
1120                break;
1121
1122        case IPV6_2292PKTINFO:
1123                val = np->rxopt.bits.rxoinfo;
1124                break;
1125
1126        case IPV6_RECVHOPLIMIT:
1127                val = np->rxopt.bits.rxhlim;
1128                break;
1129
1130        case IPV6_2292HOPLIMIT:
1131                val = np->rxopt.bits.rxohlim;
1132                break;
1133
1134        case IPV6_RECVRTHDR:
1135                val = np->rxopt.bits.srcrt;
1136                break;
1137
1138        case IPV6_2292RTHDR:
1139                val = np->rxopt.bits.osrcrt;
1140                break;
1141
1142        case IPV6_HOPOPTS:
1143        case IPV6_RTHDRDSTOPTS:
1144        case IPV6_RTHDR:
1145        case IPV6_DSTOPTS:
1146        {
1147                struct ipv6_txoptions *opt;
1148
1149                lock_sock(sk);
1150                opt = rcu_dereference_protected(np->opt,
1151                                                lockdep_sock_is_held(sk));
1152                len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len);
1153                release_sock(sk);
1154                /* check if ipv6_getsockopt_sticky() returns err code */
1155                if (len < 0)
1156                        return len;
1157                return put_user(len, optlen);
1158        }
1159
1160        case IPV6_RECVHOPOPTS:
1161                val = np->rxopt.bits.hopopts;
1162                break;
1163
1164        case IPV6_2292HOPOPTS:
1165                val = np->rxopt.bits.ohopopts;
1166                break;
1167
1168        case IPV6_RECVDSTOPTS:
1169                val = np->rxopt.bits.dstopts;
1170                break;
1171
1172        case IPV6_2292DSTOPTS:
1173                val = np->rxopt.bits.odstopts;
1174                break;
1175
1176        case IPV6_TCLASS:
1177                val = np->tclass;
1178                break;
1179
1180        case IPV6_RECVTCLASS:
1181                val = np->rxopt.bits.rxtclass;
1182                break;
1183
1184        case IPV6_FLOWINFO:
1185                val = np->rxopt.bits.rxflow;
1186                break;
1187
1188        case IPV6_RECVPATHMTU:
1189                val = np->rxopt.bits.rxpmtu;
1190                break;
1191
1192        case IPV6_PATHMTU:
1193        {
1194                struct dst_entry *dst;
1195                struct ip6_mtuinfo mtuinfo;
1196
1197                if (len < sizeof(mtuinfo))
1198                        return -EINVAL;
1199
1200                len = sizeof(mtuinfo);
1201                memset(&mtuinfo, 0, sizeof(mtuinfo));
1202
1203                rcu_read_lock();
1204                dst = __sk_dst_get(sk);
1205                if (dst)
1206                        mtuinfo.ip6m_mtu = dst_mtu(dst);
1207                rcu_read_unlock();
1208                if (!mtuinfo.ip6m_mtu)
1209                        return -ENOTCONN;
1210
1211                if (put_user(len, optlen))
1212                        return -EFAULT;
1213                if (copy_to_user(optval, &mtuinfo, len))
1214                        return -EFAULT;
1215
1216                return 0;
1217        }
1218
1219        case IPV6_TRANSPARENT:
1220                val = inet_sk(sk)->transparent;
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 = np->autoflowlabel;
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                lock_sock(sk);
1371                err = nf_getsockopt(sk, PF_INET6, optname, optval,
1372                                &len);
1373                release_sock(sk);
1374                if (err >= 0)
1375                        err = put_user(len, optlen);
1376        }
1377#endif
1378        return err;
1379}
1380EXPORT_SYMBOL(ipv6_getsockopt);
1381
1382#ifdef CONFIG_COMPAT
1383int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
1384                           char __user *optval, int __user *optlen)
1385{
1386        int err;
1387
1388        if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
1389                if (udp_prot.compat_getsockopt != NULL)
1390                        return udp_prot.compat_getsockopt(sk, level, optname,
1391                                                          optval, optlen);
1392                return udp_prot.getsockopt(sk, level, optname, optval, optlen);
1393        }
1394
1395        if (level != SOL_IPV6)
1396                return -ENOPROTOOPT;
1397
1398        if (optname == MCAST_MSFILTER)
1399                return compat_mc_getsockopt(sk, level, optname, optval, optlen,
1400                        ipv6_getsockopt);
1401
1402        err = do_ipv6_getsockopt(sk, level, optname, optval, optlen,
1403                                 MSG_CMSG_COMPAT);
1404#ifdef CONFIG_NETFILTER
1405        /* we need to exclude all possible ENOPROTOOPTs except default case */
1406        if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
1407                int len;
1408
1409                if (get_user(len, optlen))
1410                        return -EFAULT;
1411
1412                lock_sock(sk);
1413                err = compat_nf_getsockopt(sk, PF_INET6,
1414                                           optname, optval, &len);
1415                release_sock(sk);
1416                if (err >= 0)
1417                        err = put_user(len, optlen);
1418        }
1419#endif
1420        return err;
1421}
1422EXPORT_SYMBOL(compat_ipv6_getsockopt);
1423#endif
1424
1425