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