1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* SCTP kernel implementation 3 * (C) Copyright IBM Corp. 2002, 2004 4 * Copyright (c) 2002 Intel Corp. 5 * 6 * This file is part of the SCTP kernel implementation 7 * 8 * Sysctl related interfaces for SCTP. 9 * 10 * Please send any bug reports or fixes you make to the 11 * email address(es): 12 * lksctp developers <linux-sctp@vger.kernel.org> 13 * 14 * Written or modified by: 15 * Mingqin Liu <liuming@us.ibm.com> 16 * Jon Grimm <jgrimm@us.ibm.com> 17 * Ardelle Fan <ardelle.fan@intel.com> 18 * Ryan Layer <rmlayer@us.ibm.com> 19 * Sridhar Samudrala <sri@us.ibm.com> 20 */ 21 22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 23 24 #include <net/sctp/structs.h> 25 #include <net/sctp/sctp.h> 26 #include <linux/sysctl.h> 27 28 static int timer_max = 86400000; /* ms in one day */ 29 static int sack_timer_min = 1; 30 static int sack_timer_max = 500; 31 static int addr_scope_max = SCTP_SCOPE_POLICY_MAX; 32 static int rwnd_scale_max = 16; 33 static int rto_alpha_min = 0; 34 static int rto_beta_min = 0; 35 static int rto_alpha_max = 1000; 36 static int rto_beta_max = 1000; 37 static int pf_expose_max = SCTP_PF_EXPOSE_MAX; 38 static int ps_retrans_max = SCTP_PS_RETRANS_MAX; 39 40 static unsigned long max_autoclose_min = 0; 41 static unsigned long max_autoclose_max = 42 (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX) 43 ? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ; 44 45 static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, 46 void __user *buffer, size_t *lenp, 47 loff_t *ppos); 48 static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, 49 void __user *buffer, size_t *lenp, 50 loff_t *ppos); 51 static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, 52 void __user *buffer, size_t *lenp, 53 loff_t *ppos); 54 static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write, 55 void __user *buffer, size_t *lenp, 56 loff_t *ppos); 57 static int proc_sctp_do_auth(struct ctl_table *ctl, int write, 58 void __user *buffer, size_t *lenp, 59 loff_t *ppos); 60 61 static struct ctl_table sctp_table[] = { 62 { 63 .procname = "sctp_mem", 64 .data = &sysctl_sctp_mem, 65 .maxlen = sizeof(sysctl_sctp_mem), 66 .mode = 0644, 67 .proc_handler = proc_doulongvec_minmax 68 }, 69 { 70 .procname = "sctp_rmem", 71 .data = &sysctl_sctp_rmem, 72 .maxlen = sizeof(sysctl_sctp_rmem), 73 .mode = 0644, 74 .proc_handler = proc_dointvec, 75 }, 76 { 77 .procname = "sctp_wmem", 78 .data = &sysctl_sctp_wmem, 79 .maxlen = sizeof(sysctl_sctp_wmem), 80 .mode = 0644, 81 .proc_handler = proc_dointvec, 82 }, 83 84 { /* sentinel */ } 85 }; 86 87 static struct ctl_table sctp_net_table[] = { 88 { 89 .procname = "rto_initial", 90 .data = &init_net.sctp.rto_initial, 91 .maxlen = sizeof(unsigned int), 92 .mode = 0644, 93 .proc_handler = proc_dointvec_minmax, 94 .extra1 = SYSCTL_ONE, 95 .extra2 = &timer_max 96 }, 97 { 98 .procname = "rto_min", 99 .data = &init_net.sctp.rto_min, 100 .maxlen = sizeof(unsigned int), 101 .mode = 0644, 102 .proc_handler = proc_sctp_do_rto_min, 103 .extra1 = SYSCTL_ONE, 104 .extra2 = &init_net.sctp.rto_max 105 }, 106 { 107 .procname = "rto_max", 108 .data = &init_net.sctp.rto_max, 109 .maxlen = sizeof(unsigned int), 110 .mode = 0644, 111 .proc_handler = proc_sctp_do_rto_max, 112 .extra1 = &init_net.sctp.rto_min, 113 .extra2 = &timer_max 114 }, 115 { 116 .procname = "rto_alpha_exp_divisor", 117 .data = &init_net.sctp.rto_alpha, 118 .maxlen = sizeof(int), 119 .mode = 0644, 120 .proc_handler = proc_sctp_do_alpha_beta, 121 .extra1 = &rto_alpha_min, 122 .extra2 = &rto_alpha_max, 123 }, 124 { 125 .procname = "rto_beta_exp_divisor", 126 .data = &init_net.sctp.rto_beta, 127 .maxlen = sizeof(int), 128 .mode = 0644, 129 .proc_handler = proc_sctp_do_alpha_beta, 130 .extra1 = &rto_beta_min, 131 .extra2 = &rto_beta_max, 132 }, 133 { 134 .procname = "max_burst", 135 .data = &init_net.sctp.max_burst, 136 .maxlen = sizeof(int), 137 .mode = 0644, 138 .proc_handler = proc_dointvec_minmax, 139 .extra1 = SYSCTL_ZERO, 140 .extra2 = SYSCTL_INT_MAX, 141 }, 142 { 143 .procname = "cookie_preserve_enable", 144 .data = &init_net.sctp.cookie_preserve_enable, 145 .maxlen = sizeof(int), 146 .mode = 0644, 147 .proc_handler = proc_dointvec, 148 }, 149 { 150 .procname = "cookie_hmac_alg", 151 .data = &init_net.sctp.sctp_hmac_alg, 152 .maxlen = 8, 153 .mode = 0644, 154 .proc_handler = proc_sctp_do_hmac_alg, 155 }, 156 { 157 .procname = "valid_cookie_life", 158 .data = &init_net.sctp.valid_cookie_life, 159 .maxlen = sizeof(unsigned int), 160 .mode = 0644, 161 .proc_handler = proc_dointvec_minmax, 162 .extra1 = SYSCTL_ONE, 163 .extra2 = &timer_max 164 }, 165 { 166 .procname = "sack_timeout", 167 .data = &init_net.sctp.sack_timeout, 168 .maxlen = sizeof(int), 169 .mode = 0644, 170 .proc_handler = proc_dointvec_minmax, 171 .extra1 = &sack_timer_min, 172 .extra2 = &sack_timer_max, 173 }, 174 { 175 .procname = "hb_interval", 176 .data = &init_net.sctp.hb_interval, 177 .maxlen = sizeof(unsigned int), 178 .mode = 0644, 179 .proc_handler = proc_dointvec_minmax, 180 .extra1 = SYSCTL_ONE, 181 .extra2 = &timer_max 182 }, 183 { 184 .procname = "association_max_retrans", 185 .data = &init_net.sctp.max_retrans_association, 186 .maxlen = sizeof(int), 187 .mode = 0644, 188 .proc_handler = proc_dointvec_minmax, 189 .extra1 = SYSCTL_ONE, 190 .extra2 = SYSCTL_INT_MAX, 191 }, 192 { 193 .procname = "path_max_retrans", 194 .data = &init_net.sctp.max_retrans_path, 195 .maxlen = sizeof(int), 196 .mode = 0644, 197 .proc_handler = proc_dointvec_minmax, 198 .extra1 = SYSCTL_ONE, 199 .extra2 = SYSCTL_INT_MAX, 200 }, 201 { 202 .procname = "max_init_retransmits", 203 .data = &init_net.sctp.max_retrans_init, 204 .maxlen = sizeof(int), 205 .mode = 0644, 206 .proc_handler = proc_dointvec_minmax, 207 .extra1 = SYSCTL_ONE, 208 .extra2 = SYSCTL_INT_MAX, 209 }, 210 { 211 .procname = "pf_retrans", 212 .data = &init_net.sctp.pf_retrans, 213 .maxlen = sizeof(int), 214 .mode = 0644, 215 .proc_handler = proc_dointvec_minmax, 216 .extra1 = SYSCTL_ZERO, 217 .extra2 = &init_net.sctp.ps_retrans, 218 }, 219 { 220 .procname = "ps_retrans", 221 .data = &init_net.sctp.ps_retrans, 222 .maxlen = sizeof(int), 223 .mode = 0644, 224 .proc_handler = proc_dointvec_minmax, 225 .extra1 = &init_net.sctp.pf_retrans, 226 .extra2 = &ps_retrans_max, 227 }, 228 { 229 .procname = "sndbuf_policy", 230 .data = &init_net.sctp.sndbuf_policy, 231 .maxlen = sizeof(int), 232 .mode = 0644, 233 .proc_handler = proc_dointvec, 234 }, 235 { 236 .procname = "rcvbuf_policy", 237 .data = &init_net.sctp.rcvbuf_policy, 238 .maxlen = sizeof(int), 239 .mode = 0644, 240 .proc_handler = proc_dointvec, 241 }, 242 { 243 .procname = "default_auto_asconf", 244 .data = &init_net.sctp.default_auto_asconf, 245 .maxlen = sizeof(int), 246 .mode = 0644, 247 .proc_handler = proc_dointvec, 248 }, 249 { 250 .procname = "addip_enable", 251 .data = &init_net.sctp.addip_enable, 252 .maxlen = sizeof(int), 253 .mode = 0644, 254 .proc_handler = proc_dointvec, 255 }, 256 { 257 .procname = "addip_noauth_enable", 258 .data = &init_net.sctp.addip_noauth, 259 .maxlen = sizeof(int), 260 .mode = 0644, 261 .proc_handler = proc_dointvec, 262 }, 263 { 264 .procname = "prsctp_enable", 265 .data = &init_net.sctp.prsctp_enable, 266 .maxlen = sizeof(int), 267 .mode = 0644, 268 .proc_handler = proc_dointvec, 269 }, 270 { 271 .procname = "reconf_enable", 272 .data = &init_net.sctp.reconf_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 = "intl_enable", 286 .data = &init_net.sctp.intl_enable, 287 .maxlen = sizeof(int), 288 .mode = 0644, 289 .proc_handler = proc_dointvec, 290 }, 291 { 292 .procname = "ecn_enable", 293 .data = &init_net.sctp.ecn_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 = SYSCTL_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 = SYSCTL_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 .procname = "pf_expose", 334 .data = &init_net.sctp.pf_expose, 335 .maxlen = sizeof(int), 336 .mode = 0644, 337 .proc_handler = proc_dointvec_minmax, 338 .extra1 = SYSCTL_ZERO, 339 .extra2 = &pf_expose_max, 340 }, 341 342 { /* sentinel */ } 343 }; 344 345 static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, 346 void __user *buffer, size_t *lenp, 347 loff_t *ppos) 348 { 349 struct net *net = current->nsproxy->net_ns; 350 struct ctl_table tbl; 351 bool changed = false; 352 char *none = "none"; 353 char tmp[8] = {0}; 354 int ret; 355 356 memset(&tbl, 0, sizeof(struct ctl_table)); 357 358 if (write) { 359 tbl.data = tmp; 360 tbl.maxlen = sizeof(tmp); 361 } else { 362 tbl.data = net->sctp.sctp_hmac_alg ? : none; 363 tbl.maxlen = strlen(tbl.data); 364 } 365 366 ret = proc_dostring(&tbl, write, buffer, lenp, ppos); 367 if (write && ret == 0) { 368 #ifdef CONFIG_CRYPTO_MD5 369 if (!strncmp(tmp, "md5", 3)) { 370 net->sctp.sctp_hmac_alg = "md5"; 371 changed = true; 372 } 373 #endif 374 #ifdef CONFIG_CRYPTO_SHA1 375 if (!strncmp(tmp, "sha1", 4)) { 376 net->sctp.sctp_hmac_alg = "sha1"; 377 changed = true; 378 } 379 #endif 380 if (!strncmp(tmp, "none", 4)) { 381 net->sctp.sctp_hmac_alg = NULL; 382 changed = true; 383 } 384 if (!changed) 385 ret = -EINVAL; 386 } 387 388 return ret; 389 } 390 391 static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, 392 void __user *buffer, size_t *lenp, 393 loff_t *ppos) 394 { 395 struct net *net = current->nsproxy->net_ns; 396 unsigned int min = *(unsigned int *) ctl->extra1; 397 unsigned int max = *(unsigned int *) ctl->extra2; 398 struct ctl_table tbl; 399 int ret, new_value; 400 401 memset(&tbl, 0, sizeof(struct ctl_table)); 402 tbl.maxlen = sizeof(unsigned int); 403 404 if (write) 405 tbl.data = &new_value; 406 else 407 tbl.data = &net->sctp.rto_min; 408 409 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 410 if (write && ret == 0) { 411 if (new_value > max || new_value < min) 412 return -EINVAL; 413 414 net->sctp.rto_min = new_value; 415 } 416 417 return ret; 418 } 419 420 static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, 421 void __user *buffer, size_t *lenp, 422 loff_t *ppos) 423 { 424 struct net *net = current->nsproxy->net_ns; 425 unsigned int min = *(unsigned int *) ctl->extra1; 426 unsigned int max = *(unsigned int *) ctl->extra2; 427 struct ctl_table tbl; 428 int ret, new_value; 429 430 memset(&tbl, 0, sizeof(struct ctl_table)); 431 tbl.maxlen = sizeof(unsigned int); 432 433 if (write) 434 tbl.data = &new_value; 435 else 436 tbl.data = &net->sctp.rto_max; 437 438 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 439 if (write && ret == 0) { 440 if (new_value > max || new_value < min) 441 return -EINVAL; 442 443 net->sctp.rto_max = new_value; 444 } 445 446 return ret; 447 } 448 449 static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write, 450 void __user *buffer, size_t *lenp, 451 loff_t *ppos) 452 { 453 if (write) 454 pr_warn_once("Changing rto_alpha or rto_beta may lead to " 455 "suboptimal rtt/srtt estimations!\n"); 456 457 return proc_dointvec_minmax(ctl, write, buffer, lenp, ppos); 458 } 459 460 static int proc_sctp_do_auth(struct ctl_table *ctl, int write, 461 void __user *buffer, size_t *lenp, 462 loff_t *ppos) 463 { 464 struct net *net = current->nsproxy->net_ns; 465 struct ctl_table tbl; 466 int new_value, ret; 467 468 memset(&tbl, 0, sizeof(struct ctl_table)); 469 tbl.maxlen = sizeof(unsigned int); 470 471 if (write) 472 tbl.data = &new_value; 473 else 474 tbl.data = &net->sctp.auth_enable; 475 476 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 477 if (write && ret == 0) { 478 struct sock *sk = net->sctp.ctl_sock; 479 480 net->sctp.auth_enable = new_value; 481 /* Update the value in the control socket */ 482 lock_sock(sk); 483 sctp_sk(sk)->ep->auth_enable = new_value; 484 release_sock(sk); 485 } 486 487 return ret; 488 } 489 490 int sctp_sysctl_net_register(struct net *net) 491 { 492 struct ctl_table *table; 493 int i; 494 495 table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); 496 if (!table) 497 return -ENOMEM; 498 499 for (i = 0; table[i].data; i++) 500 table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; 501 502 net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); 503 if (net->sctp.sysctl_header == NULL) { 504 kfree(table); 505 return -ENOMEM; 506 } 507 return 0; 508 } 509 510 void sctp_sysctl_net_unregister(struct net *net) 511 { 512 struct ctl_table *table; 513 514 table = net->sctp.sysctl_header->ctl_table_arg; 515 unregister_net_sysctl_table(net->sctp.sysctl_header); 516 kfree(table); 517 } 518 519 static struct ctl_table_header *sctp_sysctl_header; 520 521 /* Sysctl registration. */ 522 void sctp_sysctl_register(void) 523 { 524 sctp_sysctl_header = register_net_sysctl(&init_net, "net/sctp", sctp_table); 525 } 526 527 /* Sysctl deregistration. */ 528 void sctp_sysctl_unregister(void) 529 { 530 unregister_net_sysctl_table(sctp_sysctl_header); 531 } 532