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 43static int zero = 0; 44static int one = 1; 45static int timer_max = 86400000; /* ms in one day */ 46static int int_max = INT_MAX; 47static int sack_timer_min = 1; 48static int sack_timer_max = 500; 49static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */ 50static int rwnd_scale_max = 16; 51static int rto_alpha_min = 0; 52static int rto_beta_min = 0; 53static int rto_alpha_max = 1000; 54static int rto_beta_max = 1000; 55 56static unsigned long max_autoclose_min = 0; 57static unsigned long max_autoclose_max = 58 (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX) 59 ? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ; 60 61static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, 62 void __user *buffer, size_t *lenp, 63 loff_t *ppos); 64static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, 65 void __user *buffer, size_t *lenp, 66 loff_t *ppos); 67static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, 68 void __user *buffer, size_t *lenp, 69 loff_t *ppos); 70static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write, 71 void __user *buffer, size_t *lenp, 72 loff_t *ppos); 73static int proc_sctp_do_auth(struct ctl_table *ctl, int write, 74 void __user *buffer, size_t *lenp, 75 loff_t *ppos); 76 77static 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 103static 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 { /* sentinel */ } 313}; 314 315static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, 316 void __user *buffer, size_t *lenp, 317 loff_t *ppos) 318{ 319 struct net *net = current->nsproxy->net_ns; 320 struct ctl_table tbl; 321 bool changed = false; 322 char *none = "none"; 323 char tmp[8] = {0}; 324 int ret; 325 326 memset(&tbl, 0, sizeof(struct ctl_table)); 327 328 if (write) { 329 tbl.data = tmp; 330 tbl.maxlen = sizeof(tmp); 331 } else { 332 tbl.data = net->sctp.sctp_hmac_alg ? : none; 333 tbl.maxlen = strlen(tbl.data); 334 } 335 336 ret = proc_dostring(&tbl, write, buffer, lenp, ppos); 337 if (write && ret == 0) { 338#ifdef CONFIG_CRYPTO_MD5 339 if (!strncmp(tmp, "md5", 3)) { 340 net->sctp.sctp_hmac_alg = "md5"; 341 changed = true; 342 } 343#endif 344#ifdef CONFIG_CRYPTO_SHA1 345 if (!strncmp(tmp, "sha1", 4)) { 346 net->sctp.sctp_hmac_alg = "sha1"; 347 changed = true; 348 } 349#endif 350 if (!strncmp(tmp, "none", 4)) { 351 net->sctp.sctp_hmac_alg = NULL; 352 changed = true; 353 } 354 if (!changed) 355 ret = -EINVAL; 356 } 357 358 return ret; 359} 360 361static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, 362 void __user *buffer, size_t *lenp, 363 loff_t *ppos) 364{ 365 struct net *net = current->nsproxy->net_ns; 366 unsigned int min = *(unsigned int *) ctl->extra1; 367 unsigned int max = *(unsigned int *) ctl->extra2; 368 struct ctl_table tbl; 369 int ret, new_value; 370 371 memset(&tbl, 0, sizeof(struct ctl_table)); 372 tbl.maxlen = sizeof(unsigned int); 373 374 if (write) 375 tbl.data = &new_value; 376 else 377 tbl.data = &net->sctp.rto_min; 378 379 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 380 if (write && ret == 0) { 381 if (new_value > max || new_value < min) 382 return -EINVAL; 383 384 net->sctp.rto_min = new_value; 385 } 386 387 return ret; 388} 389 390static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, 391 void __user *buffer, size_t *lenp, 392 loff_t *ppos) 393{ 394 struct net *net = current->nsproxy->net_ns; 395 unsigned int min = *(unsigned int *) ctl->extra1; 396 unsigned int max = *(unsigned int *) ctl->extra2; 397 struct ctl_table tbl; 398 int ret, new_value; 399 400 memset(&tbl, 0, sizeof(struct ctl_table)); 401 tbl.maxlen = sizeof(unsigned int); 402 403 if (write) 404 tbl.data = &new_value; 405 else 406 tbl.data = &net->sctp.rto_max; 407 408 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 409 if (write && ret == 0) { 410 if (new_value > max || new_value < min) 411 return -EINVAL; 412 413 net->sctp.rto_max = new_value; 414 } 415 416 return ret; 417} 418 419static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write, 420 void __user *buffer, size_t *lenp, 421 loff_t *ppos) 422{ 423 if (write) 424 pr_warn_once("Changing rto_alpha or rto_beta may lead to " 425 "suboptimal rtt/srtt estimations!\n"); 426 427 return proc_dointvec_minmax(ctl, write, buffer, lenp, ppos); 428} 429 430static int proc_sctp_do_auth(struct ctl_table *ctl, int write, 431 void __user *buffer, size_t *lenp, 432 loff_t *ppos) 433{ 434 struct net *net = current->nsproxy->net_ns; 435 struct ctl_table tbl; 436 int new_value, ret; 437 438 memset(&tbl, 0, sizeof(struct ctl_table)); 439 tbl.maxlen = sizeof(unsigned int); 440 441 if (write) 442 tbl.data = &new_value; 443 else 444 tbl.data = &net->sctp.auth_enable; 445 446 ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); 447 if (write && ret == 0) { 448 struct sock *sk = net->sctp.ctl_sock; 449 450 net->sctp.auth_enable = new_value; 451 /* Update the value in the control socket */ 452 lock_sock(sk); 453 sctp_sk(sk)->ep->auth_enable = new_value; 454 release_sock(sk); 455 } 456 457 return ret; 458} 459 460int sctp_sysctl_net_register(struct net *net) 461{ 462 struct ctl_table *table; 463 int i; 464 465 table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); 466 if (!table) 467 return -ENOMEM; 468 469 for (i = 0; table[i].data; i++) 470 table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; 471 472 net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); 473 if (net->sctp.sysctl_header == NULL) { 474 kfree(table); 475 return -ENOMEM; 476 } 477 return 0; 478} 479 480void sctp_sysctl_net_unregister(struct net *net) 481{ 482 struct ctl_table *table; 483 484 table = net->sctp.sysctl_header->ctl_table_arg; 485 unregister_net_sysctl_table(net->sctp.sysctl_header); 486 kfree(table); 487} 488 489static struct ctl_table_header *sctp_sysctl_header; 490 491/* Sysctl registration. */ 492void sctp_sysctl_register(void) 493{ 494 sctp_sysctl_header = register_net_sysctl(&init_net, "net/sctp", sctp_table); 495} 496 497/* Sysctl deregistration. */ 498void sctp_sysctl_unregister(void) 499{ 500 unregister_net_sysctl_table(sctp_sysctl_header); 501} 502