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