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