^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * 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) * "Ping" sockets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Based on ipv4/udp.c code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Authors: Vasiliy Kulikov / Openwall (for Linux 2.6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Pavel Kankovsky (for Linux 2.4.32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Pavel gave all rights to bugs to Vasiliy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * none of the bugs are Pavel's now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/sockios.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/inet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <net/snmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <net/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <net/icmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <net/protocol.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <net/ping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <net/udp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <net/route.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <net/inet_common.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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/in6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/icmpv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <net/addrconf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <net/ipv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <net/transp_v6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct ping_table {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct hlist_nulls_head hash[PING_HTABLE_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) rwlock_t lock;
^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 struct ping_table ping_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct pingv6_ops pingv6_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) EXPORT_SYMBOL_GPL(pingv6_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static u16 ping_port_rover;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static inline u32 ping_hashfn(const struct net *net, u32 num, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u32 res = (num + net_hash_mix(net)) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) pr_debug("hash(%u) = %u\n", num, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) EXPORT_SYMBOL_GPL(ping_hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct net *net, unsigned int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return &table->hash[ping_hashfn(net, num, PING_HTABLE_MASK)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int ping_get_port(struct sock *sk, unsigned short ident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct hlist_nulls_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct hlist_nulls_head *hlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct inet_sock *isk, *isk2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct sock *sk2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) isk = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) write_lock_bh(&ping_table.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (ident == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u16 result = ping_port_rover + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) for (i = 0; i < (1L << 16); i++, result++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (!result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) result++; /* avoid zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) hlist = ping_hashslot(&ping_table, sock_net(sk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ping_portaddr_for_each_entry(sk2, node, hlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) isk2 = inet_sk(sk2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (isk2->inet_num == result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) goto next_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ping_port_rover = ident = result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) next_port:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (i >= (1L << 16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) hlist = ping_hashslot(&ping_table, sock_net(sk), ident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ping_portaddr_for_each_entry(sk2, node, hlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) isk2 = inet_sk(sk2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* BUG? Why is this reuse and not reuseaddr? ping.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * doesn't turn off SO_REUSEADDR, and it doesn't expect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * that other ping processes can steal its packets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if ((isk2->inet_num == ident) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) (sk2 != sk) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) (!sk2->sk_reuse || !sk->sk_reuse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) pr_debug("found port/ident = %d\n", ident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) isk->inet_num = ident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (sk_unhashed(sk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) pr_debug("was not hashed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) sock_hold(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) hlist_nulls_add_head(&sk->sk_nulls_node, hlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) write_unlock_bh(&ping_table.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) write_unlock_bh(&ping_table.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) EXPORT_SYMBOL_GPL(ping_get_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int ping_hash(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) pr_debug("ping_hash(sk->port=%u)\n", inet_sk(sk)->inet_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) BUG(); /* "Please do not press this button again." */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) void ping_unhash(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct inet_sock *isk = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) write_lock_bh(&ping_table.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (sk_hashed(sk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) hlist_nulls_del(&sk->sk_nulls_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) sk_nulls_node_init(&sk->sk_nulls_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) sock_put(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) isk->inet_num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) isk->inet_sport = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) write_unlock_bh(&ping_table.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) EXPORT_SYMBOL_GPL(ping_unhash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct hlist_nulls_head *hslot = ping_hashslot(&ping_table, net, ident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct sock *sk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct inet_sock *isk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct hlist_nulls_node *hnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int dif, sdif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (skb->protocol == htons(ETH_P_IP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) dif = inet_iif(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) sdif = inet_sdif(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) (int)ident, &ip_hdr(skb)->daddr, dif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) } else if (skb->protocol == htons(ETH_P_IPV6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) dif = inet6_iif(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) sdif = inet6_sdif(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) pr_debug("try to find: num = %d, daddr = %pI6c, dif = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) (int)ident, &ipv6_hdr(skb)->daddr, dif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) read_lock_bh(&ping_table.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ping_portaddr_for_each_entry(sk, hnode, hslot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) isk = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) pr_debug("iterate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (isk->inet_num != ident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (skb->protocol == htons(ETH_P_IP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) sk->sk_family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) pr_debug("found: %p: num=%d, daddr=%pI4, dif=%d\n", sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) (int) isk->inet_num, &isk->inet_rcv_saddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) sk->sk_bound_dev_if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (isk->inet_rcv_saddr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) isk->inet_rcv_saddr != ip_hdr(skb)->daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) } else if (skb->protocol == htons(ETH_P_IPV6) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) sk->sk_family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) pr_debug("found: %p: num=%d, daddr=%pI6c, dif=%d\n", sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) (int) isk->inet_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) &sk->sk_v6_rcv_saddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) sk->sk_bound_dev_if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) !ipv6_addr_equal(&sk->sk_v6_rcv_saddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) &ipv6_hdr(skb)->daddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) sk->sk_bound_dev_if != sdif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) sock_hold(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) sk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) read_unlock_bh(&ping_table.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static void inet_get_ping_group_range_net(struct net *net, kgid_t *low,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) kgid_t *high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) kgid_t *data = net->ipv4.ping_group_range.range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) unsigned int seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) seq = read_seqbegin(&net->ipv4.ping_group_range.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) *low = data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) *high = data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) } while (read_seqretry(&net->ipv4.ping_group_range.lock, seq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int ping_init_sock(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) kgid_t group = current_egid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct group_info *group_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) kgid_t low, high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (sk->sk_family == AF_INET6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) sk->sk_ipv6only = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) inet_get_ping_group_range_net(net, &low, &high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (gid_lte(low, group) && gid_lte(group, high))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) group_info = get_current_groups();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) for (i = 0; i < group_info->ngroups; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) kgid_t gid = group_info->gid[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (gid_lte(low, gid) && gid_lte(gid, high))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) goto out_release_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ret = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) out_release_group:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) put_group_info(group_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) EXPORT_SYMBOL_GPL(ping_init_sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) void ping_close(struct sock *sk, long timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) pr_debug("ping_close(sk=%p,sk->num=%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) inet_sk(sk), inet_sk(sk)->inet_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) pr_debug("isk->refcnt = %d\n", refcount_read(&sk->sk_refcnt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) sk_common_release(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) EXPORT_SYMBOL_GPL(ping_close);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* Checks the bind address and possibly modifies sk->sk_bound_dev_if. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct sockaddr *uaddr, int addr_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (sk->sk_family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int chk_addr_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (addr_len < sizeof(*addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (addr->sin_family != AF_INET &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) !(addr->sin_family == AF_UNSPEC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) addr->sin_addr.s_addr == htonl(INADDR_ANY)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (addr->sin_addr.s_addr == htonl(INADDR_ANY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) chk_addr_ret = RTN_LOCAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if ((!inet_can_nonlocal_bind(net, isk) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) chk_addr_ret != RTN_LOCAL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) chk_addr_ret == RTN_MULTICAST ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) chk_addr_ret == RTN_BROADCAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) } else if (sk->sk_family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) int addr_type, scoped, has_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (addr_len < sizeof(*addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (addr->sin6_family != AF_INET6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) addr_type = ipv6_addr_type(&addr->sin6_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) scoped = __ipv6_addr_needs_scope_id(addr_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if ((addr_type != IPV6_ADDR_ANY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) !(addr_type & IPV6_ADDR_UNICAST)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) (scoped && !addr->sin6_scope_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (addr->sin6_scope_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) dev = dev_get_by_index_rcu(net, addr->sin6_scope_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) has_addr = pingv6_ops.ipv6_chk_addr(net, &addr->sin6_addr, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) scoped);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (!(ipv6_can_nonlocal_bind(net, isk) || has_addr ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) addr_type == IPV6_ADDR_ANY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (scoped)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) sk->sk_bound_dev_if = addr->sin6_scope_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static void ping_set_saddr(struct sock *sk, struct sockaddr *saddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (saddr->sa_family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) struct inet_sock *isk = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct sockaddr_in *addr = (struct sockaddr_in *) saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) } else if (saddr->sa_family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) struct sockaddr_in6 *addr = (struct sockaddr_in6 *) saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct ipv6_pinfo *np = inet6_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) sk->sk_v6_rcv_saddr = np->saddr = addr->sin6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) #endif
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * We need our own bind because there are no privileged id's == local ports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * Moreover, we don't allow binding to multi- and broadcast addresses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct inet_sock *isk = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) unsigned short snum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int dif = sk->sk_bound_dev_if;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) err = ping_check_bind_addr(sk, isk, uaddr, addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (isk->inet_num != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) err = -EADDRINUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) snum = ntohs(((struct sockaddr_in *)uaddr)->sin_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (ping_get_port(sk, snum) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /* Restore possibly modified sk->sk_bound_dev_if by ping_check_bind_addr(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) sk->sk_bound_dev_if = dif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) ping_set_saddr(sk, uaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) pr_debug("after bind(): num = %hu, dif = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) isk->inet_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) sk->sk_bound_dev_if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (sk->sk_family == AF_INET && isk->inet_rcv_saddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) sk->sk_userlocks |= SOCK_BINDADDR_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (sk->sk_family == AF_INET6 && !ipv6_addr_any(&sk->sk_v6_rcv_saddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) sk->sk_userlocks |= SOCK_BINDADDR_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (snum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) isk->inet_sport = htons(isk->inet_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) isk->inet_daddr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) isk->inet_dport = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (sk->sk_family == AF_INET6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) memset(&sk->sk_v6_daddr, 0, sizeof(sk->sk_v6_daddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) sk_dst_reset(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) pr_debug("ping_v4_bind -> %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) EXPORT_SYMBOL_GPL(ping_bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * Is this a supported type of ICMP message?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static inline int ping_supported(int family, int type, int code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return (family == AF_INET && type == ICMP_ECHO && code == 0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) (family == AF_INET6 && type == ICMPV6_ECHO_REQUEST && code == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * This routine is called by the ICMP module when it gets some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * sort of error condition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) void ping_err(struct sk_buff *skb, int offset, u32 info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) int family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct icmphdr *icmph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct inet_sock *inet_sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct net *net = dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int harderr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (skb->protocol == htons(ETH_P_IP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) family = AF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) type = icmp_hdr(skb)->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) code = icmp_hdr(skb)->code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) icmph = (struct icmphdr *)(skb->data + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) } else if (skb->protocol == htons(ETH_P_IPV6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) family = AF_INET6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) type = icmp6_hdr(skb)->icmp6_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) code = icmp6_hdr(skb)->icmp6_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) icmph = (struct icmphdr *) (skb->data + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /* We assume the packet has already been checked by icmp_unreach */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (!ping_supported(family, icmph->type, icmph->code))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) pr_debug("ping_err(proto=0x%x,type=%d,code=%d,id=%04x,seq=%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) skb->protocol, type, code, ntohs(icmph->un.echo.id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) ntohs(icmph->un.echo.sequence));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (!sk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) pr_debug("no socket, dropping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return; /* No socket for error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) pr_debug("err on socket %p\n", sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) harderr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) inet_sock = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (skb->protocol == htons(ETH_P_IP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) case ICMP_TIME_EXCEEDED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) err = EHOSTUNREACH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) case ICMP_SOURCE_QUENCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* This is not a real error but ping wants to see it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * Report it with some fake errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) err = EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) case ICMP_PARAMETERPROB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) err = EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) harderr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) case ICMP_DEST_UNREACH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ipv4_sk_update_pmtu(skb, sk, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) err = EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) harderr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) err = EHOSTUNREACH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (code <= NR_ICMP_UNREACH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) harderr = icmp_err_convert[code].fatal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) err = icmp_err_convert[code].errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) case ICMP_REDIRECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /* See ICMP_SOURCE_QUENCH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ipv4_sk_redirect(skb, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) err = EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) } else if (skb->protocol == htons(ETH_P_IPV6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) harderr = pingv6_ops.icmpv6_err_convert(type, code, &err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * RFC1122: OK. Passes ICMP errors back to application, as per
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * 4.1.3.3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if ((family == AF_INET && !inet_sock->recverr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) (family == AF_INET6 && !inet6_sk(sk)->recverr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (!harderr || sk->sk_state != TCP_ESTABLISHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) ip_icmp_error(sk, skb, err, 0 /* no remote port */,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) info, (u8 *)icmph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) } else if (family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) pingv6_ops.ipv6_icmp_error(sk, skb, err, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) info, (u8 *)icmph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) sk->sk_err = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) sk->sk_error_report(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) sock_put(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) EXPORT_SYMBOL_GPL(ping_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * Copy and checksum an ICMP Echo packet from user space into a buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * starting from the payload.
^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) int ping_getfrag(void *from, char *to,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int offset, int fraglen, int odd, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct pingfakehdr *pfh = (struct pingfakehdr *)from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (offset == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) fraglen -= sizeof(struct icmphdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (fraglen < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (!csum_and_copy_from_iter_full(to + sizeof(struct icmphdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) fraglen, &pfh->wcheck,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) &pfh->msg->msg_iter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) } else if (offset < sizeof(struct icmphdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (!csum_and_copy_from_iter_full(to, fraglen, &pfh->wcheck,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) &pfh->msg->msg_iter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /* For IPv6, checksum each skb as we go along, as expected by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * icmpv6_push_pending_frames. For IPv4, accumulate the checksum in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * wcheck, it will be finalized in ping_v4_push_pending_frames.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (pfh->family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) skb->csum = pfh->wcheck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) skb->ip_summed = CHECKSUM_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) pfh->wcheck = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) EXPORT_SYMBOL_GPL(ping_getfrag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) static int ping_v4_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct flowi4 *fl4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct sk_buff *skb = skb_peek(&sk->sk_write_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) pfh->wcheck = csum_partial((char *)&pfh->icmph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) sizeof(struct icmphdr), pfh->wcheck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) pfh->icmph.checksum = csum_fold(pfh->wcheck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) memcpy(icmp_hdr(skb), &pfh->icmph, sizeof(struct icmphdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) skb->ip_summed = CHECKSUM_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return ip_push_pending_frames(sk, fl4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) int ping_common_sendmsg(int family, struct msghdr *msg, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) void *user_icmph, size_t icmph_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) u8 type, code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (len > 0xFFFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /* Must have at least a full ICMP header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (len < icmph_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * Check the flags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /* Mirror BSD error message compatibility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (msg->msg_flags & MSG_OOB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * Fetch the ICMP header provided by the userland.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * iovec is modified! The ICMP header is consumed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (memcpy_from_msg(user_icmph, msg, icmph_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) type = ((struct icmphdr *) user_icmph)->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) code = ((struct icmphdr *) user_icmph)->code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) } else if (family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) type = ((struct icmp6hdr *) user_icmph)->icmp6_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) code = ((struct icmp6hdr *) user_icmph)->icmp6_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (!ping_supported(family, type, code))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) EXPORT_SYMBOL_GPL(ping_common_sendmsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct net *net = sock_net(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct flowi4 fl4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct inet_sock *inet = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) struct ipcm_cookie ipc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) struct icmphdr user_icmph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct pingfakehdr pfh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct rtable *rt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct ip_options_data opt_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) int free = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) __be32 saddr, daddr, faddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) u8 tos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) pr_debug("ping_v4_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) err = ping_common_sendmsg(AF_INET, msg, len, &user_icmph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) sizeof(user_icmph));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * Get and verify the address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (msg->msg_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) DECLARE_SOCKADDR(struct sockaddr_in *, usin, msg->msg_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (msg->msg_namelen < sizeof(*usin))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (usin->sin_family != AF_INET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) daddr = usin->sin_addr.s_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) /* no remote port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (sk->sk_state != TCP_ESTABLISHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return -EDESTADDRREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) daddr = inet->inet_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) /* no remote port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) ipcm_init_sk(&ipc, inet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (msg->msg_controllen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) err = ip_cmsg_send(sk, msg, &ipc, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (unlikely(err)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) kfree(ipc.opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (ipc.opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) free = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (!ipc.opt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct ip_options_rcu *inet_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) inet_opt = rcu_dereference(inet->inet_opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (inet_opt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) memcpy(&opt_copy, inet_opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) sizeof(*inet_opt) + inet_opt->opt.optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ipc.opt = &opt_copy.opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) saddr = ipc.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) ipc.addr = faddr = daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (ipc.opt && ipc.opt->opt.srr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (!daddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) faddr = ipc.opt->opt.faddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) tos = get_rttos(&ipc, inet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (sock_flag(sk, SOCK_LOCALROUTE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) (msg->msg_flags & MSG_DONTROUTE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) (ipc.opt && ipc.opt->opt.is_strictroute)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) tos |= RTO_ONLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (ipv4_is_multicast(daddr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (!ipc.oif || netif_index_is_l3_master(sock_net(sk), ipc.oif))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) ipc.oif = inet->mc_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (!saddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) saddr = inet->mc_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) } else if (!ipc.oif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) ipc.oif = inet->uc_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark, tos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) RT_SCOPE_UNIVERSE, sk->sk_protocol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) inet_sk_flowi_flags(sk), faddr, saddr, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) sk->sk_uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) fl4.fl4_icmp_type = user_icmph.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) fl4.fl4_icmp_code = user_icmph.code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) rt = ip_route_output_flow(net, &fl4, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (IS_ERR(rt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) err = PTR_ERR(rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) rt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (err == -ENETUNREACH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) err = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if ((rt->rt_flags & RTCF_BROADCAST) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) !sock_flag(sk, SOCK_BROADCAST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (msg->msg_flags & MSG_CONFIRM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) goto do_confirm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) back_from_confirm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (!ipc.addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) ipc.addr = fl4.daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) pfh.icmph.type = user_icmph.type; /* already checked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) pfh.icmph.code = user_icmph.code; /* ditto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) pfh.icmph.checksum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) pfh.icmph.un.echo.id = inet->inet_sport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) pfh.msg = msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) pfh.wcheck = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) pfh.family = AF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) err = ip_append_data(sk, &fl4, ping_getfrag, &pfh, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 0, &ipc, &rt, msg->msg_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ip_flush_pending_frames(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) err = ping_v4_push_pending_frames(sk, &pfh, &fl4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) ip_rt_put(rt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) kfree(ipc.opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) icmp_out_count(sock_net(sk), user_icmph.type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) do_confirm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (msg->msg_flags & MSG_PROBE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) dst_confirm_neigh(&rt->dst, &fl4.daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (!(msg->msg_flags & MSG_PROBE) || len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) goto back_from_confirm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) int ping_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) int flags, int *addr_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) struct inet_sock *isk = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) int family = sk->sk_family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) int copied, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) pr_debug("ping_recvmsg(sk=%p,sk->num=%u)\n", isk, isk->inet_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) err = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (flags & MSG_OOB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (flags & MSG_ERRQUEUE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return inet_recv_error(sk, msg, len, addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) skb = skb_recv_datagram(sk, flags, noblock, &err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) copied = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (copied > len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) msg->msg_flags |= MSG_TRUNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) copied = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) /* Don't bother checking the checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) err = skb_copy_datagram_msg(skb, 0, msg, copied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) sock_recv_timestamp(msg, sk, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) /* Copy the address and add cmsg data. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (sin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) sin->sin_family = AF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) sin->sin_port = 0 /* skb->h.uh->source */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) *addr_len = sizeof(*sin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (isk->cmsg_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) ip_cmsg_recv(msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) } else if (family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) struct ipv6_pinfo *np = inet6_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct ipv6hdr *ip6 = ipv6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (sin6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) sin6->sin6_family = AF_INET6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) sin6->sin6_port = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) sin6->sin6_addr = ip6->saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) sin6->sin6_flowinfo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (np->sndflow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) sin6->sin6_flowinfo = ip6_flowinfo(ip6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) sin6->sin6_scope_id =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) ipv6_iface_scope_id(&sin6->sin6_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) inet6_iif(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) *addr_len = sizeof(*sin6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (inet6_sk(sk)->rxopt.all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) pingv6_ops.ip6_datagram_recv_common_ctl(sk, msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (skb->protocol == htons(ETH_P_IPV6) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) inet6_sk(sk)->rxopt.all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) pingv6_ops.ip6_datagram_recv_specific_ctl(sk, msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) else if (skb->protocol == htons(ETH_P_IP) && isk->cmsg_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) ip_cmsg_recv(msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) err = copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) skb_free_datagram(sk, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) pr_debug("ping_recvmsg -> %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) EXPORT_SYMBOL_GPL(ping_recvmsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) inet_sk(sk), inet_sk(sk)->inet_num, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (sock_queue_rcv_skb(sk, skb) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) pr_debug("ping_queue_rcv_skb -> failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) EXPORT_SYMBOL_GPL(ping_queue_rcv_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * All we need to do is get the socket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) bool ping_rcv(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct net *net = dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) struct icmphdr *icmph = icmp_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) bool rc = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) /* We assume the packet has already been checked by icmp_rcv */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) pr_debug("ping_rcv(skb=%p,id=%04x,seq=%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) skb, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) /* Push ICMP header back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) skb_push(skb, skb->data - (u8 *)icmph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (sk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) pr_debug("rcv on socket %p\n", sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (skb2 && !ping_queue_rcv_skb(sk, skb2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) rc = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) sock_put(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) pr_debug("no socket, dropping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) EXPORT_SYMBOL_GPL(ping_rcv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) struct proto ping_prot = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) .name = "PING",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) .init = ping_init_sock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) .close = ping_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .connect = ip4_datagram_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) .disconnect = __udp_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) .setsockopt = ip_setsockopt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) .getsockopt = ip_getsockopt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) .sendmsg = ping_v4_sendmsg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) .recvmsg = ping_recvmsg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) .bind = ping_bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) .backlog_rcv = ping_queue_rcv_skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) .release_cb = ip4_datagram_release_cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) .hash = ping_hash,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) .unhash = ping_unhash,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) .get_port = ping_get_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) .obj_size = sizeof(struct inet_sock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) EXPORT_SYMBOL(ping_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) static struct sock *ping_get_first(struct seq_file *seq, int start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) struct ping_iter_state *state = seq->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) struct net *net = seq_file_net(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) for (state->bucket = start; state->bucket < PING_HTABLE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) ++state->bucket) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) struct hlist_nulls_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) struct hlist_nulls_head *hslot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) hslot = &ping_table.hash[state->bucket];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (hlist_nulls_empty(hslot))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) sk_nulls_for_each(sk, node, hslot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (net_eq(sock_net(sk), net) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) sk->sk_family == state->family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) sk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static struct sock *ping_get_next(struct seq_file *seq, struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) struct ping_iter_state *state = seq->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) struct net *net = seq_file_net(seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) sk = sk_nulls_next(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) } while (sk && (!net_eq(sock_net(sk), net)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (!sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return ping_get_first(seq, state->bucket + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) struct sock *sk = ping_get_first(seq, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) while (pos && (sk = ping_get_next(seq, sk)) != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) --pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) return pos ? NULL : sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) __acquires(ping_table.lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct ping_iter_state *state = seq->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) state->bucket = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) state->family = family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) read_lock_bh(&ping_table.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) EXPORT_SYMBOL_GPL(ping_seq_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) static void *ping_v4_seq_start(struct seq_file *seq, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) return ping_seq_start(seq, pos, AF_INET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (v == SEQ_START_TOKEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) sk = ping_get_idx(seq, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) sk = ping_get_next(seq, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) ++*pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) return sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) EXPORT_SYMBOL_GPL(ping_seq_next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) void ping_seq_stop(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) __releases(ping_table.lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) read_unlock_bh(&ping_table.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) EXPORT_SYMBOL_GPL(ping_seq_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) static void ping_v4_format_sock(struct sock *sp, struct seq_file *f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) int bucket)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) struct inet_sock *inet = inet_sk(sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) __be32 dest = inet->inet_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) __be32 src = inet->inet_rcv_saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) __u16 destp = ntohs(inet->inet_dport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) __u16 srcp = ntohs(inet->inet_sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) seq_printf(f, "%5d: %08X:%04X %08X:%04X"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) " %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) bucket, src, srcp, dest, destp, sp->sk_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) sk_wmem_alloc_get(sp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) sk_rmem_alloc_get(sp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 0, 0L, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 0, sock_i_ino(sp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) refcount_read(&sp->sk_refcnt), sp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) atomic_read(&sp->sk_drops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static int ping_v4_seq_show(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) seq_setwidth(seq, 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (v == SEQ_START_TOKEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) seq_puts(seq, " sl local_address rem_address st tx_queue "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) "rx_queue tr tm->when retrnsmt uid timeout "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) "inode ref pointer drops");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) struct ping_iter_state *state = seq->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) ping_v4_format_sock(v, seq, state->bucket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) seq_pad(seq, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) static const struct seq_operations ping_v4_seq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) .start = ping_v4_seq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) .show = ping_v4_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) .next = ping_seq_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) .stop = ping_seq_stop,
^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) static int __net_init ping_v4_proc_init_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (!proc_create_net("icmp", 0444, net->proc_net, &ping_v4_seq_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) sizeof(struct ping_iter_state)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) static void __net_exit ping_v4_proc_exit_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) remove_proc_entry("icmp", net->proc_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) static struct pernet_operations ping_v4_net_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) .init = ping_v4_proc_init_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) .exit = ping_v4_proc_exit_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) int __init ping_proc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return register_pernet_subsys(&ping_v4_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) void ping_proc_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) unregister_pernet_subsys(&ping_v4_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) void __init ping_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) for (i = 0; i < PING_HTABLE_SIZE; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) INIT_HLIST_NULLS_HEAD(&ping_table.hash[i], i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) rwlock_init(&ping_table.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }