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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 38 39 #include <net/sctp/structs.h> 40 #include <net/sctp/sctp.h> 41 #include <linux/sysctl.h> 42 43 static int zero = 0; 44 static int one = 1; 45 static int timer_max = 86400000; /* ms in one day */ 46 static int int_max = INT_MAX; 47 static int sack_timer_min = 1; 48 static int sack_timer_max = 500; 49 static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */ 50 static int rwnd_scale_max = 16; 51 static int rto_alpha_min = 0; 52 static int rto_beta_min = 0; 53 static int rto_alpha_max = 1000; 54 static int rto_beta_max = 1000; 55 56 static unsigned long max_autoclose_min = 0; 57 static unsigned long max_autoclose_max = 58 (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX) 59 ? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ; 60 61 static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, 62 void __user *buffer, size_t *lenp, 63 loff_t *ppos); 64 static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, 65 void __user *buffer, size_t *lenp, 66 loff_t *ppos); 67 static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, 68 void __user *buffer, size_t *lenp, 69 loff_t *ppos); 70 static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write, 71 void __user *buffer, size_t *lenp, 72 loff_t *ppos); 73 static int proc_sctp_do_auth(struct ctl_table *ctl, int write, 74 void __user *buffer, size_t *lenp, 75 loff_t *ppos); 76 77 static struct ctl_table sctp_table[] = { 78 { 79 .procname = "sctp_mem", 80 .data = &sysctl_sctp_mem, 81 .maxlen = sizeof(sysctl_sctp_mem), 82 .mode = 0644, 83 .proc_handler = proc_doulongvec_minmax 84 }, 85 { 86 .procname = "sctp_rmem", 87 .data = &sysctl_sctp_rmem, 88 .maxlen = sizeof(sysctl_sctp_rmem), 89 .mode = 0644, 90 .proc_handler = proc_dointvec, 91 }, 92 { 93 .procname = "sctp_wmem", 94 .data = &sysctl_sctp_wmem, 95 .maxlen = sizeof(sysctl_sctp_wmem), 96 .mode = 0644, 97 .proc_handler = proc_dointvec, 98 }, 99 100 { /* sentinel */ } 101 }; 102 103 static struct ctl_table sctp_net_table[] = { 104 { 105 .procname = "rto_initial", 106 .data = &init_net.sctp.rto_initial, 107 .maxlen = sizeof(unsigned int), 108 .mode = 0644, 109 .proc_handler = proc_dointvec_minmax, 110 .extra1 = &one, 111 .extra2 = &timer_max 112 }, 113 { 114 .procname = "rto_min", 115 .data = &init_net.sctp.rto_min, 116 .maxlen = sizeof(unsigned int), 117 .mode = 0644, 118 .proc_handler = proc_sctp_do_rto_min, 119 .extra1 = &one, 120 .extra2 = &init_net.sctp.rto_max 121 }, 122 { 123 .procname = "rto_max", 124 .data = &init_net.sctp.rto_max, 125 .maxlen = sizeof(unsigned int), 126 .mode = 0644, 127 .proc_handler = proc_sctp_do_rto_max, 128 .extra1 = &init_net.sctp.rto_min, 129 .extra2 = &timer_max 130 }, 131 { 132 .procname = "rto_alpha_exp_divisor", 133 .data = &init_net.sctp.rto_alpha, 134 .maxlen = sizeof(int), 135 .mode = 0644, 136 .proc_handler = proc_sctp_do_alpha_beta, 137 .extra1 = &rto_alpha_min, 138 .extra2 = &rto_alpha_max, 139 }, 140 { 141 .procname = "rto_beta_exp_divisor", 142 .data = &init_net.sctp.rto_beta, 143 .maxlen = sizeof(int), 144 .mode = 0644, 145 .proc_handler = proc_sctp_do_alpha_beta, 146 .extra1 = &rto_beta_min, 147 .extra2 = &rto_beta_max, 148 }, 149 { 150 .procname = "max_burst", 151 .data = &init_net.sctp.max_burst, 152 .maxlen = sizeof(int), 153 .mode = 0644, 154 .proc_handler = proc_dointvec_minmax, 155 .extra1 = &zero, 156 .extra2 = &int_max 157 }, 158 { 159 .procname = "cookie_preserve_enable", 160 .data = &init_net.sctp.cookie_preserve_enable, 161 .maxlen = sizeof(int), 162 .mode = 0644, 163 .proc_handler = proc_dointvec, 164 }, 165 { 166 .procname = "cookie_hmac_alg", 167 .data = &init_net.sctp.sctp_hmac_alg, 168 .maxlen = 8, 169 .mode = 0644, 170 .proc_handler = proc_sctp_do_hmac_alg, 171 }, 172 { 173 .procname = "valid_cookie_life", 174 .data = &init_net.sctp.valid_cookie_life, 175 .maxlen = sizeof(unsigned int), 176 .mode = 0644, 177 .proc_handler = proc_dointvec_minmax, 178 .extra1 = &one, 179 .extra2 = &timer_max 180 }, 181 { 182 .procname = "sack_timeout", 183 .data = &init_net.sctp.sack_timeout, 184 .maxlen = sizeof(int), 185 .mode = 0644, 186 .proc_handler = proc_dointvec_minmax, 187 .extra1 = &sack_timer_min, 188 .extra2 = &sack_timer_max, 189 }, 190 { 191 .procname = "hb_interval", 192 .data = &init_net.sctp.hb_interval, 193 .maxlen = sizeof(unsigned int), 194 .mode = 0644, 195 .proc_handler = proc_dointvec_minmax, 196 .extra1 = &one, 197 .extra2 = &timer_max 198 }, 199 { 200 .procname = "association_max_retrans", 201 .data = &init_net.sctp.max_retrans_association, 202 .maxlen = sizeof(int), 203 .mode = 0644, 204 .proc_handler = proc_dointvec_minmax, 205 .extra1 = &one, 206 .extra2 = &int_max 207 }, 208 { 209 .procname = "path_max_retrans", 210 .data = &init_net.sctp.max_retrans_path, 211 .maxlen = sizeof(int), 212 .mode = 0644, 213 .proc_handler = proc_dointvec_minmax, 214 .extra1 = &one, 215 .extra2 = &int_max 216 }, 217 { 218 .procname = "max_init_retransmits", 219 .data = &init_net.sctp.max_retrans_init, 220 .maxlen = sizeof(int), 221 .mode = 0644, 222 .proc_handler = proc_dointvec_minmax, 223 .extra1 = &one, 224 .extra2 = &int_max 225 }, 226 { 227 .procname = "pf_retrans", 228 .data = &init_net.sctp.pf_retrans, 229 .maxlen = sizeof(int), 230 .mode = 0644, 231 .proc_handler = proc_dointvec_minmax, 232 .extra1 = &zero, 233 .extra2 = &int_max 234 }, 235 { 236 .procname = "sndbuf_policy", 237 .data = &init_net.sctp.sndbuf_policy, 238 .maxlen = sizeof(int), 239 .mode = 0644, 240 .proc_handler = proc_dointvec, 241 }, 242 { 243 .procname = "rcvbuf_policy", 244 .data = &init_net.sctp.rcvbuf_policy, 245 .maxlen = sizeof(int), 246 .mode = 0644, 247 .proc_handler = proc_dointvec, 248 }, 249 { 250 .procname = "default_auto_asconf", 251 .data = &init_net.sctp.default_auto_asconf, 252 .maxlen = sizeof(int), 253 .mode = 0644, 254 .proc_handler = proc_dointvec, 255 }, 256 { 257 .procname = "addip_enable", 258 .data = &init_net.sctp.addip_enable, 259 .maxlen = sizeof(int), 260 .mode = 0644, 261 .proc_handler = proc_dointvec, 262 }, 263 { 264 .procname = "addip_noauth_enable", 265 .data = &init_net.sctp.addip_noauth, 266 .maxlen = sizeof(int), 267 .mode = 0644, 268 .proc_handler = proc_dointvec, 269 }, 270 { 271 .procname = "prsctp_enable", 272 .data = &init_net.sctp.prsctp_enable, 273 .maxlen = sizeof(int), 274 .mode = 0644, 275 .proc_handler = proc_dointvec, 276 }, 277 { 278 .procname = "reconf_enable", 279 .data = &init_net.sctp.reconf_enable, 280 .maxlen = sizeof(int), 281 .mode = 0644, 282 .proc_handler = proc_dointvec, 283 }, 284 { 285 .procname = "auth_enable", 286 .data = &init_net.sctp.auth_enable, 287 .maxlen = sizeof(int), 288 .mode = 0644, 289 .proc_handler = proc_sctp_do_auth, 290 }, 291 { 292 .procname = "addr_scope_policy", 293 .data = &init_net.sctp.scope_policy, 294 .maxlen = sizeof(int), 295 .mode = 0644, 296 .proc_handler = proc_dointvec_minmax, 297 .extra1 = &zero, 298 .extra2 = &addr_scope_max, 299 }, 300 { 301 .procname = "rwnd_update_shift", 302 .data = &init_net.sctp.rwnd_upd_shift, 303 .maxlen = sizeof(int), 304 .mode = 0644, 305 .proc_handler = &proc_dointvec_minmax, 306 .extra1 = &one, 307 .extra2 = &rwnd_scale_max, 308 }, 309 { 310 .procname = "max_autoclose", 311 .data = &init_net.sctp.max_autoclose, 312 .maxlen = sizeof(unsigned long), 313 .mode = 0644, 314 .proc_handler = &proc_doulongvec_minmax, 315 .extra1 = &max_autoclose_min, 316 .extra2 = &max_autoclose_max, 317 }, 318 { 319 .procname = "pf_enable", 320 .data = &init_net.sctp.pf_enable, 321 .maxlen = sizeof(int), 322 .mode = 0644, 323 .proc_handler = proc_dointvec, 324 }, 325 326 { /* sentinel */ } 327 }; 328 329 static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, 330 void __user *buffer, size_t *lenp, 331 loff_t *ppos) 332 { 333 struct net *net = current->nsproxy->net_ns; 334 struct ctl_table tbl; 335 bool changed = false; 336 char *none = "none"; 337 char tmp[8] = {0}; 338 int ret; 339 340 memset(&tbl, 0, sizeof(struct ctl_table)); 341 342 if (write) { 343 tbl.data = tmp; 344 tbl.maxlen = sizeof(tmp); 345 } else { 346 tbl.data = net->sctp.sctp_hmac_alg ? : none; 347 tbl.maxlen = strlen(tbl.data); 348 } 349 350 ret = proc_dostring(&tbl, write, buffer, lenp, ppos); 351 if (write && ret == 0) { 352 #ifdef CONFIG_CRYPTO_MD5 353 if (!strncmp(tmp, "md5", 3)) { 354 net->sctp.sctp_hmac_alg = "md5"; 355 changed = true; 356 } 357 #endif 358 #ifdef CONFIG_CRYPTO_SHA1 359 if (!strncmp(tmp, "sha1", 4)) { 360 net->sctp.sctp_hmac_alg = "sha1"; 361 changed = true; 362 } 363 #endif 364 if (!strncmp(tmp, "none", 4)) { 365 net->sctp.sctp_hmac_alg = NULL; 366 changed = true; 367 } 368 if (!changed) 369 ret = -EINVAL; 370 } 371 372 return ret; 373 } 374 375 static int proc_sctp_do_rto_min(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 unsigned int min = *(unsigned int *) ctl->extra1; 381 unsigned int max = *(unsigned int *) ctl->extra2; 382 struct ctl_table tbl; 383 int ret, new_value; 384 385 memset(&tbl, 0, sizeof(struct ctl_table)); 386 tbl.maxlen = sizeof(unsigned int); 387 388 if (write) 389 tbl.data = &new_value; 390 else 391 tbl.data = &net->sctp.rto_min; 392 393 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 394 if (write && ret == 0) { 395 if (new_value > max || new_value < min) 396 return -EINVAL; 397 398 net->sctp.rto_min = new_value; 399 } 400 401 return ret; 402 } 403 404 static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, 405 void __user *buffer, size_t *lenp, 406 loff_t *ppos) 407 { 408 struct net *net = current->nsproxy->net_ns; 409 unsigned int min = *(unsigned int *) ctl->extra1; 410 unsigned int max = *(unsigned int *) ctl->extra2; 411 struct ctl_table tbl; 412 int ret, new_value; 413 414 memset(&tbl, 0, sizeof(struct ctl_table)); 415 tbl.maxlen = sizeof(unsigned int); 416 417 if (write) 418 tbl.data = &new_value; 419 else 420 tbl.data = &net->sctp.rto_max; 421 422 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 423 if (write && ret == 0) { 424 if (new_value > max || new_value < min) 425 return -EINVAL; 426 427 net->sctp.rto_max = new_value; 428 } 429 430 return ret; 431 } 432 433 static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write, 434 void __user *buffer, size_t *lenp, 435 loff_t *ppos) 436 { 437 if (write) 438 pr_warn_once("Changing rto_alpha or rto_beta may lead to " 439 "suboptimal rtt/srtt estimations!\n"); 440 441 return proc_dointvec_minmax(ctl, write, buffer, lenp, ppos); 442 } 443 444 static int proc_sctp_do_auth(struct ctl_table *ctl, int write, 445 void __user *buffer, size_t *lenp, 446 loff_t *ppos) 447 { 448 struct net *net = current->nsproxy->net_ns; 449 struct ctl_table tbl; 450 int new_value, ret; 451 452 memset(&tbl, 0, sizeof(struct ctl_table)); 453 tbl.maxlen = sizeof(unsigned int); 454 455 if (write) 456 tbl.data = &new_value; 457 else 458 tbl.data = &net->sctp.auth_enable; 459 460 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 461 if (write && ret == 0) { 462 struct sock *sk = net->sctp.ctl_sock; 463 464 net->sctp.auth_enable = new_value; 465 /* Update the value in the control socket */ 466 lock_sock(sk); 467 sctp_sk(sk)->ep->auth_enable = new_value; 468 release_sock(sk); 469 } 470 471 return ret; 472 } 473 474 int sctp_sysctl_net_register(struct net *net) 475 { 476 struct ctl_table *table; 477 int i; 478 479 table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); 480 if (!table) 481 return -ENOMEM; 482 483 for (i = 0; table[i].data; i++) 484 table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; 485 486 net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); 487 if (net->sctp.sysctl_header == NULL) { 488 kfree(table); 489 return -ENOMEM; 490 } 491 return 0; 492 } 493 494 void sctp_sysctl_net_unregister(struct net *net) 495 { 496 struct ctl_table *table; 497 498 table = net->sctp.sysctl_header->ctl_table_arg; 499 unregister_net_sysctl_table(net->sctp.sysctl_header); 500 kfree(table); 501 } 502 503 static struct ctl_table_header *sctp_sysctl_header; 504 505 /* Sysctl registration. */ 506 void sctp_sysctl_register(void) 507 { 508 sctp_sysctl_header = register_net_sysctl(&init_net, "net/sctp", sctp_table); 509 } 510 511 /* Sysctl deregistration. */ 512 void sctp_sysctl_unregister(void) 513 { 514 unregister_net_sysctl_table(sctp_sysctl_header); 515 } 516