Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* Multipath TCP |
| 3 | * |
| 4 | * Copyright (c) 2019, Tessares SA. |
| 5 | */ |
| 6 | |
Matthieu Baerts | 804c72e | 2021-05-27 16:54:29 -0700 | [diff] [blame] | 7 | #ifdef CONFIG_SYSCTL |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 8 | #include <linux/sysctl.h> |
Matthieu Baerts | 804c72e | 2021-05-27 16:54:29 -0700 | [diff] [blame] | 9 | #endif |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 10 | |
| 11 | #include <net/net_namespace.h> |
| 12 | #include <net/netns/generic.h> |
| 13 | |
| 14 | #include "protocol.h" |
| 15 | |
| 16 | #define MPTCP_SYSCTL_PATH "net/mptcp" |
| 17 | |
| 18 | static int mptcp_pernet_id; |
| 19 | struct mptcp_pernet { |
Matthieu Baerts | 804c72e | 2021-05-27 16:54:29 -0700 | [diff] [blame] | 20 | #ifdef CONFIG_SYSCTL |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 21 | struct ctl_table_header *ctl_table_hdr; |
Matthieu Baerts | 804c72e | 2021-05-27 16:54:29 -0700 | [diff] [blame] | 22 | #endif |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 23 | |
Geliang Tang | 93f323b | 2020-11-03 11:05:07 -0800 | [diff] [blame] | 24 | unsigned int add_addr_timeout; |
Paolo Abeni | ff5a0b4 | 2021-08-13 15:15:45 -0700 | [diff] [blame] | 25 | unsigned int stale_loss_cnt; |
Paolo Abeni | 6da14d7 | 2021-08-13 15:15:44 -0700 | [diff] [blame] | 26 | u8 mptcp_enabled; |
Geliang Tang | fc3c82e | 2021-06-17 16:46:19 -0700 | [diff] [blame] | 27 | u8 checksum_enabled; |
Geliang Tang | d2f7796 | 2021-06-22 12:25:18 -0700 | [diff] [blame] | 28 | u8 allow_join_initial_addr_port; |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 29 | }; |
| 30 | |
Paolo Abeni | 6da14d7 | 2021-08-13 15:15:44 -0700 | [diff] [blame] | 31 | static struct mptcp_pernet *mptcp_get_pernet(const struct net *net) |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 32 | { |
| 33 | return net_generic(net, mptcp_pernet_id); |
| 34 | } |
| 35 | |
Paolo Abeni | 6da14d7 | 2021-08-13 15:15:44 -0700 | [diff] [blame] | 36 | int mptcp_is_enabled(const struct net *net) |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 37 | { |
| 38 | return mptcp_get_pernet(net)->mptcp_enabled; |
| 39 | } |
| 40 | |
Paolo Abeni | 6da14d7 | 2021-08-13 15:15:44 -0700 | [diff] [blame] | 41 | unsigned int mptcp_get_add_addr_timeout(const struct net *net) |
Geliang Tang | 93f323b | 2020-11-03 11:05:07 -0800 | [diff] [blame] | 42 | { |
| 43 | return mptcp_get_pernet(net)->add_addr_timeout; |
| 44 | } |
| 45 | |
Paolo Abeni | 6da14d7 | 2021-08-13 15:15:44 -0700 | [diff] [blame] | 46 | int mptcp_is_checksum_enabled(const struct net *net) |
Geliang Tang | fc3c82e | 2021-06-17 16:46:19 -0700 | [diff] [blame] | 47 | { |
| 48 | return mptcp_get_pernet(net)->checksum_enabled; |
| 49 | } |
| 50 | |
Paolo Abeni | 6da14d7 | 2021-08-13 15:15:44 -0700 | [diff] [blame] | 51 | int mptcp_allow_join_id0(const struct net *net) |
Geliang Tang | d2f7796 | 2021-06-22 12:25:18 -0700 | [diff] [blame] | 52 | { |
| 53 | return mptcp_get_pernet(net)->allow_join_initial_addr_port; |
| 54 | } |
| 55 | |
Paolo Abeni | ff5a0b4 | 2021-08-13 15:15:45 -0700 | [diff] [blame] | 56 | unsigned int mptcp_stale_loss_cnt(const struct net *net) |
| 57 | { |
| 58 | return mptcp_get_pernet(net)->stale_loss_cnt; |
| 59 | } |
| 60 | |
Matthieu Baerts | 804c72e | 2021-05-27 16:54:29 -0700 | [diff] [blame] | 61 | static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet) |
| 62 | { |
| 63 | pernet->mptcp_enabled = 1; |
| 64 | pernet->add_addr_timeout = TCP_RTO_MAX; |
Geliang Tang | fc3c82e | 2021-06-17 16:46:19 -0700 | [diff] [blame] | 65 | pernet->checksum_enabled = 0; |
Geliang Tang | d2f7796 | 2021-06-22 12:25:18 -0700 | [diff] [blame] | 66 | pernet->allow_join_initial_addr_port = 1; |
Paolo Abeni | ff5a0b4 | 2021-08-13 15:15:45 -0700 | [diff] [blame] | 67 | pernet->stale_loss_cnt = 4; |
Matthieu Baerts | 804c72e | 2021-05-27 16:54:29 -0700 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | #ifdef CONFIG_SYSCTL |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 71 | static struct ctl_table mptcp_sysctl_table[] = { |
| 72 | { |
| 73 | .procname = "enabled", |
Matthieu Baerts | 744ee14 | 2021-05-27 16:54:30 -0700 | [diff] [blame] | 74 | .maxlen = sizeof(u8), |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 75 | .mode = 0644, |
| 76 | /* users with CAP_NET_ADMIN or root (not and) can change this |
| 77 | * value, same as other sysctl or the 'net' tree. |
| 78 | */ |
Matthieu Baerts | 744ee14 | 2021-05-27 16:54:30 -0700 | [diff] [blame] | 79 | .proc_handler = proc_dou8vec_minmax, |
| 80 | .extra1 = SYSCTL_ZERO, |
| 81 | .extra2 = SYSCTL_ONE |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 82 | }, |
Geliang Tang | 93f323b | 2020-11-03 11:05:07 -0800 | [diff] [blame] | 83 | { |
| 84 | .procname = "add_addr_timeout", |
| 85 | .maxlen = sizeof(unsigned int), |
| 86 | .mode = 0644, |
| 87 | .proc_handler = proc_dointvec_jiffies, |
| 88 | }, |
Geliang Tang | fc3c82e | 2021-06-17 16:46:19 -0700 | [diff] [blame] | 89 | { |
| 90 | .procname = "checksum_enabled", |
| 91 | .maxlen = sizeof(u8), |
| 92 | .mode = 0644, |
| 93 | .proc_handler = proc_dou8vec_minmax, |
| 94 | .extra1 = SYSCTL_ZERO, |
| 95 | .extra2 = SYSCTL_ONE |
| 96 | }, |
Geliang Tang | d2f7796 | 2021-06-22 12:25:18 -0700 | [diff] [blame] | 97 | { |
| 98 | .procname = "allow_join_initial_addr_port", |
| 99 | .maxlen = sizeof(u8), |
| 100 | .mode = 0644, |
| 101 | .proc_handler = proc_dou8vec_minmax, |
| 102 | .extra1 = SYSCTL_ZERO, |
| 103 | .extra2 = SYSCTL_ONE |
| 104 | }, |
Paolo Abeni | ff5a0b4 | 2021-08-13 15:15:45 -0700 | [diff] [blame] | 105 | { |
| 106 | .procname = "stale_loss_cnt", |
| 107 | .maxlen = sizeof(unsigned int), |
| 108 | .mode = 0644, |
| 109 | .proc_handler = proc_douintvec_minmax, |
| 110 | }, |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 111 | {} |
| 112 | }; |
| 113 | |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 114 | static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet) |
| 115 | { |
| 116 | struct ctl_table_header *hdr; |
| 117 | struct ctl_table *table; |
| 118 | |
| 119 | table = mptcp_sysctl_table; |
| 120 | if (!net_eq(net, &init_net)) { |
| 121 | table = kmemdup(table, sizeof(mptcp_sysctl_table), GFP_KERNEL); |
| 122 | if (!table) |
| 123 | goto err_alloc; |
| 124 | } |
| 125 | |
| 126 | table[0].data = &pernet->mptcp_enabled; |
Geliang Tang | 93f323b | 2020-11-03 11:05:07 -0800 | [diff] [blame] | 127 | table[1].data = &pernet->add_addr_timeout; |
Geliang Tang | fc3c82e | 2021-06-17 16:46:19 -0700 | [diff] [blame] | 128 | table[2].data = &pernet->checksum_enabled; |
Geliang Tang | d2f7796 | 2021-06-22 12:25:18 -0700 | [diff] [blame] | 129 | table[3].data = &pernet->allow_join_initial_addr_port; |
Paolo Abeni | ff5a0b4 | 2021-08-13 15:15:45 -0700 | [diff] [blame] | 130 | table[4].data = &pernet->stale_loss_cnt; |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 131 | |
| 132 | hdr = register_net_sysctl(net, MPTCP_SYSCTL_PATH, table); |
| 133 | if (!hdr) |
| 134 | goto err_reg; |
| 135 | |
| 136 | pernet->ctl_table_hdr = hdr; |
| 137 | |
| 138 | return 0; |
| 139 | |
| 140 | err_reg: |
| 141 | if (!net_eq(net, &init_net)) |
| 142 | kfree(table); |
| 143 | err_alloc: |
| 144 | return -ENOMEM; |
| 145 | } |
| 146 | |
| 147 | static void mptcp_pernet_del_table(struct mptcp_pernet *pernet) |
| 148 | { |
| 149 | struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg; |
| 150 | |
| 151 | unregister_net_sysctl_table(pernet->ctl_table_hdr); |
| 152 | |
| 153 | kfree(table); |
| 154 | } |
| 155 | |
Matthieu Baerts | 804c72e | 2021-05-27 16:54:29 -0700 | [diff] [blame] | 156 | #else |
| 157 | |
| 158 | static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet) |
| 159 | { |
| 160 | return 0; |
| 161 | } |
| 162 | |
| 163 | static void mptcp_pernet_del_table(struct mptcp_pernet *pernet) {} |
| 164 | |
| 165 | #endif /* CONFIG_SYSCTL */ |
| 166 | |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 167 | static int __net_init mptcp_net_init(struct net *net) |
| 168 | { |
| 169 | struct mptcp_pernet *pernet = mptcp_get_pernet(net); |
| 170 | |
| 171 | mptcp_pernet_set_defaults(pernet); |
| 172 | |
| 173 | return mptcp_pernet_new_table(net, pernet); |
| 174 | } |
| 175 | |
| 176 | /* Note: the callback will only be called per extra netns */ |
| 177 | static void __net_exit mptcp_net_exit(struct net *net) |
| 178 | { |
| 179 | struct mptcp_pernet *pernet = mptcp_get_pernet(net); |
| 180 | |
| 181 | mptcp_pernet_del_table(pernet); |
| 182 | } |
| 183 | |
| 184 | static struct pernet_operations mptcp_pernet_ops = { |
| 185 | .init = mptcp_net_init, |
| 186 | .exit = mptcp_net_exit, |
| 187 | .id = &mptcp_pernet_id, |
| 188 | .size = sizeof(struct mptcp_pernet), |
| 189 | }; |
| 190 | |
| 191 | void __init mptcp_init(void) |
| 192 | { |
Florian Westphal | 9466a1c | 2020-07-30 21:25:56 +0200 | [diff] [blame] | 193 | mptcp_join_cookie_init(); |
Matthieu Baerts | 784325e | 2020-01-21 16:56:28 -0800 | [diff] [blame] | 194 | mptcp_proto_init(); |
| 195 | |
| 196 | if (register_pernet_subsys(&mptcp_pernet_ops) < 0) |
| 197 | panic("Failed to register MPTCP pernet subsystem.\n"); |
| 198 | } |
| 199 | |
| 200 | #if IS_ENABLED(CONFIG_MPTCP_IPV6) |
| 201 | int __init mptcpv6_init(void) |
| 202 | { |
| 203 | int err; |
| 204 | |
| 205 | err = mptcp_proto_v6_init(); |
| 206 | |
| 207 | return err; |
| 208 | } |
| 209 | #endif |