1 /* SCTP kernel implementation 2 * (C) Copyright IBM Corp. 2002, 2004 3 * Copyright (c) 2002 Intel Corp. 4 * 5 * This file is part of the SCTP kernel implementation 6 * 7 * Sysctl related interfaces for SCTP. 8 * 9 * This SCTP implementation is free software; 10 * you can redistribute it and/or modify it under the terms of 11 * the GNU General Public License as published by 12 * the Free Software Foundation; either version 2, or (at your option) 13 * any later version. 14 * 15 * This SCTP implementation is distributed in the hope that it 16 * will be useful, but WITHOUT ANY WARRANTY; without even the implied 17 * ************************ 18 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 * See the GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with GNU CC; see the file COPYING. If not, see 23 * <http://www.gnu.org/licenses/>. 24 * 25 * Please send any bug reports or fixes you make to the 26 * email address(es): 27 * lksctp developers <linux-sctp@vger.kernel.org> 28 * 29 * Written or modified by: 30 * Mingqin Liu <liuming@us.ibm.com> 31 * Jon Grimm <jgrimm@us.ibm.com> 32 * Ardelle Fan <ardelle.fan@intel.com> 33 * Ryan Layer <rmlayer@us.ibm.com> 34 * Sridhar Samudrala <sri@us.ibm.com> 35 */ 36 37 #include <net/sctp/structs.h> 38 #include <net/sctp/sctp.h> 39 #include <linux/sysctl.h> 40 41 static int zero = 0; 42 static int one = 1; 43 static int timer_max = 86400000; /* ms in one day */ 44 static int int_max = INT_MAX; 45 static int sack_timer_min = 1; 46 static int sack_timer_max = 500; 47 static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */ 48 static int rwnd_scale_max = 16; 49 static unsigned long max_autoclose_min = 0; 50 static unsigned long max_autoclose_max = 51 (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX) 52 ? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ; 53 54 extern long sysctl_sctp_mem[3]; 55 extern int sysctl_sctp_rmem[3]; 56 extern int sysctl_sctp_wmem[3]; 57 58 static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, 59 void __user *buffer, size_t *lenp, 60 loff_t *ppos); 61 static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, 62 void __user *buffer, size_t *lenp, 63 loff_t *ppos); 64 static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, 65 void __user *buffer, size_t *lenp, 66 loff_t *ppos); 67 68 static struct ctl_table sctp_table[] = { 69 { 70 .procname = "sctp_mem", 71 .data = &sysctl_sctp_mem, 72 .maxlen = sizeof(sysctl_sctp_mem), 73 .mode = 0644, 74 .proc_handler = proc_doulongvec_minmax 75 }, 76 { 77 .procname = "sctp_rmem", 78 .data = &sysctl_sctp_rmem, 79 .maxlen = sizeof(sysctl_sctp_rmem), 80 .mode = 0644, 81 .proc_handler = proc_dointvec, 82 }, 83 { 84 .procname = "sctp_wmem", 85 .data = &sysctl_sctp_wmem, 86 .maxlen = sizeof(sysctl_sctp_wmem), 87 .mode = 0644, 88 .proc_handler = proc_dointvec, 89 }, 90 91 { /* sentinel */ } 92 }; 93 94 static struct ctl_table sctp_net_table[] = { 95 { 96 .procname = "rto_initial", 97 .data = &init_net.sctp.rto_initial, 98 .maxlen = sizeof(unsigned int), 99 .mode = 0644, 100 .proc_handler = proc_dointvec_minmax, 101 .extra1 = &one, 102 .extra2 = &timer_max 103 }, 104 { 105 .procname = "rto_min", 106 .data = &init_net.sctp.rto_min, 107 .maxlen = sizeof(unsigned int), 108 .mode = 0644, 109 .proc_handler = proc_sctp_do_rto_min, 110 .extra1 = &one, 111 .extra2 = &init_net.sctp.rto_max 112 }, 113 { 114 .procname = "rto_max", 115 .data = &init_net.sctp.rto_max, 116 .maxlen = sizeof(unsigned int), 117 .mode = 0644, 118 .proc_handler = proc_sctp_do_rto_max, 119 .extra1 = &init_net.sctp.rto_min, 120 .extra2 = &timer_max 121 }, 122 { 123 .procname = "rto_alpha_exp_divisor", 124 .data = &init_net.sctp.rto_alpha, 125 .maxlen = sizeof(int), 126 .mode = 0444, 127 .proc_handler = proc_dointvec, 128 }, 129 { 130 .procname = "rto_beta_exp_divisor", 131 .data = &init_net.sctp.rto_beta, 132 .maxlen = sizeof(int), 133 .mode = 0444, 134 .proc_handler = proc_dointvec, 135 }, 136 { 137 .procname = "max_burst", 138 .data = &init_net.sctp.max_burst, 139 .maxlen = sizeof(int), 140 .mode = 0644, 141 .proc_handler = proc_dointvec_minmax, 142 .extra1 = &zero, 143 .extra2 = &int_max 144 }, 145 { 146 .procname = "cookie_preserve_enable", 147 .data = &init_net.sctp.cookie_preserve_enable, 148 .maxlen = sizeof(int), 149 .mode = 0644, 150 .proc_handler = proc_dointvec, 151 }, 152 { 153 .procname = "cookie_hmac_alg", 154 .maxlen = 8, 155 .mode = 0644, 156 .proc_handler = proc_sctp_do_hmac_alg, 157 }, 158 { 159 .procname = "valid_cookie_life", 160 .data = &init_net.sctp.valid_cookie_life, 161 .maxlen = sizeof(unsigned int), 162 .mode = 0644, 163 .proc_handler = proc_dointvec_minmax, 164 .extra1 = &one, 165 .extra2 = &timer_max 166 }, 167 { 168 .procname = "sack_timeout", 169 .data = &init_net.sctp.sack_timeout, 170 .maxlen = sizeof(int), 171 .mode = 0644, 172 .proc_handler = proc_dointvec_minmax, 173 .extra1 = &sack_timer_min, 174 .extra2 = &sack_timer_max, 175 }, 176 { 177 .procname = "hb_interval", 178 .data = &init_net.sctp.hb_interval, 179 .maxlen = sizeof(unsigned int), 180 .mode = 0644, 181 .proc_handler = proc_dointvec_minmax, 182 .extra1 = &one, 183 .extra2 = &timer_max 184 }, 185 { 186 .procname = "association_max_retrans", 187 .data = &init_net.sctp.max_retrans_association, 188 .maxlen = sizeof(int), 189 .mode = 0644, 190 .proc_handler = proc_dointvec_minmax, 191 .extra1 = &one, 192 .extra2 = &int_max 193 }, 194 { 195 .procname = "path_max_retrans", 196 .data = &init_net.sctp.max_retrans_path, 197 .maxlen = sizeof(int), 198 .mode = 0644, 199 .proc_handler = proc_dointvec_minmax, 200 .extra1 = &one, 201 .extra2 = &int_max 202 }, 203 { 204 .procname = "max_init_retransmits", 205 .data = &init_net.sctp.max_retrans_init, 206 .maxlen = sizeof(int), 207 .mode = 0644, 208 .proc_handler = proc_dointvec_minmax, 209 .extra1 = &one, 210 .extra2 = &int_max 211 }, 212 { 213 .procname = "pf_retrans", 214 .data = &init_net.sctp.pf_retrans, 215 .maxlen = sizeof(int), 216 .mode = 0644, 217 .proc_handler = proc_dointvec_minmax, 218 .extra1 = &zero, 219 .extra2 = &int_max 220 }, 221 { 222 .procname = "sndbuf_policy", 223 .data = &init_net.sctp.sndbuf_policy, 224 .maxlen = sizeof(int), 225 .mode = 0644, 226 .proc_handler = proc_dointvec, 227 }, 228 { 229 .procname = "rcvbuf_policy", 230 .data = &init_net.sctp.rcvbuf_policy, 231 .maxlen = sizeof(int), 232 .mode = 0644, 233 .proc_handler = proc_dointvec, 234 }, 235 { 236 .procname = "default_auto_asconf", 237 .data = &init_net.sctp.default_auto_asconf, 238 .maxlen = sizeof(int), 239 .mode = 0644, 240 .proc_handler = proc_dointvec, 241 }, 242 { 243 .procname = "addip_enable", 244 .data = &init_net.sctp.addip_enable, 245 .maxlen = sizeof(int), 246 .mode = 0644, 247 .proc_handler = proc_dointvec, 248 }, 249 { 250 .procname = "addip_noauth_enable", 251 .data = &init_net.sctp.addip_noauth, 252 .maxlen = sizeof(int), 253 .mode = 0644, 254 .proc_handler = proc_dointvec, 255 }, 256 { 257 .procname = "prsctp_enable", 258 .data = &init_net.sctp.prsctp_enable, 259 .maxlen = sizeof(int), 260 .mode = 0644, 261 .proc_handler = proc_dointvec, 262 }, 263 { 264 .procname = "auth_enable", 265 .data = &init_net.sctp.auth_enable, 266 .maxlen = sizeof(int), 267 .mode = 0644, 268 .proc_handler = proc_dointvec, 269 }, 270 { 271 .procname = "addr_scope_policy", 272 .data = &init_net.sctp.scope_policy, 273 .maxlen = sizeof(int), 274 .mode = 0644, 275 .proc_handler = proc_dointvec_minmax, 276 .extra1 = &zero, 277 .extra2 = &addr_scope_max, 278 }, 279 { 280 .procname = "rwnd_update_shift", 281 .data = &init_net.sctp.rwnd_upd_shift, 282 .maxlen = sizeof(int), 283 .mode = 0644, 284 .proc_handler = &proc_dointvec_minmax, 285 .extra1 = &one, 286 .extra2 = &rwnd_scale_max, 287 }, 288 { 289 .procname = "max_autoclose", 290 .data = &init_net.sctp.max_autoclose, 291 .maxlen = sizeof(unsigned long), 292 .mode = 0644, 293 .proc_handler = &proc_doulongvec_minmax, 294 .extra1 = &max_autoclose_min, 295 .extra2 = &max_autoclose_max, 296 }, 297 298 { /* sentinel */ } 299 }; 300 301 static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, 302 void __user *buffer, size_t *lenp, 303 loff_t *ppos) 304 { 305 struct net *net = current->nsproxy->net_ns; 306 char tmp[8]; 307 struct ctl_table tbl; 308 int ret; 309 int changed = 0; 310 char *none = "none"; 311 312 memset(&tbl, 0, sizeof(struct ctl_table)); 313 314 if (write) { 315 tbl.data = tmp; 316 tbl.maxlen = 8; 317 } else { 318 tbl.data = net->sctp.sctp_hmac_alg ? : none; 319 tbl.maxlen = strlen(tbl.data); 320 } 321 ret = proc_dostring(&tbl, write, buffer, lenp, ppos); 322 323 if (write) { 324 #ifdef CONFIG_CRYPTO_MD5 325 if (!strncmp(tmp, "md5", 3)) { 326 net->sctp.sctp_hmac_alg = "md5"; 327 changed = 1; 328 } 329 #endif 330 #ifdef CONFIG_CRYPTO_SHA1 331 if (!strncmp(tmp, "sha1", 4)) { 332 net->sctp.sctp_hmac_alg = "sha1"; 333 changed = 1; 334 } 335 #endif 336 if (!strncmp(tmp, "none", 4)) { 337 net->sctp.sctp_hmac_alg = NULL; 338 changed = 1; 339 } 340 341 if (!changed) 342 ret = -EINVAL; 343 } 344 345 return ret; 346 } 347 348 static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, 349 void __user *buffer, size_t *lenp, 350 loff_t *ppos) 351 { 352 struct net *net = current->nsproxy->net_ns; 353 int new_value; 354 struct ctl_table tbl; 355 unsigned int min = *(unsigned int *) ctl->extra1; 356 unsigned int max = *(unsigned int *) ctl->extra2; 357 int ret; 358 359 memset(&tbl, 0, sizeof(struct ctl_table)); 360 tbl.maxlen = sizeof(unsigned int); 361 362 if (write) 363 tbl.data = &new_value; 364 else 365 tbl.data = &net->sctp.rto_min; 366 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 367 if (write) { 368 if (ret || new_value > max || new_value < min) 369 return -EINVAL; 370 net->sctp.rto_min = new_value; 371 } 372 return ret; 373 } 374 375 static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, 376 void __user *buffer, size_t *lenp, 377 loff_t *ppos) 378 { 379 struct net *net = current->nsproxy->net_ns; 380 int new_value; 381 struct ctl_table tbl; 382 unsigned int min = *(unsigned int *) ctl->extra1; 383 unsigned int max = *(unsigned int *) ctl->extra2; 384 int ret; 385 386 memset(&tbl, 0, sizeof(struct ctl_table)); 387 tbl.maxlen = sizeof(unsigned int); 388 389 if (write) 390 tbl.data = &new_value; 391 else 392 tbl.data = &net->sctp.rto_max; 393 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 394 if (write) { 395 if (ret || new_value > max || new_value < min) 396 return -EINVAL; 397 net->sctp.rto_max = new_value; 398 } 399 return ret; 400 } 401 402 int sctp_sysctl_net_register(struct net *net) 403 { 404 struct ctl_table *table; 405 int i; 406 407 table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); 408 if (!table) 409 return -ENOMEM; 410 411 for (i = 0; table[i].data; i++) 412 table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; 413 414 net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); 415 return 0; 416 } 417 418 void sctp_sysctl_net_unregister(struct net *net) 419 { 420 struct ctl_table *table; 421 422 table = net->sctp.sysctl_header->ctl_table_arg; 423 unregister_net_sysctl_table(net->sctp.sysctl_header); 424 kfree(table); 425 } 426 427 static struct ctl_table_header *sctp_sysctl_header; 428 429 /* Sysctl registration. */ 430 void sctp_sysctl_register(void) 431 { 432 sctp_sysctl_header = register_net_sysctl(&init_net, "net/sctp", sctp_table); 433 } 434 435 /* Sysctl deregistration. */ 436 void sctp_sysctl_unregister(void) 437 { 438 unregister_net_sysctl_table(sctp_sysctl_header); 439 } 440