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