tcp_diag.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * tcp_diag.c Module for monitoring TCP transport protocols sockets.
  4. *
  5. * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  6. */
  7. #include <linux/module.h>
  8. #include <linux/net.h>
  9. #include <linux/sock_diag.h>
  10. #include <linux/inet_diag.h>
  11. #include <linux/tcp.h>
  12. #include <net/netlink.h>
  13. #include <net/tcp.h>
  14. static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
  15. void *_info)
  16. {
  17. struct tcp_info *info = _info;
  18. if (inet_sk_state_load(sk) == TCP_LISTEN) {
  19. r->idiag_rqueue = READ_ONCE(sk->sk_ack_backlog);
  20. r->idiag_wqueue = READ_ONCE(sk->sk_max_ack_backlog);
  21. } else if (sk->sk_type == SOCK_STREAM) {
  22. const struct tcp_sock *tp = tcp_sk(sk);
  23. r->idiag_rqueue = max_t(int, READ_ONCE(tp->rcv_nxt) -
  24. READ_ONCE(tp->copied_seq), 0);
  25. r->idiag_wqueue = READ_ONCE(tp->write_seq) - tp->snd_una;
  26. }
  27. if (info)
  28. tcp_get_info(sk, info);
  29. }
  30. #ifdef CONFIG_TCP_MD5SIG
  31. static void tcp_diag_md5sig_fill(struct tcp_diag_md5sig *info,
  32. const struct tcp_md5sig_key *key)
  33. {
  34. info->tcpm_family = key->family;
  35. info->tcpm_prefixlen = key->prefixlen;
  36. info->tcpm_keylen = key->keylen;
  37. memcpy(info->tcpm_key, key->key, key->keylen);
  38. if (key->family == AF_INET)
  39. info->tcpm_addr[0] = key->addr.a4.s_addr;
  40. #if IS_ENABLED(CONFIG_IPV6)
  41. else if (key->family == AF_INET6)
  42. memcpy(&info->tcpm_addr, &key->addr.a6,
  43. sizeof(info->tcpm_addr));
  44. #endif
  45. }
  46. static int tcp_diag_put_md5sig(struct sk_buff *skb,
  47. const struct tcp_md5sig_info *md5sig)
  48. {
  49. const struct tcp_md5sig_key *key;
  50. struct tcp_diag_md5sig *info;
  51. struct nlattr *attr;
  52. int md5sig_count = 0;
  53. hlist_for_each_entry_rcu(key, &md5sig->head, node)
  54. md5sig_count++;
  55. if (md5sig_count == 0)
  56. return 0;
  57. attr = nla_reserve(skb, INET_DIAG_MD5SIG,
  58. md5sig_count * sizeof(struct tcp_diag_md5sig));
  59. if (!attr)
  60. return -EMSGSIZE;
  61. info = nla_data(attr);
  62. memset(info, 0, md5sig_count * sizeof(struct tcp_diag_md5sig));
  63. hlist_for_each_entry_rcu(key, &md5sig->head, node) {
  64. tcp_diag_md5sig_fill(info++, key);
  65. if (--md5sig_count == 0)
  66. break;
  67. }
  68. return 0;
  69. }
  70. #endif
  71. static int tcp_diag_put_ulp(struct sk_buff *skb, struct sock *sk,
  72. const struct tcp_ulp_ops *ulp_ops)
  73. {
  74. struct nlattr *nest;
  75. int err;
  76. nest = nla_nest_start_noflag(skb, INET_DIAG_ULP_INFO);
  77. if (!nest)
  78. return -EMSGSIZE;
  79. err = nla_put_string(skb, INET_ULP_INFO_NAME, ulp_ops->name);
  80. if (err)
  81. goto nla_failure;
  82. if (ulp_ops->get_info)
  83. err = ulp_ops->get_info(sk, skb);
  84. if (err)
  85. goto nla_failure;
  86. nla_nest_end(skb, nest);
  87. return 0;
  88. nla_failure:
  89. nla_nest_cancel(skb, nest);
  90. return err;
  91. }
  92. static int tcp_diag_get_aux(struct sock *sk, bool net_admin,
  93. struct sk_buff *skb)
  94. {
  95. struct inet_connection_sock *icsk = inet_csk(sk);
  96. int err = 0;
  97. #ifdef CONFIG_TCP_MD5SIG
  98. if (net_admin) {
  99. struct tcp_md5sig_info *md5sig;
  100. rcu_read_lock();
  101. md5sig = rcu_dereference(tcp_sk(sk)->md5sig_info);
  102. if (md5sig)
  103. err = tcp_diag_put_md5sig(skb, md5sig);
  104. rcu_read_unlock();
  105. if (err < 0)
  106. return err;
  107. }
  108. #endif
  109. if (net_admin) {
  110. const struct tcp_ulp_ops *ulp_ops;
  111. ulp_ops = icsk->icsk_ulp_ops;
  112. if (ulp_ops)
  113. err = tcp_diag_put_ulp(skb, sk, ulp_ops);
  114. if (err)
  115. return err;
  116. }
  117. return 0;
  118. }
  119. static size_t tcp_diag_get_aux_size(struct sock *sk, bool net_admin)
  120. {
  121. struct inet_connection_sock *icsk = inet_csk(sk);
  122. size_t size = 0;
  123. #ifdef CONFIG_TCP_MD5SIG
  124. if (net_admin && sk_fullsock(sk)) {
  125. const struct tcp_md5sig_info *md5sig;
  126. const struct tcp_md5sig_key *key;
  127. size_t md5sig_count = 0;
  128. rcu_read_lock();
  129. md5sig = rcu_dereference(tcp_sk(sk)->md5sig_info);
  130. if (md5sig) {
  131. hlist_for_each_entry_rcu(key, &md5sig->head, node)
  132. md5sig_count++;
  133. }
  134. rcu_read_unlock();
  135. size += nla_total_size(md5sig_count *
  136. sizeof(struct tcp_diag_md5sig));
  137. }
  138. #endif
  139. if (net_admin && sk_fullsock(sk)) {
  140. const struct tcp_ulp_ops *ulp_ops;
  141. ulp_ops = icsk->icsk_ulp_ops;
  142. if (ulp_ops) {
  143. size += nla_total_size(0) +
  144. nla_total_size(TCP_ULP_NAME_MAX);
  145. if (ulp_ops->get_info_size)
  146. size += ulp_ops->get_info_size(sk);
  147. }
  148. }
  149. return size;
  150. }
  151. static void tcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
  152. const struct inet_diag_req_v2 *r)
  153. {
  154. inet_diag_dump_icsk(&tcp_hashinfo, skb, cb, r);
  155. }
  156. static int tcp_diag_dump_one(struct netlink_callback *cb,
  157. const struct inet_diag_req_v2 *req)
  158. {
  159. return inet_diag_dump_one_icsk(&tcp_hashinfo, cb, req);
  160. }
  161. #ifdef CONFIG_INET_DIAG_DESTROY
  162. static int tcp_diag_destroy(struct sk_buff *in_skb,
  163. const struct inet_diag_req_v2 *req)
  164. {
  165. struct net *net = sock_net(in_skb->sk);
  166. struct sock *sk = inet_diag_find_one_icsk(net, &tcp_hashinfo, req);
  167. int err;
  168. if (IS_ERR(sk))
  169. return PTR_ERR(sk);
  170. err = sock_diag_destroy(sk, ECONNABORTED);
  171. sock_gen_put(sk);
  172. return err;
  173. }
  174. #endif
  175. static const struct inet_diag_handler tcp_diag_handler = {
  176. .dump = tcp_diag_dump,
  177. .dump_one = tcp_diag_dump_one,
  178. .idiag_get_info = tcp_diag_get_info,
  179. .idiag_get_aux = tcp_diag_get_aux,
  180. .idiag_get_aux_size = tcp_diag_get_aux_size,
  181. .idiag_type = IPPROTO_TCP,
  182. .idiag_info_size = sizeof(struct tcp_info),
  183. #ifdef CONFIG_INET_DIAG_DESTROY
  184. .destroy = tcp_diag_destroy,
  185. #endif
  186. };
  187. static int __init tcp_diag_init(void)
  188. {
  189. return inet_diag_register(&tcp_diag_handler);
  190. }
  191. static void __exit tcp_diag_exit(void)
  192. {
  193. inet_diag_unregister(&tcp_diag_handler);
  194. }
  195. module_init(tcp_diag_init);
  196. module_exit(tcp_diag_exit);
  197. MODULE_LICENSE("GPL");
  198. MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-6 /* AF_INET - IPPROTO_TCP */);