sysctl.c 12.3 KB
Newer Older
1
/* SCTP kernel implementation
L
Linus Torvalds 已提交
2 3 4
 * (C) Copyright IBM Corp. 2002, 2004
 * Copyright (c) 2002 Intel Corp.
 *
5
 * This file is part of the SCTP kernel implementation
L
Linus Torvalds 已提交
6 7 8
 *
 * Sysctl related interfaces for SCTP.
 *
9
 * This SCTP implementation is free software;
L
Linus Torvalds 已提交
10 11 12 13 14
 * you can redistribute it and/or modify it under the terms of
 * the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
15
 * This SCTP implementation is distributed in the hope that it
L
Linus Torvalds 已提交
16 17 18 19 20 21
 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
 *                 ************************
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
22 23
 * along with GNU CC; see the file COPYING.  If not, see
 * <http://www.gnu.org/licenses/>.
L
Linus Torvalds 已提交
24 25 26
 *
 * Please send any bug reports or fixes you make to the
 * email address(es):
27
 *    lksctp developers <linux-sctp@vger.kernel.org>
L
Linus Torvalds 已提交
28 29 30 31 32 33 34 35 36
 *
 * Written or modified by:
 *    Mingqin Liu           <liuming@us.ibm.com>
 *    Jon Grimm             <jgrimm@us.ibm.com>
 *    Ardelle Fan           <ardelle.fan@intel.com>
 *    Ryan Layer            <rmlayer@us.ibm.com>
 *    Sridhar Samudrala     <sri@us.ibm.com>
 */

37 38
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

L
Linus Torvalds 已提交
39
#include <net/sctp/structs.h>
40
#include <net/sctp/sctp.h>
L
Linus Torvalds 已提交
41 42
#include <linux/sysctl.h>

43 44 45 46
static int zero = 0;
static int one = 1;
static int timer_max = 86400000; /* ms in one day */
static int int_max = INT_MAX;
47 48
static int sack_timer_min = 1;
static int sack_timer_max = 500;
49
static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */
50
static int rwnd_scale_max = 16;
51 52 53 54 55
static int rto_alpha_min = 0;
static int rto_beta_min = 0;
static int rto_alpha_max = 1000;
static int rto_beta_max = 1000;

56 57 58 59
static unsigned long max_autoclose_min = 0;
static unsigned long max_autoclose_max =
	(MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX)
	? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ;
L
Linus Torvalds 已提交
60

E
Eric Dumazet 已提交
61
extern long sysctl_sctp_mem[3];
62 63
extern int sysctl_sctp_rmem[3];
extern int sysctl_sctp_wmem[3];
64

W
wangweidong 已提交
65
static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
66 67
				void __user *buffer, size_t *lenp,
				loff_t *ppos);
68 69 70 71
static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
				void __user *buffer, size_t *lenp,
				loff_t *ppos);
static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
72 73
				void __user *buffer, size_t *lenp,
				loff_t *ppos);
74 75 76
static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write,
				   void __user *buffer, size_t *lenp,
				   loff_t *ppos);
77 78 79
static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
			     void __user *buffer, size_t *lenp,
			     loff_t *ppos);
80

81
static struct ctl_table sctp_table[] = {
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
	{
		.procname	= "sctp_mem",
		.data		= &sysctl_sctp_mem,
		.maxlen		= sizeof(sysctl_sctp_mem),
		.mode		= 0644,
		.proc_handler	= proc_doulongvec_minmax
	},
	{
		.procname	= "sctp_rmem",
		.data		= &sysctl_sctp_rmem,
		.maxlen		= sizeof(sysctl_sctp_rmem),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "sctp_wmem",
		.data		= &sysctl_sctp_wmem,
		.maxlen		= sizeof(sysctl_sctp_wmem),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},

	{ /* sentinel */ }
};

107
static struct ctl_table sctp_net_table[] = {
L
Linus Torvalds 已提交
108 109
	{
		.procname	= "rto_initial",
110
		.data		= &init_net.sctp.rto_initial,
111
		.maxlen		= sizeof(unsigned int),
L
Linus Torvalds 已提交
112
		.mode		= 0644,
A
Alexey Dobriyan 已提交
113
		.proc_handler	= proc_dointvec_minmax,
114 115
		.extra1         = &one,
		.extra2         = &timer_max
L
Linus Torvalds 已提交
116 117 118
	},
	{
		.procname	= "rto_min",
119
		.data		= &init_net.sctp.rto_min,
120
		.maxlen		= sizeof(unsigned int),
L
Linus Torvalds 已提交
121
		.mode		= 0644,
122
		.proc_handler	= proc_sctp_do_rto_min,
123
		.extra1         = &one,
124
		.extra2         = &init_net.sctp.rto_max
L
Linus Torvalds 已提交
125 126 127
	},
	{
		.procname	= "rto_max",
128
		.data		= &init_net.sctp.rto_max,
129
		.maxlen		= sizeof(unsigned int),
L
Linus Torvalds 已提交
130
		.mode		= 0644,
131 132
		.proc_handler	= proc_sctp_do_rto_max,
		.extra1         = &init_net.sctp.rto_min,
133
		.extra2         = &timer_max
L
Linus Torvalds 已提交
134 135
	},
	{
136 137 138
		.procname	= "rto_alpha_exp_divisor",
		.data		= &init_net.sctp.rto_alpha,
		.maxlen		= sizeof(int),
139 140 141 142
		.mode		= 0644,
		.proc_handler	= proc_sctp_do_alpha_beta,
		.extra1		= &rto_alpha_min,
		.extra2		= &rto_alpha_max,
143 144 145 146 147
	},
	{
		.procname	= "rto_beta_exp_divisor",
		.data		= &init_net.sctp.rto_beta,
		.maxlen		= sizeof(int),
148 149 150 151
		.mode		= 0644,
		.proc_handler	= proc_sctp_do_alpha_beta,
		.extra1		= &rto_beta_min,
		.extra2		= &rto_beta_max,
L
Linus Torvalds 已提交
152 153 154
	},
	{
		.procname	= "max_burst",
155
		.data		= &init_net.sctp.max_burst,
L
Linus Torvalds 已提交
156 157
		.maxlen		= sizeof(int),
		.mode		= 0644,
A
Alexey Dobriyan 已提交
158
		.proc_handler	= proc_dointvec_minmax,
159 160
		.extra1		= &zero,
		.extra2		= &int_max
L
Linus Torvalds 已提交
161 162
	},
	{
163 164
		.procname	= "cookie_preserve_enable",
		.data		= &init_net.sctp.cookie_preserve_enable,
L
Linus Torvalds 已提交
165 166
		.maxlen		= sizeof(int),
		.mode		= 0644,
167 168
		.proc_handler	= proc_dointvec,
	},
169 170
	{
		.procname	= "cookie_hmac_alg",
171
		.data		= &init_net.sctp.sctp_hmac_alg,
172 173 174 175
		.maxlen		= 8,
		.mode		= 0644,
		.proc_handler	= proc_sctp_do_hmac_alg,
	},
176 177 178 179 180
	{
		.procname	= "valid_cookie_life",
		.data		= &init_net.sctp.valid_cookie_life,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
A
Alexey Dobriyan 已提交
181
		.proc_handler	= proc_dointvec_minmax,
182 183
		.extra1         = &one,
		.extra2         = &timer_max
L
Linus Torvalds 已提交
184
	},
185
	{
186 187
		.procname	= "sack_timeout",
		.data		= &init_net.sctp.sack_timeout,
188 189
		.maxlen		= sizeof(int),
		.mode		= 0644,
190 191 192
		.proc_handler	= proc_dointvec_minmax,
		.extra1         = &sack_timer_min,
		.extra2         = &sack_timer_max,
193
	},
194
	{
195 196 197
		.procname	= "hb_interval",
		.data		= &init_net.sctp.hb_interval,
		.maxlen		= sizeof(unsigned int),
198
		.mode		= 0644,
199 200 201
		.proc_handler	= proc_dointvec_minmax,
		.extra1         = &one,
		.extra2         = &timer_max
202
	},
L
Linus Torvalds 已提交
203
	{
204 205
		.procname	= "association_max_retrans",
		.data		= &init_net.sctp.max_retrans_association,
L
Linus Torvalds 已提交
206 207
		.maxlen		= sizeof(int),
		.mode		= 0644,
A
Alexey Dobriyan 已提交
208
		.proc_handler	= proc_dointvec_minmax,
209 210
		.extra1		= &one,
		.extra2		= &int_max
L
Linus Torvalds 已提交
211
	},
212
	{
213 214
		.procname	= "path_max_retrans",
		.data		= &init_net.sctp.max_retrans_path,
215 216 217
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
218
		.extra1		= &one,
219 220
		.extra2		= &int_max
	},
L
Linus Torvalds 已提交
221 222
	{
		.procname	= "max_init_retransmits",
223
		.data		= &init_net.sctp.max_retrans_init,
L
Linus Torvalds 已提交
224 225
		.maxlen		= sizeof(int),
		.mode		= 0644,
A
Alexey Dobriyan 已提交
226
		.proc_handler	= proc_dointvec_minmax,
227 228
		.extra1		= &one,
		.extra2		= &int_max
L
Linus Torvalds 已提交
229 230
	},
	{
231 232 233
		.procname	= "pf_retrans",
		.data		= &init_net.sctp.pf_retrans,
		.maxlen		= sizeof(int),
L
Linus Torvalds 已提交
234
		.mode		= 0644,
A
Alexey Dobriyan 已提交
235
		.proc_handler	= proc_dointvec_minmax,
236 237
		.extra1		= &zero,
		.extra2		= &int_max
L
Linus Torvalds 已提交
238 239
	},
	{
240 241
		.procname	= "sndbuf_policy",
		.data		= &init_net.sctp.sndbuf_policy,
242
		.maxlen		= sizeof(int),
L
Linus Torvalds 已提交
243
		.mode		= 0644,
A
Alexey Dobriyan 已提交
244
		.proc_handler	= proc_dointvec,
L
Linus Torvalds 已提交
245 246
	},
	{
247 248
		.procname	= "rcvbuf_policy",
		.data		= &init_net.sctp.rcvbuf_policy,
249 250 251 252 253 254
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "default_auto_asconf",
255
		.data		= &init_net.sctp.default_auto_asconf,
L
Linus Torvalds 已提交
256 257
		.maxlen		= sizeof(int),
		.mode		= 0644,
A
Alexey Dobriyan 已提交
258
		.proc_handler	= proc_dointvec,
L
Linus Torvalds 已提交
259 260
	},
	{
261 262
		.procname	= "addip_enable",
		.data		= &init_net.sctp.addip_enable,
L
Linus Torvalds 已提交
263 264
		.maxlen		= sizeof(int),
		.mode		= 0644,
A
Alexey Dobriyan 已提交
265
		.proc_handler	= proc_dointvec,
L
Linus Torvalds 已提交
266
	},
267
	{
268 269
		.procname	= "addip_noauth_enable",
		.data		= &init_net.sctp.addip_noauth,
270
		.maxlen		= sizeof(int),
271
		.mode		= 0644,
A
Alexey Dobriyan 已提交
272
		.proc_handler	= proc_dointvec,
273 274
	},
	{
275 276
		.procname	= "prsctp_enable",
		.data		= &init_net.sctp.prsctp_enable,
277 278
		.maxlen		= sizeof(int),
		.mode		= 0644,
A
Alexey Dobriyan 已提交
279
		.proc_handler	= proc_dointvec,
280
	},
281
	{
282 283
		.procname	= "auth_enable",
		.data		= &init_net.sctp.auth_enable,
284 285
		.maxlen		= sizeof(int),
		.mode		= 0644,
286
		.proc_handler	= proc_sctp_do_auth,
287
	},
288 289
	{
		.procname	= "addr_scope_policy",
290
		.data		= &init_net.sctp.scope_policy,
291 292
		.maxlen		= sizeof(int),
		.mode		= 0644,
293
		.proc_handler	= proc_dointvec_minmax,
294 295 296
		.extra1		= &zero,
		.extra2		= &addr_scope_max,
	},
297 298
	{
		.procname	= "rwnd_update_shift",
299
		.data		= &init_net.sctp.rwnd_upd_shift,
300 301 302 303 304 305
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= &proc_dointvec_minmax,
		.extra1		= &one,
		.extra2		= &rwnd_scale_max,
	},
306 307
	{
		.procname	= "max_autoclose",
308
		.data		= &init_net.sctp.max_autoclose,
309 310 311 312 313 314
		.maxlen		= sizeof(unsigned long),
		.mode		= 0644,
		.proc_handler	= &proc_doulongvec_minmax,
		.extra1		= &max_autoclose_min,
		.extra2		= &max_autoclose_max,
	},
315

316
	{ /* sentinel */ }
L
Linus Torvalds 已提交
317 318
};

W
wangweidong 已提交
319
static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
320 321 322 323
				void __user *buffer, size_t *lenp,
				loff_t *ppos)
{
	struct net *net = current->nsproxy->net_ns;
324
	struct ctl_table tbl;
325
	bool changed = false;
326
	char *none = "none";
327 328
	char tmp[8];
	int ret;
329 330 331 332 333

	memset(&tbl, 0, sizeof(struct ctl_table));

	if (write) {
		tbl.data = tmp;
334
		tbl.maxlen = sizeof(tmp);
335 336 337 338 339
	} else {
		tbl.data = net->sctp.sctp_hmac_alg ? : none;
		tbl.maxlen = strlen(tbl.data);
	}

340 341
	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
	if (write && ret == 0) {
342 343 344
#ifdef CONFIG_CRYPTO_MD5
		if (!strncmp(tmp, "md5", 3)) {
			net->sctp.sctp_hmac_alg = "md5";
345
			changed = true;
346 347 348 349 350
		}
#endif
#ifdef CONFIG_CRYPTO_SHA1
		if (!strncmp(tmp, "sha1", 4)) {
			net->sctp.sctp_hmac_alg = "sha1";
351
			changed = true;
352 353 354 355
		}
#endif
		if (!strncmp(tmp, "none", 4)) {
			net->sctp.sctp_hmac_alg = NULL;
356
			changed = true;
357 358 359 360 361 362 363 364
		}
		if (!changed)
			ret = -EINVAL;
	}

	return ret;
}

365 366 367 368 369 370 371
static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
				void __user *buffer, size_t *lenp,
				loff_t *ppos)
{
	struct net *net = current->nsproxy->net_ns;
	unsigned int min = *(unsigned int *) ctl->extra1;
	unsigned int max = *(unsigned int *) ctl->extra2;
372 373
	struct ctl_table tbl;
	int ret, new_value;
374 375 376 377 378 379 380 381

	memset(&tbl, 0, sizeof(struct ctl_table));
	tbl.maxlen = sizeof(unsigned int);

	if (write)
		tbl.data = &new_value;
	else
		tbl.data = &net->sctp.rto_min;
382

383
	ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
384 385
	if (write && ret == 0) {
		if (new_value > max || new_value < min)
386
			return -EINVAL;
387

388 389
		net->sctp.rto_min = new_value;
	}
390

391 392 393 394 395 396 397 398 399 400
	return ret;
}

static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
				void __user *buffer, size_t *lenp,
				loff_t *ppos)
{
	struct net *net = current->nsproxy->net_ns;
	unsigned int min = *(unsigned int *) ctl->extra1;
	unsigned int max = *(unsigned int *) ctl->extra2;
401 402
	struct ctl_table tbl;
	int ret, new_value;
403 404 405 406 407 408 409 410

	memset(&tbl, 0, sizeof(struct ctl_table));
	tbl.maxlen = sizeof(unsigned int);

	if (write)
		tbl.data = &new_value;
	else
		tbl.data = &net->sctp.rto_max;
411

412
	ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
413 414
	if (write && ret == 0) {
		if (new_value > max || new_value < min)
415
			return -EINVAL;
416

417 418
		net->sctp.rto_max = new_value;
	}
419

420 421 422
	return ret;
}

423 424 425 426
static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write,
				   void __user *buffer, size_t *lenp,
				   loff_t *ppos)
{
427 428 429
	if (write)
		pr_warn_once("Changing rto_alpha or rto_beta may lead to "
			     "suboptimal rtt/srtt estimations!\n");
430 431 432 433

	return proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
}

434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
			     void __user *buffer, size_t *lenp,
			     loff_t *ppos)
{
	struct net *net = current->nsproxy->net_ns;
	struct ctl_table tbl;
	int new_value, ret;

	memset(&tbl, 0, sizeof(struct ctl_table));
	tbl.maxlen = sizeof(unsigned int);

	if (write)
		tbl.data = &new_value;
	else
		tbl.data = &net->sctp.auth_enable;

	ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
451
	if (write && ret == 0) {
452 453 454 455 456 457 458 459 460 461 462 463
		struct sock *sk = net->sctp.ctl_sock;

		net->sctp.auth_enable = new_value;
		/* Update the value in the control socket */
		lock_sock(sk);
		sctp_sk(sk)->ep->auth_enable = new_value;
		release_sock(sk);
	}

	return ret;
}

464 465
int sctp_sysctl_net_register(struct net *net)
{
466 467
	struct ctl_table *table;
	int i;
468

469 470 471
	table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
	if (!table)
		return -ENOMEM;
472

473 474
	for (i = 0; table[i].data; i++)
		table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp;
475

476
	net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table);
477 478 479 480
	if (net->sctp.sysctl_header == NULL) {
		kfree(table);
		return -ENOMEM;
	}
481 482 483 484 485
	return 0;
}

void sctp_sysctl_net_unregister(struct net *net)
{
486 487 488
	struct ctl_table *table;

	table = net->sctp.sysctl_header->ctl_table_arg;
489
	unregister_net_sysctl_table(net->sctp.sysctl_header);
490
	kfree(table);
491 492
}

493
static struct ctl_table_header *sctp_sysctl_header;
L
Linus Torvalds 已提交
494 495 496 497

/* Sysctl registration.  */
void sctp_sysctl_register(void)
{
498
	sctp_sysctl_header = register_net_sysctl(&init_net, "net/sctp", sctp_table);
L
Linus Torvalds 已提交
499 500 501 502 503
}

/* Sysctl deregistration.  */
void sctp_sysctl_unregister(void)
{
504
	unregister_net_sysctl_table(sctp_sysctl_header);
L
Linus Torvalds 已提交
505
}