Skip to content

Commit

Permalink
mptcp: add MPTCP_INFO getsockopt
Browse files Browse the repository at this point in the history
Its not compatible with multipath-tcp.org kernel one.

1. The out-of-tree implementation defines a different 'struct mptcp_info',
   with embedded __user addresses for additional data such as
   endpoint addresses.

2. Mat Martineau points out that embedded __user addresses doesn't work
with BPF_CGROUP_RUN_PROG_GETSOCKOPT() which assumes that copying in
optsize bytes from optval provides all data that got copied to userspace.

This provides mptcp_info data for the given mptcp socket.

Userspace sets optlen to the size of the structure it expects.
The kernel updates it to contain the number of bytes that it copied.

This allows to append more information to the structure later.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Florian Westphal authored and David S. Miller committed Sep 18, 2021
1 parent 61bc6e8 commit 55c42fa
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/linux/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ struct ucred {
#define SOL_KCM 281
#define SOL_TLS 282
#define SOL_XDP 283
#define SOL_MPTCP 284

/* IPX options */
#define IPX_TYPE 1
Expand Down
3 changes: 3 additions & 0 deletions include/uapi/linux/mptcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,7 @@ enum mptcp_event_attr {
#define MPTCP_RST_EBADPERF 5
#define MPTCP_RST_EMIDDLEBOX 6

/* MPTCP socket options */
#define MPTCP_INFO 1

#endif /* _UAPI_MPTCP_H */
40 changes: 39 additions & 1 deletion net/mptcp/sockopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -673,10 +673,14 @@ static int mptcp_getsockopt_first_sf_only(struct mptcp_sock *msk, int level, int
void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info)
{
struct sock *sk = &msk->sk.icsk_inet.sk;
bool slow = lock_sock_fast(sk);
u32 flags = 0;
bool slow;
u8 val;

memset(info, 0, sizeof(*info));

slow = lock_sock_fast(sk);

info->mptcpi_subflows = READ_ONCE(msk->pm.subflows);
info->mptcpi_add_addr_signal = READ_ONCE(msk->pm.add_addr_signaled);
info->mptcpi_add_addr_accepted = READ_ONCE(msk->pm.add_addr_accepted);
Expand All @@ -702,6 +706,27 @@ void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info)
}
EXPORT_SYMBOL_GPL(mptcp_diag_fill_info);

static int mptcp_getsockopt_info(struct mptcp_sock *msk, char __user *optval, int __user *optlen)
{
struct mptcp_info m_info;
int len;

if (get_user(len, optlen))
return -EFAULT;

len = min_t(unsigned int, len, sizeof(struct mptcp_info));

mptcp_diag_fill_info(msk, &m_info);

if (put_user(len, optlen))
return -EFAULT;

if (copy_to_user(optval, &m_info, len))
return -EFAULT;

return 0;
}

static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
char __user *optval, int __user *optlen)
{
Expand All @@ -716,6 +741,17 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
return -EOPNOTSUPP;
}

static int mptcp_getsockopt_sol_mptcp(struct mptcp_sock *msk, int optname,
char __user *optval, int __user *optlen)
{
switch (optname) {
case MPTCP_INFO:
return mptcp_getsockopt_info(msk, optval, optlen);
}

return -EOPNOTSUPP;
}

int mptcp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *option)
{
Expand All @@ -738,6 +774,8 @@ int mptcp_getsockopt(struct sock *sk, int level, int optname,

if (level == SOL_TCP)
return mptcp_getsockopt_sol_tcp(msk, optname, optval, option);
if (level == SOL_MPTCP)
return mptcp_getsockopt_sol_mptcp(msk, optname, optval, option);
return -EOPNOTSUPP;
}

Expand Down

0 comments on commit 55c42fa

Please sign in to comment.