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