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