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