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