diag.c 3.0 KB

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