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, int write, 60 void __user *buffer, size_t *lenp, 61 loff_t *ppos); 62 static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, 63 void __user *buffer, size_t *lenp, 64 loff_t *ppos); 65 static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, 66 void __user *buffer, size_t *lenp, 67 loff_t *ppos); 68 69 static struct ctl_table sctp_table[] = { 70 { 71 .procname = "sctp_mem", 72 .data = &sysctl_sctp_mem, 73 .maxlen = sizeof(sysctl_sctp_mem), 74 .mode = 0644, 75 .proc_handler = proc_doulongvec_minmax 76 }, 77 { 78 .procname = "sctp_rmem", 79 .data = &sysctl_sctp_rmem, 80 .maxlen = sizeof(sysctl_sctp_rmem), 81 .mode = 0644, 82 .proc_handler = proc_dointvec, 83 }, 84 { 85 .procname = "sctp_wmem", 86 .data = &sysctl_sctp_wmem, 87 .maxlen = sizeof(sysctl_sctp_wmem), 88 .mode = 0644, 89 .proc_handler = proc_dointvec, 90 }, 91 92 { /* sentinel */ } 93 }; 94 95 static struct ctl_table sctp_net_table[] = { 96 { 97 .procname = "rto_initial", 98 .data = &init_net.sctp.rto_initial, 99 .maxlen = sizeof(unsigned int), 100 .mode = 0644, 101 .proc_handler = proc_dointvec_minmax, 102 .extra1 = &one, 103 .extra2 = &timer_max 104 }, 105 { 106 .procname = "rto_min", 107 .data = &init_net.sctp.rto_min, 108 .maxlen = sizeof(unsigned int), 109 .mode = 0644, 110 .proc_handler = proc_sctp_do_rto_min, 111 .extra1 = &one, 112 .extra2 = &init_net.sctp.rto_max 113 }, 114 { 115 .procname = "rto_max", 116 .data = &init_net.sctp.rto_max, 117 .maxlen = sizeof(unsigned int), 118 .mode = 0644, 119 .proc_handler = proc_sctp_do_rto_max, 120 .extra1 = &init_net.sctp.rto_min, 121 .extra2 = &timer_max 122 }, 123 { 124 .procname = "rto_alpha_exp_divisor", 125 .data = &init_net.sctp.rto_alpha, 126 .maxlen = sizeof(int), 127 .mode = 0444, 128 .proc_handler = proc_dointvec, 129 }, 130 { 131 .procname = "rto_beta_exp_divisor", 132 .data = &init_net.sctp.rto_beta, 133 .maxlen = sizeof(int), 134 .mode = 0444, 135 .proc_handler = proc_dointvec, 136 }, 137 { 138 .procname = "max_burst", 139 .data = &init_net.sctp.max_burst, 140 .maxlen = sizeof(int), 141 .mode = 0644, 142 .proc_handler = proc_dointvec_minmax, 143 .extra1 = &zero, 144 .extra2 = &int_max 145 }, 146 { 147 .procname = "cookie_preserve_enable", 148 .data = &init_net.sctp.cookie_preserve_enable, 149 .maxlen = sizeof(int), 150 .mode = 0644, 151 .proc_handler = proc_dointvec, 152 }, 153 { 154 .procname = "cookie_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