0001
0002
0003
0004
0005
0006
0007 #ifdef CONFIG_SYSCTL
0008 #include <linux/sysctl.h>
0009 #endif
0010
0011 #include <net/net_namespace.h>
0012 #include <net/netns/generic.h>
0013
0014 #include "protocol.h"
0015
0016 #define MPTCP_SYSCTL_PATH "net/mptcp"
0017
0018 static int mptcp_pernet_id;
0019
0020 #ifdef CONFIG_SYSCTL
0021 static int mptcp_pm_type_max = __MPTCP_PM_TYPE_MAX;
0022 #endif
0023
0024 struct mptcp_pernet {
0025 #ifdef CONFIG_SYSCTL
0026 struct ctl_table_header *ctl_table_hdr;
0027 #endif
0028
0029 unsigned int add_addr_timeout;
0030 unsigned int stale_loss_cnt;
0031 u8 mptcp_enabled;
0032 u8 checksum_enabled;
0033 u8 allow_join_initial_addr_port;
0034 u8 pm_type;
0035 };
0036
0037 static struct mptcp_pernet *mptcp_get_pernet(const struct net *net)
0038 {
0039 return net_generic(net, mptcp_pernet_id);
0040 }
0041
0042 int mptcp_is_enabled(const struct net *net)
0043 {
0044 return mptcp_get_pernet(net)->mptcp_enabled;
0045 }
0046
0047 unsigned int mptcp_get_add_addr_timeout(const struct net *net)
0048 {
0049 return mptcp_get_pernet(net)->add_addr_timeout;
0050 }
0051
0052 int mptcp_is_checksum_enabled(const struct net *net)
0053 {
0054 return mptcp_get_pernet(net)->checksum_enabled;
0055 }
0056
0057 int mptcp_allow_join_id0(const struct net *net)
0058 {
0059 return mptcp_get_pernet(net)->allow_join_initial_addr_port;
0060 }
0061
0062 unsigned int mptcp_stale_loss_cnt(const struct net *net)
0063 {
0064 return mptcp_get_pernet(net)->stale_loss_cnt;
0065 }
0066
0067 int mptcp_get_pm_type(const struct net *net)
0068 {
0069 return mptcp_get_pernet(net)->pm_type;
0070 }
0071
0072 static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
0073 {
0074 pernet->mptcp_enabled = 1;
0075 pernet->add_addr_timeout = TCP_RTO_MAX;
0076 pernet->checksum_enabled = 0;
0077 pernet->allow_join_initial_addr_port = 1;
0078 pernet->stale_loss_cnt = 4;
0079 pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
0080 }
0081
0082 #ifdef CONFIG_SYSCTL
0083 static struct ctl_table mptcp_sysctl_table[] = {
0084 {
0085 .procname = "enabled",
0086 .maxlen = sizeof(u8),
0087 .mode = 0644,
0088
0089
0090
0091 .proc_handler = proc_dou8vec_minmax,
0092 .extra1 = SYSCTL_ZERO,
0093 .extra2 = SYSCTL_ONE
0094 },
0095 {
0096 .procname = "add_addr_timeout",
0097 .maxlen = sizeof(unsigned int),
0098 .mode = 0644,
0099 .proc_handler = proc_dointvec_jiffies,
0100 },
0101 {
0102 .procname = "checksum_enabled",
0103 .maxlen = sizeof(u8),
0104 .mode = 0644,
0105 .proc_handler = proc_dou8vec_minmax,
0106 .extra1 = SYSCTL_ZERO,
0107 .extra2 = SYSCTL_ONE
0108 },
0109 {
0110 .procname = "allow_join_initial_addr_port",
0111 .maxlen = sizeof(u8),
0112 .mode = 0644,
0113 .proc_handler = proc_dou8vec_minmax,
0114 .extra1 = SYSCTL_ZERO,
0115 .extra2 = SYSCTL_ONE
0116 },
0117 {
0118 .procname = "stale_loss_cnt",
0119 .maxlen = sizeof(unsigned int),
0120 .mode = 0644,
0121 .proc_handler = proc_douintvec_minmax,
0122 },
0123 {
0124 .procname = "pm_type",
0125 .maxlen = sizeof(u8),
0126 .mode = 0644,
0127 .proc_handler = proc_dou8vec_minmax,
0128 .extra1 = SYSCTL_ZERO,
0129 .extra2 = &mptcp_pm_type_max
0130 },
0131 {}
0132 };
0133
0134 static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
0135 {
0136 struct ctl_table_header *hdr;
0137 struct ctl_table *table;
0138
0139 table = mptcp_sysctl_table;
0140 if (!net_eq(net, &init_net)) {
0141 table = kmemdup(table, sizeof(mptcp_sysctl_table), GFP_KERNEL);
0142 if (!table)
0143 goto err_alloc;
0144 }
0145
0146 table[0].data = &pernet->mptcp_enabled;
0147 table[1].data = &pernet->add_addr_timeout;
0148 table[2].data = &pernet->checksum_enabled;
0149 table[3].data = &pernet->allow_join_initial_addr_port;
0150 table[4].data = &pernet->stale_loss_cnt;
0151 table[5].data = &pernet->pm_type;
0152
0153 hdr = register_net_sysctl(net, MPTCP_SYSCTL_PATH, table);
0154 if (!hdr)
0155 goto err_reg;
0156
0157 pernet->ctl_table_hdr = hdr;
0158
0159 return 0;
0160
0161 err_reg:
0162 if (!net_eq(net, &init_net))
0163 kfree(table);
0164 err_alloc:
0165 return -ENOMEM;
0166 }
0167
0168 static void mptcp_pernet_del_table(struct mptcp_pernet *pernet)
0169 {
0170 struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg;
0171
0172 unregister_net_sysctl_table(pernet->ctl_table_hdr);
0173
0174 kfree(table);
0175 }
0176
0177 #else
0178
0179 static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
0180 {
0181 return 0;
0182 }
0183
0184 static void mptcp_pernet_del_table(struct mptcp_pernet *pernet) {}
0185
0186 #endif
0187
0188 static int __net_init mptcp_net_init(struct net *net)
0189 {
0190 struct mptcp_pernet *pernet = mptcp_get_pernet(net);
0191
0192 mptcp_pernet_set_defaults(pernet);
0193
0194 return mptcp_pernet_new_table(net, pernet);
0195 }
0196
0197
0198 static void __net_exit mptcp_net_exit(struct net *net)
0199 {
0200 struct mptcp_pernet *pernet = mptcp_get_pernet(net);
0201
0202 mptcp_pernet_del_table(pernet);
0203 }
0204
0205 static struct pernet_operations mptcp_pernet_ops = {
0206 .init = mptcp_net_init,
0207 .exit = mptcp_net_exit,
0208 .id = &mptcp_pernet_id,
0209 .size = sizeof(struct mptcp_pernet),
0210 };
0211
0212 void __init mptcp_init(void)
0213 {
0214 mptcp_join_cookie_init();
0215 mptcp_proto_init();
0216
0217 if (register_pernet_subsys(&mptcp_pernet_ops) < 0)
0218 panic("Failed to register MPTCP pernet subsystem.\n");
0219 }
0220
0221 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
0222 int __init mptcpv6_init(void)
0223 {
0224 int err;
0225
0226 err = mptcp_proto_v6_init();
0227
0228 return err;
0229 }
0230 #endif