root/net/vmw_vsock/diag.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sk_diag_fill
  2. vsock_diag_dump
  3. vsock_diag_handler_dump
  4. vsock_diag_init
  5. vsock_diag_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * vsock sock_diag(7) module
   4  *
   5  * Copyright (C) 2017 Red Hat, Inc.
   6  * Author: Stefan Hajnoczi <stefanha@redhat.com>
   7  */
   8 
   9 #include <linux/module.h>
  10 #include <linux/sock_diag.h>
  11 #include <linux/vm_sockets_diag.h>
  12 #include <net/af_vsock.h>
  13 
  14 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
  15                         u32 portid, u32 seq, u32 flags)
  16 {
  17         struct vsock_sock *vsk = vsock_sk(sk);
  18         struct vsock_diag_msg *rep;
  19         struct nlmsghdr *nlh;
  20 
  21         nlh = nlmsg_put(skb, portid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep),
  22                         flags);
  23         if (!nlh)
  24                 return -EMSGSIZE;
  25 
  26         rep = nlmsg_data(nlh);
  27         rep->vdiag_family = AF_VSOCK;
  28 
  29         /* Lock order dictates that sk_lock is acquired before
  30          * vsock_table_lock, so we cannot lock here.  Simply don't take
  31          * sk_lock; sk is guaranteed to stay alive since vsock_table_lock is
  32          * held.
  33          */
  34         rep->vdiag_type = sk->sk_type;
  35         rep->vdiag_state = sk->sk_state;
  36         rep->vdiag_shutdown = sk->sk_shutdown;
  37         rep->vdiag_src_cid = vsk->local_addr.svm_cid;
  38         rep->vdiag_src_port = vsk->local_addr.svm_port;
  39         rep->vdiag_dst_cid = vsk->remote_addr.svm_cid;
  40         rep->vdiag_dst_port = vsk->remote_addr.svm_port;
  41         rep->vdiag_ino = sock_i_ino(sk);
  42 
  43         sock_diag_save_cookie(sk, rep->vdiag_cookie);
  44 
  45         return 0;
  46 }
  47 
  48 static int vsock_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
  49 {
  50         struct vsock_diag_req *req;
  51         struct vsock_sock *vsk;
  52         unsigned int bucket;
  53         unsigned int last_i;
  54         unsigned int table;
  55         struct net *net;
  56         unsigned int i;
  57 
  58         req = nlmsg_data(cb->nlh);
  59         net = sock_net(skb->sk);
  60 
  61         /* State saved between calls: */
  62         table = cb->args[0];
  63         bucket = cb->args[1];
  64         i = last_i = cb->args[2];
  65 
  66         /* TODO VMCI pending sockets? */
  67 
  68         spin_lock_bh(&vsock_table_lock);
  69 
  70         /* Bind table (locally created sockets) */
  71         if (table == 0) {
  72                 while (bucket < ARRAY_SIZE(vsock_bind_table)) {
  73                         struct list_head *head = &vsock_bind_table[bucket];
  74 
  75                         i = 0;
  76                         list_for_each_entry(vsk, head, bound_table) {
  77                                 struct sock *sk = sk_vsock(vsk);
  78 
  79                                 if (!net_eq(sock_net(sk), net))
  80                                         continue;
  81                                 if (i < last_i)
  82                                         goto next_bind;
  83                                 if (!(req->vdiag_states & (1 << sk->sk_state)))
  84                                         goto next_bind;
  85                                 if (sk_diag_fill(sk, skb,
  86                                                  NETLINK_CB(cb->skb).portid,
  87                                                  cb->nlh->nlmsg_seq,
  88                                                  NLM_F_MULTI) < 0)
  89                                         goto done;
  90 next_bind:
  91                                 i++;
  92                         }
  93                         last_i = 0;
  94                         bucket++;
  95                 }
  96 
  97                 table++;
  98                 bucket = 0;
  99         }
 100 
 101         /* Connected table (accepted connections) */
 102         while (bucket < ARRAY_SIZE(vsock_connected_table)) {
 103                 struct list_head *head = &vsock_connected_table[bucket];
 104 
 105                 i = 0;
 106                 list_for_each_entry(vsk, head, connected_table) {
 107                         struct sock *sk = sk_vsock(vsk);
 108 
 109                         /* Skip sockets we've already seen above */
 110                         if (__vsock_in_bound_table(vsk))
 111                                 continue;
 112 
 113                         if (!net_eq(sock_net(sk), net))
 114                                 continue;
 115                         if (i < last_i)
 116                                 goto next_connected;
 117                         if (!(req->vdiag_states & (1 << sk->sk_state)))
 118                                 goto next_connected;
 119                         if (sk_diag_fill(sk, skb,
 120                                          NETLINK_CB(cb->skb).portid,
 121                                          cb->nlh->nlmsg_seq,
 122                                          NLM_F_MULTI) < 0)
 123                                 goto done;
 124 next_connected:
 125                         i++;
 126                 }
 127                 last_i = 0;
 128                 bucket++;
 129         }
 130 
 131 done:
 132         spin_unlock_bh(&vsock_table_lock);
 133 
 134         cb->args[0] = table;
 135         cb->args[1] = bucket;
 136         cb->args[2] = i;
 137 
 138         return skb->len;
 139 }
 140 
 141 static int vsock_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
 142 {
 143         int hdrlen = sizeof(struct vsock_diag_req);
 144         struct net *net = sock_net(skb->sk);
 145 
 146         if (nlmsg_len(h) < hdrlen)
 147                 return -EINVAL;
 148 
 149         if (h->nlmsg_flags & NLM_F_DUMP) {
 150                 struct netlink_dump_control c = {
 151                         .dump = vsock_diag_dump,
 152                 };
 153                 return netlink_dump_start(net->diag_nlsk, skb, h, &c);
 154         }
 155 
 156         return -EOPNOTSUPP;
 157 }
 158 
 159 static const struct sock_diag_handler vsock_diag_handler = {
 160         .family = AF_VSOCK,
 161         .dump = vsock_diag_handler_dump,
 162 };
 163 
 164 static int __init vsock_diag_init(void)
 165 {
 166         return sock_diag_register(&vsock_diag_handler);
 167 }
 168 
 169 static void __exit vsock_diag_exit(void)
 170 {
 171         sock_diag_unregister(&vsock_diag_handler);
 172 }
 173 
 174 module_init(vsock_diag_init);
 175 module_exit(vsock_diag_exit);
 176 MODULE_LICENSE("GPL");
 177 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG,
 178                                40 /* AF_VSOCK */);

/* [<][>][^][v][top][bottom][index][help] */