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 = SCTP_SCOPE_POLICY_MAX; 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 = "intl_enable", 293 .data = &init_net.sctp.intl_enable, 294 .maxlen = sizeof(int), 295 .mode = 0644, 296 .proc_handler = proc_dointvec, 297 }, 298 { 299 .procname = "addr_scope_policy", 300 .data = &init_net.sctp.scope_policy, 301 .maxlen = sizeof(int), 302 .mode = 0644, 303 .proc_handler = proc_dointvec_minmax, 304 .extra1 = &zero, 305 .extra2 = &addr_scope_max, 306 }, 307 { 308 .procname = "rwnd_update_shift", 309 .data = &init_net.sctp.rwnd_upd_shift, 310 .maxlen = sizeof(int), 311 .mode = 0644, 312 .proc_handler = &proc_dointvec_minmax, 313 .extra1 = &one, 314 .extra2 = &rwnd_scale_max, 315 }, 316 { 317 .procname = "max_autoclose", 318 .data = &init_net.sctp.max_autoclose, 319 .maxlen = sizeof(unsigned long), 320 .mode = 0644, 321 .proc_handler = &proc_doulongvec_minmax, 322 .extra1 = &max_autoclose_min, 323 .extra2 = &max_autoclose_max, 324 }, 325 { 326 .procname = "pf_enable", 327 .data = &init_net.sctp.pf_enable, 328 .maxlen = sizeof(int), 329 .mode = 0644, 330 .proc_handler = proc_dointvec, 331 }, 332 333 { /* sentinel */ } 334 }; 335 336 static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, 337 void __user *buffer, size_t *lenp, 338 loff_t *ppos) 339 { 340 struct net *net = current->nsproxy->net_ns; 341 struct ctl_table tbl; 342 bool changed = false; 343 char *none = "none"; 344 char tmp[8] = {0}; 345 int ret; 346 347 memset(&tbl, 0, sizeof(struct ctl_table)); 348 349 if (write) { 350 tbl.data = tmp; 351 tbl.maxlen = sizeof(tmp); 352 } else { 353 tbl.data = net->sctp.sctp_hmac_alg ? : none; 354 tbl.maxlen = strlen(tbl.data); 355 } 356 357 ret = proc_dostring(&tbl, write, buffer, lenp, ppos); 358 if (write && ret == 0) { 359 #ifdef CONFIG_CRYPTO_MD5 360 if (!strncmp(tmp, "md5", 3)) { 361 net->sctp.sctp_hmac_alg = "md5"; 362 changed = true; 363 } 364 #endif 365 #ifdef CONFIG_CRYPTO_SHA1 366 if (!strncmp(tmp, "sha1", 4)) { 367 net->sctp.sctp_hmac_alg = "sha1"; 368 changed = true; 369 } 370 #endif 371 if (!strncmp(tmp, "none", 4)) { 372 net->sctp.sctp_hmac_alg = NULL; 373 changed = true; 374 } 375 if (!changed) 376 ret = -EINVAL; 377 } 378 379 return ret; 380 } 381 382 static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, 383 void __user *buffer, size_t *lenp, 384 loff_t *ppos) 385 { 386 struct net *net = current->nsproxy->net_ns; 387 unsigned int min = *(unsigned int *) ctl->extra1; 388 unsigned int max = *(unsigned int *) ctl->extra2; 389 struct ctl_table tbl; 390 int ret, new_value; 391 392 memset(&tbl, 0, sizeof(struct ctl_table)); 393 tbl.maxlen = sizeof(unsigned int); 394 395 if (write) 396 tbl.data = &new_value; 397 else 398 tbl.data = &net->sctp.rto_min; 399 400 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 401 if (write && ret == 0) { 402 if (new_value > max || new_value < min) 403 return -EINVAL; 404 405 net->sctp.rto_min = new_value; 406 } 407 408 return ret; 409 } 410 411 static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, 412 void __user *buffer, size_t *lenp, 413 loff_t *ppos) 414 { 415 struct net *net = current->nsproxy->net_ns; 416 unsigned int min = *(unsigned int *) ctl->extra1; 417 unsigned int max = *(unsigned int *) ctl->extra2; 418 struct ctl_table tbl; 419 int ret, new_value; 420 421 memset(&tbl, 0, sizeof(struct ctl_table)); 422 tbl.maxlen = sizeof(unsigned int); 423 424 if (write) 425 tbl.data = &new_value; 426 else 427 tbl.data = &net->sctp.rto_max; 428 429 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 430 if (write && ret == 0) { 431 if (new_value > max || new_value < min) 432 return -EINVAL; 433 434 net->sctp.rto_max = new_value; 435 } 436 437 return ret; 438 } 439 440 static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write, 441 void __user *buffer, size_t *lenp, 442 loff_t *ppos) 443 { 444 if (write) 445 pr_warn_once("Changing rto_alpha or rto_beta may lead to " 446 "suboptimal rtt/srtt estimations!\n"); 447 448 return proc_dointvec_minmax(ctl, write, buffer, lenp, ppos); 449 } 450 451 static int proc_sctp_do_auth(struct ctl_table *ctl, int write, 452 void __user *buffer, size_t *lenp, 453 loff_t *ppos) 454 { 455 struct net *net = current->nsproxy->net_ns; 456 struct ctl_table tbl; 457 int new_value, ret; 458 459 memset(&tbl, 0, sizeof(struct ctl_table)); 460 tbl.maxlen = sizeof(unsigned int); 461 462 if (write) 463 tbl.data = &new_value; 464 else 465 tbl.data = &net->sctp.auth_enable; 466 467 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 468 if (write && ret == 0) { 469 struct sock *sk = net->sctp.ctl_sock; 470 471 net->sctp.auth_enable = new_value; 472 /* Update the value in the control socket */ 473 lock_sock(sk); 474 sctp_sk(sk)->ep->auth_enable = new_value; 475 release_sock(sk); 476 } 477 478 return ret; 479 } 480 481 int sctp_sysctl_net_register(struct net *net) 482 { 483 struct ctl_table *table; 484 int i; 485 486 table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); 487 if (!table) 488 return -ENOMEM; 489 490 for (i = 0; table[i].data; i++) 491 table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; 492 493 net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); 494 if (net->sctp.sysctl_header == NULL) { 495 kfree(table); 496 return -ENOMEM; 497 } 498 return 0; 499 } 500 501 void sctp_sysctl_net_unregister(struct net *net) 502 { 503 struct ctl_table *table; 504 505 table = net->sctp.sysctl_header->ctl_table_arg; 506 unregister_net_sysctl_table(net->sctp.sysctl_header); 507 kfree(table); 508 } 509 510 static struct ctl_table_header *sctp_sysctl_header; 511 512 /* Sysctl registration. */ 513 void sctp_sysctl_register(void) 514 { 515 sctp_sysctl_header = register_net_sysctl(&init_net, "net/sctp", sctp_table); 516 } 517 518 /* Sysctl deregistration. */ 519 void sctp_sysctl_unregister(void) 520 { 521 unregister_net_sysctl_table(sctp_sysctl_header); 522 } 523