^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * INET An implementation of the TCP/IP protocol suite for the LINUX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * operating system. INET is implemented using the BSD Socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * interface as the means of communication with the user level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * The IP to API glue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Authors: see ip.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Fixes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Many : Split from ip.c , see ip.c for history.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Martin Mares : TOS setting fixed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Alan Cox : Fixed a couple of oopses in Martin's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * TOS tweaks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Mike McLagan : Routing by source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/icmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/inetdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <net/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <net/icmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <net/tcp_states.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/udp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/igmp.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/route.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/mroute.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <net/inet_ecn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <net/route.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <net/xfrm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <net/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <net/checksum.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <net/transp_v6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <net/ip_fib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/errqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/bpfilter.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * SOL_IP control messages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct in_pktinfo info = *PKTINFO_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) info.ipi_addr.s_addr = ip_hdr(skb)->daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) put_cmsg(msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static void ip_cmsg_recv_ttl(struct msghdr *msg, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int ttl = ip_hdr(skb)->ttl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) put_cmsg(msg, SOL_IP, IP_TTL, sizeof(int), &ttl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static void ip_cmsg_recv_tos(struct msghdr *msg, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) put_cmsg(msg, SOL_IP, IP_TOS, 1, &ip_hdr(skb)->tos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static void ip_cmsg_recv_opts(struct msghdr *msg, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (IPCB(skb)->opt.optlen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) put_cmsg(msg, SOL_IP, IP_RECVOPTS, IPCB(skb)->opt.optlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ip_hdr(skb) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static void ip_cmsg_recv_retopts(struct net *net, struct msghdr *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned char optbuf[sizeof(struct ip_options) + 40];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct ip_options *opt = (struct ip_options *)optbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (IPCB(skb)->opt.optlen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (ip_options_echo(net, opt, skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) msg->msg_flags |= MSG_CTRUNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ip_options_undo(opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static void ip_cmsg_recv_fragsize(struct msghdr *msg, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (IPCB(skb)->frag_max_size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) val = IPCB(skb)->frag_max_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) put_cmsg(msg, SOL_IP, IP_RECVFRAGSIZE, sizeof(val), &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int tlen, int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) __wsum csum = skb->csum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (skb->ip_summed != CHECKSUM_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (offset != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int tend_off = skb_transport_offset(skb) + tlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) char *secdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u32 seclen, secid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) err = security_socket_getpeersec_dgram(NULL, skb, &secid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) err = security_secid_to_secctx(secid, &secdata, &seclen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) security_release_secctx(secdata, seclen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) __be16 _ports[2], *ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct sockaddr_in sin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* All current transport protocols have the port numbers in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * first four bytes of the transport header and this function is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * written with this assumption in mind.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) ports = skb_header_pointer(skb, skb_transport_offset(skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) sizeof(_ports), &_ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (!ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) sin.sin_family = AF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) sin.sin_addr.s_addr = ip_hdr(skb)->daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) sin.sin_port = ports[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) put_cmsg(msg, SOL_IP, IP_ORIGDSTADDR, sizeof(sin), &sin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct sk_buff *skb, int tlen, int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct inet_sock *inet = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) unsigned int flags = inet->cmsg_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* Ordered by supposed usage frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (flags & IP_CMSG_PKTINFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ip_cmsg_recv_pktinfo(msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) flags &= ~IP_CMSG_PKTINFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (!flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (flags & IP_CMSG_TTL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ip_cmsg_recv_ttl(msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) flags &= ~IP_CMSG_TTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (!flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (flags & IP_CMSG_TOS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ip_cmsg_recv_tos(msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) flags &= ~IP_CMSG_TOS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (!flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (flags & IP_CMSG_RECVOPTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) ip_cmsg_recv_opts(msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) flags &= ~IP_CMSG_RECVOPTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (!flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (flags & IP_CMSG_RETOPTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) ip_cmsg_recv_retopts(sock_net(sk), msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) flags &= ~IP_CMSG_RETOPTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (!flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (flags & IP_CMSG_PASSSEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ip_cmsg_recv_security(msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) flags &= ~IP_CMSG_PASSSEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (flags & IP_CMSG_ORIGDSTADDR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ip_cmsg_recv_dstaddr(msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) flags &= ~IP_CMSG_ORIGDSTADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return;
^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) if (flags & IP_CMSG_CHECKSUM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ip_cmsg_recv_checksum(msg, skb, tlen, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (flags & IP_CMSG_RECVFRAGSIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ip_cmsg_recv_fragsize(msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) EXPORT_SYMBOL(ip_cmsg_recv_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) bool allow_ipv6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) int err, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct cmsghdr *cmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) for_each_cmsghdr(cmsg, msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (!CMSG_OK(msg, cmsg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (allow_ipv6 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) cmsg->cmsg_level == SOL_IPV6 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) cmsg->cmsg_type == IPV6_PKTINFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct in6_pktinfo *src_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (cmsg->cmsg_len < CMSG_LEN(sizeof(*src_info)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (!ipv6_addr_v4mapped(&src_info->ipi6_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (src_info->ipi6_ifindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) ipc->oif = src_info->ipi6_ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) ipc->addr = src_info->ipi6_addr.s6_addr32[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (cmsg->cmsg_level == SOL_SOCKET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) err = __sock_cmsg_send(sk, msg, cmsg, &ipc->sockc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (cmsg->cmsg_level != SOL_IP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) switch (cmsg->cmsg_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) case IP_RETOPTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) err = cmsg->cmsg_len - sizeof(struct cmsghdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /* Our caller is responsible for freeing ipc->opt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) err = ip_options_get(net, &ipc->opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) KERNEL_SOCKPTR(CMSG_DATA(cmsg)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) err < 40 ? err : 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) case IP_PKTINFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct in_pktinfo *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct in_pktinfo)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) info = (struct in_pktinfo *)CMSG_DATA(cmsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (info->ipi_ifindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) ipc->oif = info->ipi_ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ipc->addr = info->ipi_spec_dst.s_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case IP_TTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) val = *(int *)CMSG_DATA(cmsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (val < 1 || val > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ipc->ttl = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) case IP_TOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) val = *(int *)CMSG_DATA(cmsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) else if (cmsg->cmsg_len == CMSG_LEN(sizeof(u8)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) val = *(u8 *)CMSG_DATA(cmsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (val < 0 || val > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ipc->tos = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ipc->priority = rt_tos2priority(ipc->tos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static void ip_ra_destroy_rcu(struct rcu_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) struct ip_ra_chain *ra = container_of(head, struct ip_ra_chain, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) sock_put(ra->saved_sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) kfree(ra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) int ip_ra_control(struct sock *sk, unsigned char on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) void (*destructor)(struct sock *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct ip_ra_chain *ra, *new_ra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct ip_ra_chain __rcu **rap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (sk->sk_type != SOCK_RAW || inet_sk(sk)->inet_num == IPPROTO_RAW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (on && !new_ra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) mutex_lock(&net->ipv4.ra_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) for (rap = &net->ipv4.ra_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) (ra = rcu_dereference_protected(*rap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) lockdep_is_held(&net->ipv4.ra_mutex))) != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) rap = &ra->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (ra->sk == sk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) mutex_unlock(&net->ipv4.ra_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) kfree(new_ra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return -EADDRINUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /* dont let ip_call_ra_chain() use sk again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ra->sk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) RCU_INIT_POINTER(*rap, ra->next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) mutex_unlock(&net->ipv4.ra_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (ra->destructor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ra->destructor(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * Delay sock_put(sk) and kfree(ra) after one rcu grace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * period. This guarantee ip_call_ra_chain() dont need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * to mess with socket refcounts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) ra->saved_sk = sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) call_rcu(&ra->rcu, ip_ra_destroy_rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (!new_ra) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) mutex_unlock(&net->ipv4.ra_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) new_ra->sk = sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) new_ra->destructor = destructor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) RCU_INIT_POINTER(new_ra->next, ra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) rcu_assign_pointer(*rap, new_ra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) sock_hold(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) mutex_unlock(&net->ipv4.ra_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static void ipv4_icmp_error_rfc4884(const struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct sock_ee_data_rfc4884 *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) switch (icmp_hdr(skb)->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) case ICMP_DEST_UNREACH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) case ICMP_TIME_EXCEEDED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) case ICMP_PARAMETERPROB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) ip_icmp_error_rfc4884(skb, out, sizeof(struct icmphdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) icmp_hdr(skb)->un.reserved[1] * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) __be16 port, u32 info, u8 *payload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct sock_exterr_skb *serr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) skb = skb_clone(skb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) serr = SKB_EXT_ERR(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) serr->ee.ee_errno = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) serr->ee.ee_origin = SO_EE_ORIGIN_ICMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) serr->ee.ee_type = icmp_hdr(skb)->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) serr->ee.ee_code = icmp_hdr(skb)->code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) serr->ee.ee_pad = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) serr->ee.ee_info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) serr->ee.ee_data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) serr->addr_offset = (u8 *)&(((struct iphdr *)(icmp_hdr(skb) + 1))->daddr) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) skb_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) serr->port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (skb_pull(skb, payload - skb->data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (inet_sk(sk)->recverr_rfc4884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) ipv4_icmp_error_rfc4884(skb, &serr->ee.ee_rfc4884);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (sock_queue_err_skb(sk, skb) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct inet_sock *inet = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct sock_exterr_skb *serr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct iphdr *iph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (!inet->recverr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) skb = alloc_skb(sizeof(struct iphdr), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) skb_put(skb, sizeof(struct iphdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) iph = ip_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) iph->daddr = daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) serr = SKB_EXT_ERR(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) serr->ee.ee_errno = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) serr->ee.ee_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) serr->ee.ee_code = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) serr->ee.ee_pad = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) serr->ee.ee_info = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) serr->ee.ee_data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) serr->addr_offset = (u8 *)&iph->daddr - skb_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) serr->port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) __skb_pull(skb, skb_tail_pointer(skb) - skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (sock_queue_err_skb(sk, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* For some errors we have valid addr_offset even with zero payload and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * zero port. Also, addr_offset should be supported if port is set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static inline bool ipv4_datagram_support_addr(struct sock_exterr_skb *serr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL || serr->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* IPv4 supports cmsg on all imcp errors and some timestamps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * Timestamp code paths do not initialize the fields expected by cmsg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * the PKTINFO fields in skb->cb[]. Fill those in here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static bool ipv4_datagram_support_cmsg(const struct sock *sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) int ee_origin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) struct in_pktinfo *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (ee_origin == SO_EE_ORIGIN_ICMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (ee_origin == SO_EE_ORIGIN_LOCAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /* Support IP_PKTINFO on tstamp packets if requested, to correlate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * timestamp with egress dev. Not possible for packets without iif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * or without payload (SOF_TIMESTAMPING_OPT_TSONLY).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) info = PKTINFO_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (!(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_CMSG) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) !info->ipi_ifindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) info->ipi_spec_dst.s_addr = ip_hdr(skb)->saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * Handle MSG_ERRQUEUE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) struct sock_exterr_skb *serr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct sock_extended_err ee;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) struct sockaddr_in offender;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) } errhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) int copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) err = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) skb = sock_dequeue_err_skb(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) copied = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (copied > len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) msg->msg_flags |= MSG_TRUNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) copied = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) err = skb_copy_datagram_msg(skb, 0, msg, copied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (unlikely(err)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) sock_recv_timestamp(msg, sk, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) serr = SKB_EXT_ERR(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (sin && ipv4_datagram_support_addr(serr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) sin->sin_family = AF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) serr->addr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) sin->sin_port = serr->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) *addr_len = sizeof(*sin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) sin = &errhdr.offender;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) memset(sin, 0, sizeof(*sin));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (ipv4_datagram_support_cmsg(sk, skb, serr->ee.ee_origin)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) sin->sin_family = AF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (inet_sk(sk)->cmsg_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) ip_cmsg_recv(msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) put_cmsg(msg, SOL_IP, IP_RECVERR, sizeof(errhdr), &errhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* Now we could try to dump offended packet options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) msg->msg_flags |= MSG_ERRQUEUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) err = copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) consume_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) static void __ip_sock_set_tos(struct sock *sk, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (sk->sk_type == SOCK_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) val &= ~INET_ECN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) val |= inet_sk(sk)->tos & INET_ECN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (inet_sk(sk)->tos != val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) inet_sk(sk)->tos = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) sk->sk_priority = rt_tos2priority(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) sk_dst_reset(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) void ip_sock_set_tos(struct sock *sk, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) __ip_sock_set_tos(sk, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) EXPORT_SYMBOL(ip_sock_set_tos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) void ip_sock_set_freebind(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) inet_sk(sk)->freebind = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) EXPORT_SYMBOL(ip_sock_set_freebind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) void ip_sock_set_recverr(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) inet_sk(sk)->recverr = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) EXPORT_SYMBOL(ip_sock_set_recverr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) int ip_sock_set_mtu_discover(struct sock *sk, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_OMIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) inet_sk(sk)->pmtudisc = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) EXPORT_SYMBOL(ip_sock_set_mtu_discover);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) void ip_sock_set_pktinfo(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) inet_sk(sk)->cmsg_flags |= IP_CMSG_PKTINFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) EXPORT_SYMBOL(ip_sock_set_pktinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * Socket option code for IP. This is the end of the line after any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * TCP,UDP etc options on an IP socket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static bool setsockopt_needs_rtnl(int optname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) switch (optname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) case IP_ADD_MEMBERSHIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) case IP_ADD_SOURCE_MEMBERSHIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) case IP_BLOCK_SOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) case IP_DROP_MEMBERSHIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) case IP_DROP_SOURCE_MEMBERSHIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) case IP_MSFILTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) case IP_UNBLOCK_SOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) case MCAST_BLOCK_SOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case MCAST_MSFILTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) case MCAST_JOIN_GROUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) case MCAST_JOIN_SOURCE_GROUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) case MCAST_LEAVE_GROUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) case MCAST_LEAVE_SOURCE_GROUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) case MCAST_UNBLOCK_SOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static int set_mcast_msfilter(struct sock *sk, int ifindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) int numsrc, int fmode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct sockaddr_storage *group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct sockaddr_storage *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) int msize = IP_MSFILTER_SIZE(numsrc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct ip_msfilter *msf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct sockaddr_in *psin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) msf = kmalloc(msize, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (!msf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) psin = (struct sockaddr_in *)group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (psin->sin_family != AF_INET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) goto Eaddrnotavail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) msf->imsf_multiaddr = psin->sin_addr.s_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) msf->imsf_interface = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) msf->imsf_fmode = fmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) msf->imsf_numsrc = numsrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) for (i = 0; i < numsrc; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) psin = (struct sockaddr_in *)&list[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (psin->sin_family != AF_INET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) goto Eaddrnotavail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) msf->imsf_slist[i] = psin->sin_addr.s_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) err = ip_mc_msfilter(sk, msf, ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) kfree(msf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) Eaddrnotavail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) kfree(msf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static int copy_group_source_from_sockptr(struct group_source_req *greqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) sockptr_t optval, int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (in_compat_syscall()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct compat_group_source_req gr32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (optlen != sizeof(gr32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (copy_from_sockptr(&gr32, optval, sizeof(gr32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) greqs->gsr_interface = gr32.gsr_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) greqs->gsr_group = gr32.gsr_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) greqs->gsr_source = gr32.gsr_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (optlen != sizeof(*greqs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (copy_from_sockptr(greqs, optval, sizeof(*greqs)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) static int do_mcast_group_source(struct sock *sk, int optname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) sockptr_t optval, int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct group_source_req greqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct ip_mreq_source mreqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) struct sockaddr_in *psin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int omode, add, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) err = copy_group_source_from_sockptr(&greqs, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (greqs.gsr_group.ss_family != AF_INET ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) greqs.gsr_source.ss_family != AF_INET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) psin = (struct sockaddr_in *)&greqs.gsr_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) mreqs.imr_multiaddr = psin->sin_addr.s_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) psin = (struct sockaddr_in *)&greqs.gsr_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) mreqs.imr_sourceaddr = psin->sin_addr.s_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) mreqs.imr_interface = 0; /* use index for mc_source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (optname == MCAST_BLOCK_SOURCE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) omode = MCAST_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) add = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) } else if (optname == MCAST_UNBLOCK_SOURCE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) omode = MCAST_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) add = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) } else if (optname == MCAST_JOIN_SOURCE_GROUP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct ip_mreqn mreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) psin = (struct sockaddr_in *)&greqs.gsr_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) mreq.imr_multiaddr = psin->sin_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) mreq.imr_address.s_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) mreq.imr_ifindex = greqs.gsr_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) err = ip_mc_join_group_ssm(sk, &mreq, MCAST_INCLUDE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (err && err != -EADDRINUSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) greqs.gsr_interface = mreq.imr_ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) omode = MCAST_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) add = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) } else /* MCAST_LEAVE_SOURCE_GROUP */ {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) omode = MCAST_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) add = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return ip_mc_source(add, omode, sk, &mreqs, greqs.gsr_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static int ip_set_mcast_msfilter(struct sock *sk, sockptr_t optval, int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) struct group_filter *gsf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (optlen < GROUP_FILTER_SIZE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (optlen > sysctl_optmem_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) gsf = memdup_sockptr(optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (IS_ERR(gsf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return PTR_ERR(gsf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) /* numsrc >= (4G-140)/128 overflow in 32 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (gsf->gf_numsrc >= 0x1ffffff ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) gsf->gf_numsrc > sock_net(sk)->ipv4.sysctl_igmp_max_msf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) goto out_free_gsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) goto out_free_gsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) err = set_mcast_msfilter(sk, gsf->gf_interface, gsf->gf_numsrc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) gsf->gf_fmode, &gsf->gf_group, gsf->gf_slist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) out_free_gsf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) kfree(gsf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) static int compat_ip_set_mcast_msfilter(struct sock *sk, sockptr_t optval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) const int size0 = offsetof(struct compat_group_filter, gf_slist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) struct compat_group_filter *gf32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) unsigned int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) void *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (optlen < size0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (optlen > sysctl_optmem_max - 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) p = kmalloc(optlen + 4, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) gf32 = p + 4; /* we want ->gf_group and ->gf_slist aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (copy_from_sockptr(gf32, optval, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) goto out_free_gsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) /* numsrc >= (4G-140)/128 overflow in 32 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) n = gf32->gf_numsrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (n >= 0x1ffffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) goto out_free_gsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (offsetof(struct compat_group_filter, gf_slist[n]) > optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) goto out_free_gsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) /* numsrc >= (4G-140)/128 overflow in 32 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (n > sock_net(sk)->ipv4.sysctl_igmp_max_msf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) goto out_free_gsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) err = set_mcast_msfilter(sk, gf32->gf_interface, n, gf32->gf_fmode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) &gf32->gf_group, gf32->gf_slist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) out_free_gsf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static int ip_mcast_join_leave(struct sock *sk, int optname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) sockptr_t optval, int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) struct ip_mreqn mreq = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct sockaddr_in *psin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) struct group_req greq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (optlen < sizeof(struct group_req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (copy_from_sockptr(&greq, optval, sizeof(greq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) psin = (struct sockaddr_in *)&greq.gr_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (psin->sin_family != AF_INET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) mreq.imr_multiaddr = psin->sin_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) mreq.imr_ifindex = greq.gr_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (optname == MCAST_JOIN_GROUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return ip_mc_join_group(sk, &mreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return ip_mc_leave_group(sk, &mreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) static int compat_ip_mcast_join_leave(struct sock *sk, int optname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) sockptr_t optval, int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) struct compat_group_req greq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) struct ip_mreqn mreq = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) struct sockaddr_in *psin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (optlen < sizeof(struct compat_group_req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (copy_from_sockptr(&greq, optval, sizeof(greq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) psin = (struct sockaddr_in *)&greq.gr_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (psin->sin_family != AF_INET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) mreq.imr_multiaddr = psin->sin_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) mreq.imr_ifindex = greq.gr_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (optname == MCAST_JOIN_GROUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) return ip_mc_join_group(sk, &mreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return ip_mc_leave_group(sk, &mreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) static int do_ip_setsockopt(struct sock *sk, int level, int optname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) sockptr_t optval, unsigned int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct inet_sock *inet = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) int val = 0, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) bool needs_rtnl = setsockopt_needs_rtnl(optname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) switch (optname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) case IP_PKTINFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) case IP_RECVTTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) case IP_RECVOPTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) case IP_RECVTOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) case IP_RETOPTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) case IP_TOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) case IP_TTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) case IP_HDRINCL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) case IP_MTU_DISCOVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) case IP_RECVERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) case IP_ROUTER_ALERT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) case IP_FREEBIND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) case IP_PASSSEC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) case IP_TRANSPARENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) case IP_MINTTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) case IP_NODEFRAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) case IP_BIND_ADDRESS_NO_PORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) case IP_UNICAST_IF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) case IP_MULTICAST_TTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) case IP_MULTICAST_ALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) case IP_MULTICAST_LOOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) case IP_RECVORIGDSTADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) case IP_CHECKSUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) case IP_RECVFRAGSIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) case IP_RECVERR_RFC4884:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (optlen >= sizeof(int)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (copy_from_sockptr(&val, optval, sizeof(val)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) } else if (optlen >= sizeof(char)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) unsigned char ucval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if (copy_from_sockptr(&ucval, optval, sizeof(ucval)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) val = (int) ucval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) /* If optlen==0, it is equivalent to val == 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (optname == IP_ROUTER_ALERT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return ip_ra_control(sk, val ? 1 : 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (ip_mroute_opt(optname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return ip_mroute_setsockopt(sk, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (needs_rtnl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) switch (optname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) case IP_OPTIONS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) struct ip_options_rcu *old, *opt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (optlen > 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) err = ip_options_get(sock_net(sk), &opt, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) old = rcu_dereference_protected(inet->inet_opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) lockdep_sock_is_held(sk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (inet->is_icsk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct inet_connection_sock *icsk = inet_csk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (sk->sk_family == PF_INET ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) (!((1 << sk->sk_state) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) (TCPF_LISTEN | TCPF_CLOSE)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) inet->inet_daddr != LOOPBACK4_IPV6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) icsk->icsk_ext_hdr_len -= old->opt.optlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) icsk->icsk_ext_hdr_len += opt->opt.optlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) rcu_assign_pointer(inet->inet_opt, opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) kfree_rcu(old, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) case IP_PKTINFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) inet->cmsg_flags |= IP_CMSG_PKTINFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) inet->cmsg_flags &= ~IP_CMSG_PKTINFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) case IP_RECVTTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) inet->cmsg_flags |= IP_CMSG_TTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) inet->cmsg_flags &= ~IP_CMSG_TTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) case IP_RECVTOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) inet->cmsg_flags |= IP_CMSG_TOS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) inet->cmsg_flags &= ~IP_CMSG_TOS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) case IP_RECVOPTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) inet->cmsg_flags |= IP_CMSG_RECVOPTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) inet->cmsg_flags &= ~IP_CMSG_RECVOPTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) case IP_RETOPTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) inet->cmsg_flags |= IP_CMSG_RETOPTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) inet->cmsg_flags &= ~IP_CMSG_RETOPTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) case IP_PASSSEC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) inet->cmsg_flags |= IP_CMSG_PASSSEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) inet->cmsg_flags &= ~IP_CMSG_PASSSEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) case IP_RECVORIGDSTADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) inet->cmsg_flags |= IP_CMSG_ORIGDSTADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) inet->cmsg_flags &= ~IP_CMSG_ORIGDSTADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) case IP_CHECKSUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (!(inet->cmsg_flags & IP_CMSG_CHECKSUM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) inet_inc_convert_csum(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) inet->cmsg_flags |= IP_CMSG_CHECKSUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (inet->cmsg_flags & IP_CMSG_CHECKSUM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) inet_dec_convert_csum(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) inet->cmsg_flags &= ~IP_CMSG_CHECKSUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) case IP_RECVFRAGSIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (sk->sk_type != SOCK_RAW && sk->sk_type != SOCK_DGRAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) inet->cmsg_flags |= IP_CMSG_RECVFRAGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) inet->cmsg_flags &= ~IP_CMSG_RECVFRAGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) case IP_TOS: /* This sets both TOS and Precedence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) __ip_sock_set_tos(sk, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) case IP_TTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (optlen < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) if (val != -1 && (val < 1 || val > 255))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) inet->uc_ttl = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) case IP_HDRINCL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (sk->sk_type != SOCK_RAW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) err = -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) inet->hdrincl = val ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) case IP_NODEFRAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (sk->sk_type != SOCK_RAW) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) err = -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) inet->nodefrag = val ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) case IP_BIND_ADDRESS_NO_PORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) inet->bind_address_no_port = val ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) case IP_MTU_DISCOVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_OMIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) inet->pmtudisc = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) case IP_RECVERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) inet->recverr = !!val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) skb_queue_purge(&sk->sk_error_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) case IP_RECVERR_RFC4884:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (val < 0 || val > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) inet->recverr_rfc4884 = !!val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) case IP_MULTICAST_TTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (sk->sk_type == SOCK_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (optlen < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) val = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (val < 0 || val > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) inet->mc_ttl = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) case IP_MULTICAST_LOOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (optlen < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) inet->mc_loop = !!val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) case IP_UNICAST_IF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) int ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) int midx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (optlen != sizeof(int))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) ifindex = (__force int)ntohl((__force __be32)val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if (ifindex == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) inet->uc_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) dev = dev_get_by_index(sock_net(sk), ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) err = -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) midx = l3mdev_master_ifindex(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (sk->sk_bound_dev_if && midx != sk->sk_bound_dev_if)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) inet->uc_index = ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) case IP_MULTICAST_IF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct ip_mreqn mreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) int midx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (sk->sk_type == SOCK_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) * Check the arguments are allowable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (optlen < sizeof(struct in_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) if (optlen >= sizeof(struct ip_mreqn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (copy_from_sockptr(&mreq, optval, sizeof(mreq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) memset(&mreq, 0, sizeof(mreq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (optlen >= sizeof(struct ip_mreq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (copy_from_sockptr(&mreq, optval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) sizeof(struct ip_mreq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) } else if (optlen >= sizeof(struct in_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (copy_from_sockptr(&mreq.imr_address, optval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) sizeof(struct in_addr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (!mreq.imr_ifindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (mreq.imr_address.s_addr == htonl(INADDR_ANY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) inet->mc_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) inet->mc_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) dev = ip_dev_find(sock_net(sk), mreq.imr_address.s_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) mreq.imr_ifindex = dev->ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) dev = dev_get_by_index(sock_net(sk), mreq.imr_ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) err = -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) midx = l3mdev_master_ifindex(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) if (sk->sk_bound_dev_if &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) mreq.imr_ifindex != sk->sk_bound_dev_if &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) midx != sk->sk_bound_dev_if)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) inet->mc_index = mreq.imr_ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) inet->mc_addr = mreq.imr_address.s_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) case IP_ADD_MEMBERSHIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) case IP_DROP_MEMBERSHIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) struct ip_mreqn mreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) err = -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (inet_sk(sk)->is_icsk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (optlen < sizeof(struct ip_mreq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) if (optlen >= sizeof(struct ip_mreqn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (copy_from_sockptr(&mreq, optval, sizeof(mreq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) memset(&mreq, 0, sizeof(mreq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (copy_from_sockptr(&mreq, optval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) sizeof(struct ip_mreq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (optname == IP_ADD_MEMBERSHIP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) err = ip_mc_join_group(sk, &mreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) err = ip_mc_leave_group(sk, &mreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) case IP_MSFILTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) struct ip_msfilter *msf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) if (optlen < IP_MSFILTER_SIZE(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (optlen > sysctl_optmem_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) err = -ENOBUFS;
^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) msf = memdup_sockptr(optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) if (IS_ERR(msf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) err = PTR_ERR(msf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) /* numsrc >= (1G-4) overflow in 32 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (msf->imsf_numsrc >= 0x3ffffffcU ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) msf->imsf_numsrc > net->ipv4.sysctl_igmp_max_msf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) kfree(msf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) kfree(msf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) err = ip_mc_msfilter(sk, msf, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) kfree(msf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) case IP_BLOCK_SOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) case IP_UNBLOCK_SOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) case IP_ADD_SOURCE_MEMBERSHIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) case IP_DROP_SOURCE_MEMBERSHIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) struct ip_mreq_source mreqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) int omode, add;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (optlen != sizeof(struct ip_mreq_source))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) if (copy_from_sockptr(&mreqs, optval, sizeof(mreqs))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if (optname == IP_BLOCK_SOURCE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) omode = MCAST_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) add = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) } else if (optname == IP_UNBLOCK_SOURCE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) omode = MCAST_EXCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) add = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) } else if (optname == IP_ADD_SOURCE_MEMBERSHIP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) struct ip_mreqn mreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) mreq.imr_multiaddr.s_addr = mreqs.imr_multiaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) mreq.imr_address.s_addr = mreqs.imr_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) mreq.imr_ifindex = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) err = ip_mc_join_group_ssm(sk, &mreq, MCAST_INCLUDE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (err && err != -EADDRINUSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) omode = MCAST_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) add = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) } else /* IP_DROP_SOURCE_MEMBERSHIP */ {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) omode = MCAST_INCLUDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) add = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) err = ip_mc_source(add, omode, sk, &mreqs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) case MCAST_JOIN_GROUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) case MCAST_LEAVE_GROUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) if (in_compat_syscall())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) err = compat_ip_mcast_join_leave(sk, optname, optval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) err = ip_mcast_join_leave(sk, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) case MCAST_JOIN_SOURCE_GROUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) case MCAST_LEAVE_SOURCE_GROUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) case MCAST_BLOCK_SOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) case MCAST_UNBLOCK_SOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) err = do_mcast_group_source(sk, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) case MCAST_MSFILTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (in_compat_syscall())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) err = compat_ip_set_mcast_msfilter(sk, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) err = ip_set_mcast_msfilter(sk, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) case IP_MULTICAST_ALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if (optlen < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) if (val != 0 && val != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) inet->mc_all = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) case IP_FREEBIND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) if (optlen < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) inet->freebind = !!val;
^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 IP_IPSEC_POLICY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) case IP_XFRM_POLICY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) err = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) err = xfrm_user_policy(sk, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) case IP_TRANSPARENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) if (!!val && !ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) !ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) err = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (optlen < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) inet->transparent = !!val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) case IP_MINTTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (optlen < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) if (val < 0 || val > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) goto e_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) inet->min_ttl = val;
^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) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) err = -ENOPROTOOPT;
^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) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (needs_rtnl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) e_inval:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (needs_rtnl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) * ipv4_pktinfo_prepare - transfer some info from rtable to skb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) * @sk: socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) * @skb: buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) * To support IP_CMSG_PKTINFO option, we store rt_iif and specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * destination in skb->cb[] before dst drop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * This way, receiver doesn't make cache line misses to read rtable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) struct in_pktinfo *pktinfo = PKTINFO_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) bool prepare = (inet_sk(sk)->cmsg_flags & IP_CMSG_PKTINFO) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) ipv6_sk_rxinfo(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) if (prepare && skb_rtable(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) /* skb->cb is overloaded: prior to this point it is IP{6}CB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * which has interface index (iif) as the first member of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * underlying inet{6}_skb_parm struct. This code then overlays
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) * PKTINFO_SKB_CB and in_pktinfo also has iif as the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) * element so the iif is picked up from the prior IPCB. If iif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) * is the loopback interface, then return the sending interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) * (e.g., process binds socket to eth0 for Tx which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) * redirected to loopback in the rtable/dst).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) struct rtable *rt = skb_rtable(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) bool l3slave = ipv4_l3mdev_skb(IPCB(skb)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if (pktinfo->ipi_ifindex == LOOPBACK_IFINDEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) pktinfo->ipi_ifindex = inet_iif(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) else if (l3slave && rt && rt->rt_iif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) pktinfo->ipi_ifindex = rt->rt_iif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) pktinfo->ipi_ifindex = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) pktinfo->ipi_spec_dst.s_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) skb_dst_drop(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) unsigned int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) if (level != SOL_IP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) return -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) err = do_ip_setsockopt(sk, level, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) #if IS_ENABLED(CONFIG_BPFILTER_UMH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (optname >= BPFILTER_IPT_SO_SET_REPLACE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) optname < BPFILTER_IPT_SET_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) err = bpfilter_ip_set_sockopt(sk, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) #ifdef CONFIG_NETFILTER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) /* we need to exclude all possible ENOPROTOOPTs except default case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) if (err == -ENOPROTOOPT && optname != IP_HDRINCL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) optname != IP_IPSEC_POLICY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) optname != IP_XFRM_POLICY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) !ip_mroute_opt(optname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) err = nf_setsockopt(sk, PF_INET, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) EXPORT_SYMBOL(ip_setsockopt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) * Get the options. Note for future reference. The GET of IP options gets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) * the _received_ ones. The set sets the _sent_ ones.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) static bool getsockopt_needs_rtnl(int optname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) switch (optname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) case IP_MSFILTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) case MCAST_MSFILTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) static int ip_get_mcast_msfilter(struct sock *sk, void __user *optval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) int __user *optlen, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) const int size0 = offsetof(struct group_filter, gf_slist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) struct group_filter __user *p = optval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) struct group_filter gsf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) int num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) if (len < size0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (copy_from_user(&gsf, p, size0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) num = gsf.gf_numsrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) err = ip_mc_gsfget(sk, &gsf, p->gf_slist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) if (gsf.gf_numsrc < num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) num = gsf.gf_numsrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) if (put_user(GROUP_FILTER_SIZE(num), optlen) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) copy_to_user(p, &gsf, size0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) static int compat_ip_get_mcast_msfilter(struct sock *sk, void __user *optval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) int __user *optlen, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) const int size0 = offsetof(struct compat_group_filter, gf_slist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) struct compat_group_filter __user *p = optval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) struct compat_group_filter gf32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) struct group_filter gf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) int num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (len < size0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) if (copy_from_user(&gf32, p, size0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) gf.gf_interface = gf32.gf_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) gf.gf_fmode = gf32.gf_fmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) num = gf.gf_numsrc = gf32.gf_numsrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) gf.gf_group = gf32.gf_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) err = ip_mc_gsfget(sk, &gf, p->gf_slist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) if (gf.gf_numsrc < num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) num = gf.gf_numsrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) len = GROUP_FILTER_SIZE(num) - (sizeof(gf) - sizeof(gf32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) if (put_user(len, optlen) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) put_user(gf.gf_fmode, &p->gf_fmode) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) put_user(gf.gf_numsrc, &p->gf_numsrc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) static int do_ip_getsockopt(struct sock *sk, int level, int optname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) char __user *optval, int __user *optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) struct inet_sock *inet = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) bool needs_rtnl = getsockopt_needs_rtnl(optname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) int val, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) if (level != SOL_IP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) if (ip_mroute_opt(optname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) return ip_mroute_getsockopt(sk, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) if (get_user(len, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) if (len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) if (needs_rtnl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) switch (optname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) case IP_OPTIONS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) unsigned char optbuf[sizeof(struct ip_options)+40];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) struct ip_options *opt = (struct ip_options *)optbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) struct ip_options_rcu *inet_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) inet_opt = rcu_dereference_protected(inet->inet_opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) lockdep_sock_is_held(sk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) opt->optlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) if (inet_opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) memcpy(optbuf, &inet_opt->opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) sizeof(struct ip_options) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) inet_opt->opt.optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) if (opt->optlen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) return put_user(0, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) ip_options_undo(opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) len = min_t(unsigned int, len, opt->optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) if (put_user(len, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) if (copy_to_user(optval, opt->__data, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) case IP_PKTINFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) val = (inet->cmsg_flags & IP_CMSG_PKTINFO) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) case IP_RECVTTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) val = (inet->cmsg_flags & IP_CMSG_TTL) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) case IP_RECVTOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) val = (inet->cmsg_flags & IP_CMSG_TOS) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) case IP_RECVOPTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) val = (inet->cmsg_flags & IP_CMSG_RECVOPTS) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) case IP_RETOPTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) case IP_PASSSEC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) case IP_RECVORIGDSTADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) val = (inet->cmsg_flags & IP_CMSG_ORIGDSTADDR) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) case IP_CHECKSUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) val = (inet->cmsg_flags & IP_CMSG_CHECKSUM) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) case IP_RECVFRAGSIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) val = (inet->cmsg_flags & IP_CMSG_RECVFRAGSIZE) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) case IP_TOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) val = inet->tos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) case IP_TTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) val = (inet->uc_ttl == -1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) net->ipv4.sysctl_ip_default_ttl :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) inet->uc_ttl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) case IP_HDRINCL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) val = inet->hdrincl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) case IP_NODEFRAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) val = inet->nodefrag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) case IP_BIND_ADDRESS_NO_PORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) val = inet->bind_address_no_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) case IP_MTU_DISCOVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) val = inet->pmtudisc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) case IP_MTU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) struct dst_entry *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) dst = sk_dst_get(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) if (dst) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) val = dst_mtu(dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) dst_release(dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) if (!val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) return -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) case IP_RECVERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) val = inet->recverr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) case IP_RECVERR_RFC4884:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) val = inet->recverr_rfc4884;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) case IP_MULTICAST_TTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) val = inet->mc_ttl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) case IP_MULTICAST_LOOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) val = inet->mc_loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) case IP_UNICAST_IF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) val = (__force int)htonl((__u32) inet->uc_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) case IP_MULTICAST_IF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) struct in_addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) len = min_t(unsigned int, len, sizeof(struct in_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) addr.s_addr = inet->mc_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) if (put_user(len, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) if (copy_to_user(optval, &addr, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) case IP_MSFILTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) struct ip_msfilter msf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) if (len < IP_MSFILTER_SIZE(0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) if (copy_from_user(&msf, optval, IP_MSFILTER_SIZE(0))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) err = ip_mc_msfget(sk, &msf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) (struct ip_msfilter __user *)optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) case MCAST_MSFILTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) if (in_compat_syscall())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) err = compat_ip_get_mcast_msfilter(sk, optval, optlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) err = ip_get_mcast_msfilter(sk, optval, optlen, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) case IP_MULTICAST_ALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) val = inet->mc_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) case IP_PKTOPTIONS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) struct msghdr msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) if (sk->sk_type != SOCK_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) return -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) msg.msg_control_is_user = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) msg.msg_control_user = optval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) msg.msg_controllen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) msg.msg_flags = in_compat_syscall() ? MSG_CMSG_COMPAT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) if (inet->cmsg_flags & IP_CMSG_PKTINFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) struct in_pktinfo info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) info.ipi_addr.s_addr = inet->inet_rcv_saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) info.ipi_spec_dst.s_addr = inet->inet_rcv_saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) info.ipi_ifindex = inet->mc_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) if (inet->cmsg_flags & IP_CMSG_TTL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) int hlim = inet->mc_ttl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) if (inet->cmsg_flags & IP_CMSG_TOS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) int tos = inet->rcv_tos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) put_cmsg(&msg, SOL_IP, IP_TOS, sizeof(tos), &tos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) len -= msg.msg_controllen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) return put_user(len, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) case IP_FREEBIND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) val = inet->freebind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) case IP_TRANSPARENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) val = inet->transparent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) case IP_MINTTL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) val = inet->min_ttl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) return -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) if (len < sizeof(int) && len > 0 && val >= 0 && val <= 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) unsigned char ucval = (unsigned char)val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) if (put_user(len, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if (copy_to_user(optval, &ucval, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) len = min_t(unsigned int, sizeof(int), len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) if (put_user(len, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) if (copy_to_user(optval, &val, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) if (needs_rtnl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) int ip_getsockopt(struct sock *sk, int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) int optname, char __user *optval, int __user *optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) err = do_ip_getsockopt(sk, level, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) #if IS_ENABLED(CONFIG_BPFILTER_UMH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) if (optname >= BPFILTER_IPT_SO_GET_INFO &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) optname < BPFILTER_IPT_GET_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) err = bpfilter_ip_get_sockopt(sk, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) #ifdef CONFIG_NETFILTER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) /* we need to exclude all possible ENOPROTOOPTs except default case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) !ip_mroute_opt(optname)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) if (get_user(len, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) err = nf_getsockopt(sk, PF_INET, optname, optval, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) err = put_user(len, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) EXPORT_SYMBOL(ip_getsockopt);