1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright (c) 2019, Tessares SA.
7 #include <linux/sysctl.h>
9 #include <net/net_namespace.h>
10 #include <net/netns/generic.h>
14 #define MPTCP_SYSCTL_PATH "net/mptcp"
16 static int mptcp_pernet_id
;
18 struct ctl_table_header
*ctl_table_hdr
;
21 unsigned int add_addr_timeout
;
24 static struct mptcp_pernet
*mptcp_get_pernet(struct net
*net
)
26 return net_generic(net
, mptcp_pernet_id
);
29 int mptcp_is_enabled(struct net
*net
)
31 return mptcp_get_pernet(net
)->mptcp_enabled
;
34 unsigned int mptcp_get_add_addr_timeout(struct net
*net
)
36 return mptcp_get_pernet(net
)->add_addr_timeout
;
39 static struct ctl_table mptcp_sysctl_table
[] = {
41 .procname
= "enabled",
42 .maxlen
= sizeof(int),
44 /* users with CAP_NET_ADMIN or root (not and) can change this
45 * value, same as other sysctl or the 'net' tree.
47 .proc_handler
= proc_dointvec
,
50 .procname
= "add_addr_timeout",
51 .maxlen
= sizeof(unsigned int),
53 .proc_handler
= proc_dointvec_jiffies
,
58 static void mptcp_pernet_set_defaults(struct mptcp_pernet
*pernet
)
60 pernet
->mptcp_enabled
= 1;
61 pernet
->add_addr_timeout
= TCP_RTO_MAX
;
64 static int mptcp_pernet_new_table(struct net
*net
, struct mptcp_pernet
*pernet
)
66 struct ctl_table_header
*hdr
;
67 struct ctl_table
*table
;
69 table
= mptcp_sysctl_table
;
70 if (!net_eq(net
, &init_net
)) {
71 table
= kmemdup(table
, sizeof(mptcp_sysctl_table
), GFP_KERNEL
);
76 table
[0].data
= &pernet
->mptcp_enabled
;
77 table
[1].data
= &pernet
->add_addr_timeout
;
79 hdr
= register_net_sysctl(net
, MPTCP_SYSCTL_PATH
, table
);
83 pernet
->ctl_table_hdr
= hdr
;
88 if (!net_eq(net
, &init_net
))
94 static void mptcp_pernet_del_table(struct mptcp_pernet
*pernet
)
96 struct ctl_table
*table
= pernet
->ctl_table_hdr
->ctl_table_arg
;
98 unregister_net_sysctl_table(pernet
->ctl_table_hdr
);
103 static int __net_init
mptcp_net_init(struct net
*net
)
105 struct mptcp_pernet
*pernet
= mptcp_get_pernet(net
);
107 mptcp_pernet_set_defaults(pernet
);
109 return mptcp_pernet_new_table(net
, pernet
);
112 /* Note: the callback will only be called per extra netns */
113 static void __net_exit
mptcp_net_exit(struct net
*net
)
115 struct mptcp_pernet
*pernet
= mptcp_get_pernet(net
);
117 mptcp_pernet_del_table(pernet
);
120 static struct pernet_operations mptcp_pernet_ops
= {
121 .init
= mptcp_net_init
,
122 .exit
= mptcp_net_exit
,
123 .id
= &mptcp_pernet_id
,
124 .size
= sizeof(struct mptcp_pernet
),
127 void __init
mptcp_init(void)
129 mptcp_join_cookie_init();
132 if (register_pernet_subsys(&mptcp_pernet_ops
) < 0)
133 panic("Failed to register MPTCP pernet subsystem.\n");
136 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
137 int __init
mptcpv6_init(void)
141 err
= mptcp_proto_v6_init();