1 // SPDX-License-Identifier: GPL-2.0 2 /* Multipath TCP 3 * 4 * Copyright (c) 2019, Tessares SA. 5 */ 6 7 #ifdef CONFIG_SYSCTL 8 #include <linux/sysctl.h> 9 #endif 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 { 20 #ifdef CONFIG_SYSCTL 21 struct ctl_table_header *ctl_table_hdr; 22 #endif 23 24 u8 mptcp_enabled; 25 unsigned int add_addr_timeout; 26 u8 checksum_enabled; 27 }; 28 29 static struct mptcp_pernet *mptcp_get_pernet(struct net *net) 30 { 31 return net_generic(net, mptcp_pernet_id); 32 } 33 34 int mptcp_is_enabled(struct net *net) 35 { 36 return mptcp_get_pernet(net)->mptcp_enabled; 37 } 38 39 unsigned int mptcp_get_add_addr_timeout(struct net *net) 40 { 41 return mptcp_get_pernet(net)->add_addr_timeout; 42 } 43 44 int mptcp_is_checksum_enabled(struct net *net) 45 { 46 return mptcp_get_pernet(net)->checksum_enabled; 47 } 48 49 static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet) 50 { 51 pernet->mptcp_enabled = 1; 52 pernet->add_addr_timeout = TCP_RTO_MAX; 53 pernet->checksum_enabled = 0; 54 } 55 56 #ifdef CONFIG_SYSCTL 57 static struct ctl_table mptcp_sysctl_table[] = { 58 { 59 .procname = "enabled", 60 .maxlen = sizeof(u8), 61 .mode = 0644, 62 /* users with CAP_NET_ADMIN or root (not and) can change this 63 * value, same as other sysctl or the 'net' tree. 64 */ 65 .proc_handler = proc_dou8vec_minmax, 66 .extra1 = SYSCTL_ZERO, 67 .extra2 = SYSCTL_ONE 68 }, 69 { 70 .procname = "add_addr_timeout", 71 .maxlen = sizeof(unsigned int), 72 .mode = 0644, 73 .proc_handler = proc_dointvec_jiffies, 74 }, 75 { 76 .procname = "checksum_enabled", 77 .maxlen = sizeof(u8), 78 .mode = 0644, 79 .proc_handler = proc_dou8vec_minmax, 80 .extra1 = SYSCTL_ZERO, 81 .extra2 = SYSCTL_ONE 82 }, 83 {} 84 }; 85 86 static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet) 87 { 88 struct ctl_table_header *hdr; 89 struct ctl_table *table; 90 91 table = mptcp_sysctl_table; 92 if (!net_eq(net, &init_net)) { 93 table = kmemdup(table, sizeof(mptcp_sysctl_table), GFP_KERNEL); 94 if (!table) 95 goto err_alloc; 96 } 97 98 table[0].data = &pernet->mptcp_enabled; 99 table[1].data = &pernet->add_addr_timeout; 100 table[2].data = &pernet->checksum_enabled; 101 102 hdr = register_net_sysctl(net, MPTCP_SYSCTL_PATH, table); 103 if (!hdr) 104 goto err_reg; 105 106 pernet->ctl_table_hdr = hdr; 107 108 return 0; 109 110 err_reg: 111 if (!net_eq(net, &init_net)) 112 kfree(table); 113 err_alloc: 114 return -ENOMEM; 115 } 116 117 static void mptcp_pernet_del_table(struct mptcp_pernet *pernet) 118 { 119 struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg; 120 121 unregister_net_sysctl_table(pernet->ctl_table_hdr); 122 123 kfree(table); 124 } 125 126 #else 127 128 static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet) 129 { 130 return 0; 131 } 132 133 static void mptcp_pernet_del_table(struct mptcp_pernet *pernet) {} 134 135 #endif /* CONFIG_SYSCTL */ 136 137 static int __net_init mptcp_net_init(struct net *net) 138 { 139 struct mptcp_pernet *pernet = mptcp_get_pernet(net); 140 141 mptcp_pernet_set_defaults(pernet); 142 143 return mptcp_pernet_new_table(net, pernet); 144 } 145 146 /* Note: the callback will only be called per extra netns */ 147 static void __net_exit mptcp_net_exit(struct net *net) 148 { 149 struct mptcp_pernet *pernet = mptcp_get_pernet(net); 150 151 mptcp_pernet_del_table(pernet); 152 } 153 154 static struct pernet_operations mptcp_pernet_ops = { 155 .init = mptcp_net_init, 156 .exit = mptcp_net_exit, 157 .id = &mptcp_pernet_id, 158 .size = sizeof(struct mptcp_pernet), 159 }; 160 161 void __init mptcp_init(void) 162 { 163 mptcp_join_cookie_init(); 164 mptcp_proto_init(); 165 166 if (register_pernet_subsys(&mptcp_pernet_ops) < 0) 167 panic("Failed to register MPTCP pernet subsystem.\n"); 168 } 169 170 #if IS_ENABLED(CONFIG_MPTCP_IPV6) 171 int __init mptcpv6_init(void) 172 { 173 int err; 174 175 err = mptcp_proto_v6_init(); 176 177 return err; 178 } 179 #endif 180