sysctl.c (15303B)
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 28static int timer_max = 86400000; /* ms in one day */ 29static int sack_timer_min = 1; 30static int sack_timer_max = 500; 31static int addr_scope_max = SCTP_SCOPE_POLICY_MAX; 32static int rwnd_scale_max = 16; 33static int rto_alpha_min = 0; 34static int rto_beta_min = 0; 35static int rto_alpha_max = 1000; 36static int rto_beta_max = 1000; 37static int pf_expose_max = SCTP_PF_EXPOSE_MAX; 38static int ps_retrans_max = SCTP_PS_RETRANS_MAX; 39static int udp_port_max = 65535; 40 41static unsigned long max_autoclose_min = 0; 42static unsigned long max_autoclose_max = 43 (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX) 44 ? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ; 45 46static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, 47 void *buffer, size_t *lenp, loff_t *ppos); 48static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, 49 void *buffer, size_t *lenp, loff_t *ppos); 50static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, void *buffer, 51 size_t *lenp, loff_t *ppos); 52static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write, void *buffer, 53 size_t *lenp, loff_t *ppos); 54static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write, 55 void *buffer, size_t *lenp, loff_t *ppos); 56static int proc_sctp_do_auth(struct ctl_table *ctl, int write, 57 void *buffer, size_t *lenp, loff_t *ppos); 58static int proc_sctp_do_probe_interval(struct ctl_table *ctl, int write, 59 void *buffer, size_t *lenp, loff_t *ppos); 60 61static 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 87static 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 = "plpmtud_probe_interval", 300 .data = &init_net.sctp.probe_interval, 301 .maxlen = sizeof(int), 302 .mode = 0644, 303 .proc_handler = proc_sctp_do_probe_interval, 304 }, 305 { 306 .procname = "udp_port", 307 .data = &init_net.sctp.udp_port, 308 .maxlen = sizeof(int), 309 .mode = 0644, 310 .proc_handler = proc_sctp_do_udp_port, 311 .extra1 = SYSCTL_ZERO, 312 .extra2 = &udp_port_max, 313 }, 314 { 315 .procname = "encap_port", 316 .data = &init_net.sctp.encap_port, 317 .maxlen = sizeof(int), 318 .mode = 0644, 319 .proc_handler = proc_dointvec_minmax, 320 .extra1 = SYSCTL_ZERO, 321 .extra2 = &udp_port_max, 322 }, 323 { 324 .procname = "addr_scope_policy", 325 .data = &init_net.sctp.scope_policy, 326 .maxlen = sizeof(int), 327 .mode = 0644, 328 .proc_handler = proc_dointvec_minmax, 329 .extra1 = SYSCTL_ZERO, 330 .extra2 = &addr_scope_max, 331 }, 332 { 333 .procname = "rwnd_update_shift", 334 .data = &init_net.sctp.rwnd_upd_shift, 335 .maxlen = sizeof(int), 336 .mode = 0644, 337 .proc_handler = &proc_dointvec_minmax, 338 .extra1 = SYSCTL_ONE, 339 .extra2 = &rwnd_scale_max, 340 }, 341 { 342 .procname = "max_autoclose", 343 .data = &init_net.sctp.max_autoclose, 344 .maxlen = sizeof(unsigned long), 345 .mode = 0644, 346 .proc_handler = &proc_doulongvec_minmax, 347 .extra1 = &max_autoclose_min, 348 .extra2 = &max_autoclose_max, 349 }, 350 { 351 .procname = "pf_enable", 352 .data = &init_net.sctp.pf_enable, 353 .maxlen = sizeof(int), 354 .mode = 0644, 355 .proc_handler = proc_dointvec, 356 }, 357 { 358 .procname = "pf_expose", 359 .data = &init_net.sctp.pf_expose, 360 .maxlen = sizeof(int), 361 .mode = 0644, 362 .proc_handler = proc_dointvec_minmax, 363 .extra1 = SYSCTL_ZERO, 364 .extra2 = &pf_expose_max, 365 }, 366 367 { /* sentinel */ } 368}; 369 370static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, 371 void *buffer, size_t *lenp, loff_t *ppos) 372{ 373 struct net *net = current->nsproxy->net_ns; 374 struct ctl_table tbl; 375 bool changed = false; 376 char *none = "none"; 377 char tmp[8] = {0}; 378 int ret; 379 380 memset(&tbl, 0, sizeof(struct ctl_table)); 381 382 if (write) { 383 tbl.data = tmp; 384 tbl.maxlen = sizeof(tmp); 385 } else { 386 tbl.data = net->sctp.sctp_hmac_alg ? : none; 387 tbl.maxlen = strlen(tbl.data); 388 } 389 390 ret = proc_dostring(&tbl, write, buffer, lenp, ppos); 391 if (write && ret == 0) { 392#ifdef CONFIG_CRYPTO_MD5 393 if (!strncmp(tmp, "md5", 3)) { 394 net->sctp.sctp_hmac_alg = "md5"; 395 changed = true; 396 } 397#endif 398#ifdef CONFIG_CRYPTO_SHA1 399 if (!strncmp(tmp, "sha1", 4)) { 400 net->sctp.sctp_hmac_alg = "sha1"; 401 changed = true; 402 } 403#endif 404 if (!strncmp(tmp, "none", 4)) { 405 net->sctp.sctp_hmac_alg = NULL; 406 changed = true; 407 } 408 if (!changed) 409 ret = -EINVAL; 410 } 411 412 return ret; 413} 414 415static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, 416 void *buffer, size_t *lenp, loff_t *ppos) 417{ 418 struct net *net = current->nsproxy->net_ns; 419 unsigned int min = *(unsigned int *) ctl->extra1; 420 unsigned int max = *(unsigned int *) ctl->extra2; 421 struct ctl_table tbl; 422 int ret, new_value; 423 424 memset(&tbl, 0, sizeof(struct ctl_table)); 425 tbl.maxlen = sizeof(unsigned int); 426 427 if (write) 428 tbl.data = &new_value; 429 else 430 tbl.data = &net->sctp.rto_min; 431 432 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 433 if (write && ret == 0) { 434 if (new_value > max || new_value < min) 435 return -EINVAL; 436 437 net->sctp.rto_min = new_value; 438 } 439 440 return ret; 441} 442 443static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, 444 void *buffer, size_t *lenp, loff_t *ppos) 445{ 446 struct net *net = current->nsproxy->net_ns; 447 unsigned int min = *(unsigned int *) ctl->extra1; 448 unsigned int max = *(unsigned int *) ctl->extra2; 449 struct ctl_table tbl; 450 int ret, new_value; 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.rto_max; 459 460 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 461 if (write && ret == 0) { 462 if (new_value > max || new_value < min) 463 return -EINVAL; 464 465 net->sctp.rto_max = new_value; 466 } 467 468 return ret; 469} 470 471static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write, 472 void *buffer, size_t *lenp, loff_t *ppos) 473{ 474 if (write) 475 pr_warn_once("Changing rto_alpha or rto_beta may lead to " 476 "suboptimal rtt/srtt estimations!\n"); 477 478 return proc_dointvec_minmax(ctl, write, buffer, lenp, ppos); 479} 480 481static int proc_sctp_do_auth(struct ctl_table *ctl, int write, 482 void *buffer, size_t *lenp, loff_t *ppos) 483{ 484 struct net *net = current->nsproxy->net_ns; 485 struct ctl_table tbl; 486 int new_value, ret; 487 488 memset(&tbl, 0, sizeof(struct ctl_table)); 489 tbl.maxlen = sizeof(unsigned int); 490 491 if (write) 492 tbl.data = &new_value; 493 else 494 tbl.data = &net->sctp.auth_enable; 495 496 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 497 if (write && ret == 0) { 498 struct sock *sk = net->sctp.ctl_sock; 499 500 net->sctp.auth_enable = new_value; 501 /* Update the value in the control socket */ 502 lock_sock(sk); 503 sctp_sk(sk)->ep->auth_enable = new_value; 504 release_sock(sk); 505 } 506 507 return ret; 508} 509 510static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write, 511 void *buffer, size_t *lenp, loff_t *ppos) 512{ 513 struct net *net = current->nsproxy->net_ns; 514 unsigned int min = *(unsigned int *)ctl->extra1; 515 unsigned int max = *(unsigned int *)ctl->extra2; 516 struct ctl_table tbl; 517 int ret, new_value; 518 519 memset(&tbl, 0, sizeof(struct ctl_table)); 520 tbl.maxlen = sizeof(unsigned int); 521 522 if (write) 523 tbl.data = &new_value; 524 else 525 tbl.data = &net->sctp.udp_port; 526 527 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 528 if (write && ret == 0) { 529 struct sock *sk = net->sctp.ctl_sock; 530 531 if (new_value > max || new_value < min) 532 return -EINVAL; 533 534 net->sctp.udp_port = new_value; 535 sctp_udp_sock_stop(net); 536 if (new_value) { 537 ret = sctp_udp_sock_start(net); 538 if (ret) 539 net->sctp.udp_port = 0; 540 } 541 542 /* Update the value in the control socket */ 543 lock_sock(sk); 544 sctp_sk(sk)->udp_port = htons(net->sctp.udp_port); 545 release_sock(sk); 546 } 547 548 return ret; 549} 550 551static int proc_sctp_do_probe_interval(struct ctl_table *ctl, int write, 552 void *buffer, size_t *lenp, loff_t *ppos) 553{ 554 struct net *net = current->nsproxy->net_ns; 555 struct ctl_table tbl; 556 int ret, new_value; 557 558 memset(&tbl, 0, sizeof(struct ctl_table)); 559 tbl.maxlen = sizeof(unsigned int); 560 561 if (write) 562 tbl.data = &new_value; 563 else 564 tbl.data = &net->sctp.probe_interval; 565 566 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 567 if (write && ret == 0) { 568 if (new_value && new_value < SCTP_PROBE_TIMER_MIN) 569 return -EINVAL; 570 571 net->sctp.probe_interval = new_value; 572 } 573 574 return ret; 575} 576 577int sctp_sysctl_net_register(struct net *net) 578{ 579 struct ctl_table *table; 580 int i; 581 582 table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); 583 if (!table) 584 return -ENOMEM; 585 586 for (i = 0; table[i].data; i++) 587 table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; 588 589 net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); 590 if (net->sctp.sysctl_header == NULL) { 591 kfree(table); 592 return -ENOMEM; 593 } 594 return 0; 595} 596 597void sctp_sysctl_net_unregister(struct net *net) 598{ 599 struct ctl_table *table; 600 601 table = net->sctp.sysctl_header->ctl_table_arg; 602 unregister_net_sysctl_table(net->sctp.sysctl_header); 603 kfree(table); 604} 605 606static struct ctl_table_header *sctp_sysctl_header; 607 608/* Sysctl registration. */ 609void sctp_sysctl_register(void) 610{ 611 sctp_sysctl_header = register_net_sysctl(&init_net, "net/sctp", sctp_table); 612} 613 614/* Sysctl deregistration. */ 615void sctp_sysctl_unregister(void) 616{ 617 unregister_net_sysctl_table(sctp_sysctl_header); 618}