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