diag.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * vsock sock_diag(7) module
  3. *
  4. * Copyright (C) 2017 Red Hat, Inc.
  5. * Author: Stefan Hajnoczi <stefanha@redhat.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the Free
  9. * Software Foundation version 2 and no later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14. * more details.
  15. */
  16. #include <linux/module.h>
  17. #include <linux/sock_diag.h>
  18. #include <linux/vm_sockets_diag.h>
  19. #include <net/af_vsock.h>
  20. static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
  21. u32 portid, u32 seq, u32 flags)
  22. {
  23. struct vsock_sock *vsk = vsock_sk(sk);
  24. struct vsock_diag_msg *rep;
  25. struct nlmsghdr *nlh;
  26. nlh = nlmsg_put(skb, portid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep),
  27. flags);
  28. if (!nlh)
  29. return -EMSGSIZE;
  30. rep = nlmsg_data(nlh);
  31. rep->vdiag_family = AF_VSOCK;
  32. /* Lock order dictates that sk_lock is acquired before
  33. * vsock_table_lock, so we cannot lock here. Simply don't take
  34. * sk_lock; sk is guaranteed to stay alive since vsock_table_lock is
  35. * held.
  36. */
  37. rep->vdiag_type = sk->sk_type;
  38. rep->vdiag_state = sk->sk_state;
  39. rep->vdiag_shutdown = sk->sk_shutdown;
  40. rep->vdiag_src_cid = vsk->local_addr.svm_cid;
  41. rep->vdiag_src_port = vsk->local_addr.svm_port;
  42. rep->vdiag_dst_cid = vsk->remote_addr.svm_cid;
  43. rep->vdiag_dst_port = vsk->remote_addr.svm_port;
  44. rep->vdiag_ino = sock_i_ino(sk);
  45. sock_diag_save_cookie(sk, rep->vdiag_cookie);
  46. return 0;
  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. req = nlmsg_data(cb->nlh);
  58. net = sock_net(skb->sk);
  59. /* State saved between calls: */
  60. table = cb->args[0];
  61. bucket = cb->args[1];
  62. i = last_i = cb->args[2];
  63. /* TODO VMCI pending sockets? */
  64. spin_lock_bh(&vsock_table_lock);
  65. /* Bind table (locally created sockets) */
  66. if (table == 0) {
  67. while (bucket < ARRAY_SIZE(vsock_bind_table)) {
  68. struct list_head *head = &vsock_bind_table[bucket];
  69. i = 0;
  70. list_for_each_entry(vsk, head, bound_table) {
  71. struct sock *sk = sk_vsock(vsk);
  72. if (!net_eq(sock_net(sk), net))
  73. continue;
  74. if (i < last_i)
  75. goto next_bind;
  76. if (!(req->vdiag_states & (1 << sk->sk_state)))
  77. goto next_bind;
  78. if (sk_diag_fill(sk, skb,
  79. NETLINK_CB(cb->skb).portid,
  80. cb->nlh->nlmsg_seq,
  81. NLM_F_MULTI) < 0)
  82. goto done;
  83. next_bind:
  84. i++;
  85. }
  86. last_i = 0;
  87. bucket++;
  88. }
  89. table++;
  90. bucket = 0;
  91. }
  92. /* Connected table (accepted connections) */
  93. while (bucket < ARRAY_SIZE(vsock_connected_table)) {
  94. struct list_head *head = &vsock_connected_table[bucket];
  95. i = 0;
  96. list_for_each_entry(vsk, head, connected_table) {
  97. struct sock *sk = sk_vsock(vsk);
  98. /* Skip sockets we've already seen above */
  99. if (__vsock_in_bound_table(vsk))
  100. continue;
  101. if (!net_eq(sock_net(sk), net))
  102. continue;
  103. if (i < last_i)
  104. goto next_connected;
  105. if (!(req->vdiag_states & (1 << sk->sk_state)))
  106. goto next_connected;
  107. if (sk_diag_fill(sk, skb,
  108. NETLINK_CB(cb->skb).portid,
  109. cb->nlh->nlmsg_seq,
  110. NLM_F_MULTI) < 0)
  111. goto done;
  112. next_connected:
  113. i++;
  114. }
  115. last_i = 0;
  116. bucket++;
  117. }
  118. done:
  119. spin_unlock_bh(&vsock_table_lock);
  120. cb->args[0] = table;
  121. cb->args[1] = bucket;
  122. cb->args[2] = i;
  123. return skb->len;
  124. }
  125. static int vsock_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
  126. {
  127. int hdrlen = sizeof(struct vsock_diag_req);
  128. struct net *net = sock_net(skb->sk);
  129. if (nlmsg_len(h) < hdrlen)
  130. return -EINVAL;
  131. if (h->nlmsg_flags & NLM_F_DUMP) {
  132. struct netlink_dump_control c = {
  133. .dump = vsock_diag_dump,
  134. };
  135. return netlink_dump_start(net->diag_nlsk, skb, h, &c);
  136. }
  137. return -EOPNOTSUPP;
  138. }
  139. static const struct sock_diag_handler vsock_diag_handler = {
  140. .family = AF_VSOCK,
  141. .dump = vsock_diag_handler_dump,
  142. };
  143. static int __init vsock_diag_init(void)
  144. {
  145. return sock_diag_register(&vsock_diag_handler);
  146. }
  147. static void __exit vsock_diag_exit(void)
  148. {
  149. sock_diag_unregister(&vsock_diag_handler);
  150. }
  151. module_init(vsock_diag_init);
  152. module_exit(vsock_diag_exit);
  153. MODULE_LICENSE("GPL");
  154. MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG,
  155. 40 /* AF_VSOCK */);