0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/net.h>
0011 #include <linux/inet_diag.h>
0012 #include <net/netlink.h>
0013 #include <uapi/linux/mptcp.h>
0014 #include "protocol.h"
0015
0016 static int subflow_get_info(const struct sock *sk, struct sk_buff *skb)
0017 {
0018 struct mptcp_subflow_context *sf;
0019 struct nlattr *start;
0020 u32 flags = 0;
0021 int err;
0022
0023 start = nla_nest_start_noflag(skb, INET_ULP_INFO_MPTCP);
0024 if (!start)
0025 return -EMSGSIZE;
0026
0027 rcu_read_lock();
0028 sf = rcu_dereference(inet_csk(sk)->icsk_ulp_data);
0029 if (!sf) {
0030 err = 0;
0031 goto nla_failure;
0032 }
0033
0034 if (sf->mp_capable)
0035 flags |= MPTCP_SUBFLOW_FLAG_MCAP_REM;
0036 if (sf->request_mptcp)
0037 flags |= MPTCP_SUBFLOW_FLAG_MCAP_LOC;
0038 if (sf->mp_join)
0039 flags |= MPTCP_SUBFLOW_FLAG_JOIN_REM;
0040 if (sf->request_join)
0041 flags |= MPTCP_SUBFLOW_FLAG_JOIN_LOC;
0042 if (sf->backup)
0043 flags |= MPTCP_SUBFLOW_FLAG_BKUP_REM;
0044 if (sf->request_bkup)
0045 flags |= MPTCP_SUBFLOW_FLAG_BKUP_LOC;
0046 if (sf->fully_established)
0047 flags |= MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED;
0048 if (sf->conn_finished)
0049 flags |= MPTCP_SUBFLOW_FLAG_CONNECTED;
0050 if (sf->map_valid)
0051 flags |= MPTCP_SUBFLOW_FLAG_MAPVALID;
0052
0053 if (nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_TOKEN_REM, sf->remote_token) ||
0054 nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_TOKEN_LOC, sf->token) ||
0055 nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ,
0056 sf->rel_write_seq) ||
0057 nla_put_u64_64bit(skb, MPTCP_SUBFLOW_ATTR_MAP_SEQ, sf->map_seq,
0058 MPTCP_SUBFLOW_ATTR_PAD) ||
0059 nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_MAP_SFSEQ,
0060 sf->map_subflow_seq) ||
0061 nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_SSN_OFFSET, sf->ssn_offset) ||
0062 nla_put_u16(skb, MPTCP_SUBFLOW_ATTR_MAP_DATALEN,
0063 sf->map_data_len) ||
0064 nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_FLAGS, flags) ||
0065 nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_REM, sf->remote_id) ||
0066 nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_LOC, sf->local_id)) {
0067 err = -EMSGSIZE;
0068 goto nla_failure;
0069 }
0070
0071 rcu_read_unlock();
0072 nla_nest_end(skb, start);
0073 return 0;
0074
0075 nla_failure:
0076 rcu_read_unlock();
0077 nla_nest_cancel(skb, start);
0078 return err;
0079 }
0080
0081 static size_t subflow_get_info_size(const struct sock *sk)
0082 {
0083 size_t size = 0;
0084
0085 size += nla_total_size(0) +
0086 nla_total_size(4) +
0087 nla_total_size(4) +
0088 nla_total_size(4) +
0089 nla_total_size_64bit(8) +
0090 nla_total_size(4) +
0091 nla_total_size(2) +
0092 nla_total_size(2) +
0093 nla_total_size(4) +
0094 nla_total_size(1) +
0095 nla_total_size(1) +
0096 0;
0097 return size;
0098 }
0099
0100 void mptcp_diag_subflow_init(struct tcp_ulp_ops *ops)
0101 {
0102 ops->get_info = subflow_get_info;
0103 ops->get_info_size = subflow_get_info_size;
0104 }