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