Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* MPTCP socket monitoring support
0003  *
0004  * Copyright (c) 2019 Red Hat
0005  *
0006  * Author: Davide Caratti <dcaratti@redhat.com>
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) + /* INET_ULP_INFO_MPTCP */
0086         nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_TOKEN_REM */
0087         nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_TOKEN_LOC */
0088         nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ */
0089         nla_total_size_64bit(8) +   /* MPTCP_SUBFLOW_ATTR_MAP_SEQ */
0090         nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_MAP_SFSEQ */
0091         nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */
0092         nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_MAP_DATALEN */
0093         nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_FLAGS */
0094         nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_REM */
0095         nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_LOC */
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 }