diag.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include <linux/module.h>
  2. #include <net/sock.h>
  3. #include <linux/netlink.h>
  4. #include <linux/sock_diag.h>
  5. #include <linux/netlink_diag.h>
  6. #include <linux/rhashtable.h>
  7. #include "af_netlink.h"
  8. static int sk_diag_dump_groups(struct sock *sk, struct sk_buff *nlskb)
  9. {
  10. struct netlink_sock *nlk = nlk_sk(sk);
  11. if (nlk->groups == NULL)
  12. return 0;
  13. return nla_put(nlskb, NETLINK_DIAG_GROUPS, NLGRPSZ(nlk->ngroups),
  14. nlk->groups);
  15. }
  16. static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
  17. struct netlink_diag_req *req,
  18. u32 portid, u32 seq, u32 flags, int sk_ino)
  19. {
  20. struct nlmsghdr *nlh;
  21. struct netlink_diag_msg *rep;
  22. struct netlink_sock *nlk = nlk_sk(sk);
  23. nlh = nlmsg_put(skb, portid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep),
  24. flags);
  25. if (!nlh)
  26. return -EMSGSIZE;
  27. rep = nlmsg_data(nlh);
  28. rep->ndiag_family = AF_NETLINK;
  29. rep->ndiag_type = sk->sk_type;
  30. rep->ndiag_protocol = sk->sk_protocol;
  31. rep->ndiag_state = sk->sk_state;
  32. rep->ndiag_ino = sk_ino;
  33. rep->ndiag_portid = nlk->portid;
  34. rep->ndiag_dst_portid = nlk->dst_portid;
  35. rep->ndiag_dst_group = nlk->dst_group;
  36. sock_diag_save_cookie(sk, rep->ndiag_cookie);
  37. if ((req->ndiag_show & NDIAG_SHOW_GROUPS) &&
  38. sk_diag_dump_groups(sk, skb))
  39. goto out_nlmsg_trim;
  40. if ((req->ndiag_show & NDIAG_SHOW_MEMINFO) &&
  41. sock_diag_put_meminfo(sk, skb, NETLINK_DIAG_MEMINFO))
  42. goto out_nlmsg_trim;
  43. nlmsg_end(skb, nlh);
  44. return 0;
  45. out_nlmsg_trim:
  46. nlmsg_cancel(skb, nlh);
  47. return -EMSGSIZE;
  48. }
  49. static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
  50. int protocol, int s_num)
  51. {
  52. struct netlink_table *tbl = &nl_table[protocol];
  53. struct rhashtable *ht = &tbl->hash;
  54. const struct bucket_table *htbl = rht_dereference_rcu(ht->tbl, ht);
  55. struct net *net = sock_net(skb->sk);
  56. struct netlink_diag_req *req;
  57. struct netlink_sock *nlsk;
  58. struct sock *sk;
  59. int ret = 0, num = 0, i;
  60. req = nlmsg_data(cb->nlh);
  61. for (i = 0; i < htbl->size; i++) {
  62. struct rhash_head *pos;
  63. rht_for_each_entry_rcu(nlsk, pos, htbl, i, node) {
  64. sk = (struct sock *)nlsk;
  65. if (!net_eq(sock_net(sk), net))
  66. continue;
  67. if (num < s_num) {
  68. num++;
  69. continue;
  70. }
  71. if (sk_diag_fill(sk, skb, req,
  72. NETLINK_CB(cb->skb).portid,
  73. cb->nlh->nlmsg_seq,
  74. NLM_F_MULTI,
  75. sock_i_ino(sk)) < 0) {
  76. ret = 1;
  77. goto done;
  78. }
  79. num++;
  80. }
  81. }
  82. sk_for_each_bound(sk, &tbl->mc_list) {
  83. if (sk_hashed(sk))
  84. continue;
  85. if (!net_eq(sock_net(sk), net))
  86. continue;
  87. if (num < s_num) {
  88. num++;
  89. continue;
  90. }
  91. if (sk_diag_fill(sk, skb, req,
  92. NETLINK_CB(cb->skb).portid,
  93. cb->nlh->nlmsg_seq,
  94. NLM_F_MULTI,
  95. sock_i_ino(sk)) < 0) {
  96. ret = 1;
  97. goto done;
  98. }
  99. num++;
  100. }
  101. done:
  102. cb->args[0] = num;
  103. cb->args[1] = protocol;
  104. return ret;
  105. }
  106. static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
  107. {
  108. struct netlink_diag_req *req;
  109. int s_num = cb->args[0];
  110. req = nlmsg_data(cb->nlh);
  111. rcu_read_lock();
  112. read_lock(&nl_table_lock);
  113. if (req->sdiag_protocol == NDIAG_PROTO_ALL) {
  114. int i;
  115. for (i = cb->args[1]; i < MAX_LINKS; i++) {
  116. if (__netlink_diag_dump(skb, cb, i, s_num))
  117. break;
  118. s_num = 0;
  119. }
  120. } else {
  121. if (req->sdiag_protocol >= MAX_LINKS) {
  122. read_unlock(&nl_table_lock);
  123. rcu_read_unlock();
  124. return -ENOENT;
  125. }
  126. __netlink_diag_dump(skb, cb, req->sdiag_protocol, s_num);
  127. }
  128. read_unlock(&nl_table_lock);
  129. rcu_read_unlock();
  130. return skb->len;
  131. }
  132. static int netlink_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
  133. {
  134. int hdrlen = sizeof(struct netlink_diag_req);
  135. struct net *net = sock_net(skb->sk);
  136. if (nlmsg_len(h) < hdrlen)
  137. return -EINVAL;
  138. if (h->nlmsg_flags & NLM_F_DUMP) {
  139. struct netlink_dump_control c = {
  140. .dump = netlink_diag_dump,
  141. };
  142. return netlink_dump_start(net->diag_nlsk, skb, h, &c);
  143. } else
  144. return -EOPNOTSUPP;
  145. }
  146. static const struct sock_diag_handler netlink_diag_handler = {
  147. .family = AF_NETLINK,
  148. .dump = netlink_diag_handler_dump,
  149. };
  150. static int __init netlink_diag_init(void)
  151. {
  152. return sock_diag_register(&netlink_diag_handler);
  153. }
  154. static void __exit netlink_diag_exit(void)
  155. {
  156. sock_diag_unregister(&netlink_diag_handler);
  157. }
  158. module_init(netlink_diag_init);
  159. module_exit(netlink_diag_exit);
  160. MODULE_LICENSE("GPL");
  161. MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 16 /* AF_NETLINK */);