LCOV - code coverage report
Current view: top level - net/ipv4 - ping.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 10 528 1.9 %
Date: 2021-04-22 12:43:58 Functions: 3 32 9.4 %

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

Generated by: LCOV version 1.14