diag.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* MPTCP socket monitoring support
  3. *
  4. * Copyright (c) 2019 Red Hat
  5. *
  6. * Author: Davide Caratti <dcaratti@redhat.com>
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/net.h>
  10. #include <linux/inet_diag.h>
  11. #include <net/netlink.h>
  12. #include "protocol.h"
  13. static int subflow_get_info(struct sock *sk, struct sk_buff *skb)
  14. {
  15. struct mptcp_subflow_context *sf;
  16. struct nlattr *start;
  17. u32 flags = 0;
  18. bool slow;
  19. int err;
  20. if (inet_sk_state_load(sk) == TCP_LISTEN)
  21. return 0;
  22. start = nla_nest_start_noflag(skb, INET_ULP_INFO_MPTCP);
  23. if (!start)
  24. return -EMSGSIZE;
  25. slow = lock_sock_fast(sk);
  26. rcu_read_lock();
  27. sf = rcu_dereference(inet_csk(sk)->icsk_ulp_data);
  28. if (!sf) {
  29. err = 0;
  30. goto nla_failure;
  31. }
  32. if (sf->mp_capable)
  33. flags |= MPTCP_SUBFLOW_FLAG_MCAP_REM;
  34. if (sf->request_mptcp)
  35. flags |= MPTCP_SUBFLOW_FLAG_MCAP_LOC;
  36. if (sf->mp_join)
  37. flags |= MPTCP_SUBFLOW_FLAG_JOIN_REM;
  38. if (sf->request_join)
  39. flags |= MPTCP_SUBFLOW_FLAG_JOIN_LOC;
  40. if (sf->backup)
  41. flags |= MPTCP_SUBFLOW_FLAG_BKUP_REM;
  42. if (sf->request_bkup)
  43. flags |= MPTCP_SUBFLOW_FLAG_BKUP_LOC;
  44. if (READ_ONCE(sf->fully_established))
  45. flags |= MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED;
  46. if (sf->conn_finished)
  47. flags |= MPTCP_SUBFLOW_FLAG_CONNECTED;
  48. if (sf->map_valid)
  49. flags |= MPTCP_SUBFLOW_FLAG_MAPVALID;
  50. if (nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_TOKEN_REM, sf->remote_token) ||
  51. nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_TOKEN_LOC, sf->token) ||
  52. nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ,
  53. sf->rel_write_seq) ||
  54. nla_put_u64_64bit(skb, MPTCP_SUBFLOW_ATTR_MAP_SEQ, sf->map_seq,
  55. MPTCP_SUBFLOW_ATTR_PAD) ||
  56. nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_MAP_SFSEQ,
  57. sf->map_subflow_seq) ||
  58. nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_SSN_OFFSET, sf->ssn_offset) ||
  59. nla_put_u16(skb, MPTCP_SUBFLOW_ATTR_MAP_DATALEN,
  60. sf->map_data_len) ||
  61. nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_FLAGS, flags) ||
  62. nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_REM, sf->remote_id) ||
  63. nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_LOC, subflow_get_local_id(sf))) {
  64. err = -EMSGSIZE;
  65. goto nla_failure;
  66. }
  67. rcu_read_unlock();
  68. unlock_sock_fast(sk, slow);
  69. nla_nest_end(skb, start);
  70. return 0;
  71. nla_failure:
  72. rcu_read_unlock();
  73. unlock_sock_fast(sk, slow);
  74. nla_nest_cancel(skb, start);
  75. return err;
  76. }
  77. static size_t subflow_get_info_size(const struct sock *sk)
  78. {
  79. size_t size = 0;
  80. size += nla_total_size(0) + /* INET_ULP_INFO_MPTCP */
  81. nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_TOKEN_REM */
  82. nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_TOKEN_LOC */
  83. nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ */
  84. nla_total_size_64bit(8) + /* MPTCP_SUBFLOW_ATTR_MAP_SEQ */
  85. nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_MAP_SFSEQ */
  86. nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */
  87. nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_MAP_DATALEN */
  88. nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_FLAGS */
  89. nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_REM */
  90. nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_LOC */
  91. 0;
  92. return size;
  93. }
  94. void mptcp_diag_subflow_init(struct tcp_ulp_ops *ops)
  95. {
  96. ops->get_info = subflow_get_info;
  97. ops->get_info_size = subflow_get_info_size;
  98. }