diag.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #include <linux/types.h>
  2. #include <linux/spinlock.h>
  3. #include <linux/sock_diag.h>
  4. #include <linux/unix_diag.h>
  5. #include <linux/skbuff.h>
  6. #include <net/netlink.h>
  7. #include <net/af_unix.h>
  8. #include <net/tcp_states.h>
  9. #define UNIX_DIAG_PUT(skb, attrtype, attrlen) \
  10. RTA_DATA(__RTA_PUT(skb, attrtype, attrlen))
  11. static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req,
  12. u32 pid, u32 seq, u32 flags, int sk_ino)
  13. {
  14. unsigned char *b = skb_tail_pointer(skb);
  15. struct nlmsghdr *nlh;
  16. struct unix_diag_msg *rep;
  17. nlh = NLMSG_PUT(skb, pid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep));
  18. nlh->nlmsg_flags = flags;
  19. rep = NLMSG_DATA(nlh);
  20. rep->udiag_family = AF_UNIX;
  21. rep->udiag_type = sk->sk_type;
  22. rep->udiag_state = sk->sk_state;
  23. rep->udiag_ino = sk_ino;
  24. sock_diag_save_cookie(sk, rep->udiag_cookie);
  25. nlh->nlmsg_len = skb_tail_pointer(skb) - b;
  26. return skb->len;
  27. nlmsg_failure:
  28. nlmsg_trim(skb, b);
  29. return -EMSGSIZE;
  30. }
  31. static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req,
  32. u32 pid, u32 seq, u32 flags)
  33. {
  34. int sk_ino;
  35. unix_state_lock(sk);
  36. sk_ino = sock_i_ino(sk);
  37. unix_state_unlock(sk);
  38. if (!sk_ino)
  39. return 0;
  40. return sk_diag_fill(sk, skb, req, pid, seq, flags, sk_ino);
  41. }
  42. static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
  43. {
  44. struct unix_diag_req *req;
  45. int num, s_num, slot, s_slot;
  46. req = NLMSG_DATA(cb->nlh);
  47. s_slot = cb->args[0];
  48. num = s_num = cb->args[1];
  49. spin_lock(&unix_table_lock);
  50. for (slot = s_slot; slot <= UNIX_HASH_SIZE; s_num = 0, slot++) {
  51. struct sock *sk;
  52. struct hlist_node *node;
  53. num = 0;
  54. sk_for_each(sk, node, &unix_socket_table[slot]) {
  55. if (num < s_num)
  56. goto next;
  57. if (!(req->udiag_states & (1 << sk->sk_state)))
  58. goto next;
  59. if (sk_diag_dump(sk, skb, req,
  60. NETLINK_CB(cb->skb).pid,
  61. cb->nlh->nlmsg_seq,
  62. NLM_F_MULTI) < 0)
  63. goto done;
  64. next:
  65. num++;
  66. }
  67. }
  68. done:
  69. spin_unlock(&unix_table_lock);
  70. cb->args[0] = slot;
  71. cb->args[1] = num;
  72. return skb->len;
  73. }
  74. static int unix_diag_get_exact(struct sk_buff *in_skb,
  75. const struct nlmsghdr *nlh,
  76. struct unix_diag_req *req)
  77. {
  78. return -EAFNOSUPPORT;
  79. }
  80. static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
  81. {
  82. int hdrlen = sizeof(struct unix_diag_req);
  83. if (nlmsg_len(h) < hdrlen)
  84. return -EINVAL;
  85. if (h->nlmsg_flags & NLM_F_DUMP)
  86. return netlink_dump_start(sock_diag_nlsk, skb, h,
  87. unix_diag_dump, NULL, 0);
  88. else
  89. return unix_diag_get_exact(skb, h, (struct unix_diag_req *)NLMSG_DATA(h));
  90. }
  91. static struct sock_diag_handler unix_diag_handler = {
  92. .family = AF_UNIX,
  93. .dump = unix_diag_handler_dump,
  94. };
  95. static int __init unix_diag_init(void)
  96. {
  97. return sock_diag_register(&unix_diag_handler);
  98. }
  99. static void __exit unix_diag_exit(void)
  100. {
  101. sock_diag_unregister(&unix_diag_handler);
  102. }
  103. module_init(unix_diag_init);
  104. module_exit(unix_diag_exit);
  105. MODULE_LICENSE("GPL");
  106. MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 1 /* AF_LOCAL */);