Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * DECnet       An implementation of the DECnet protocol suite for the LINUX
  4 *              operating system.  DECnet is implemented using the  BSD Socket
  5 *              interface as the means of communication with the user level.
  6 *
  7 *              DECnet sysctl support functions
  8 *
  9 * Author:      Steve Whitehouse <SteveW@ACM.org>
 10 *
 11 *
 12 * Changes:
 13 * Steve Whitehouse - C99 changes and default device handling
 14 * Steve Whitehouse - Memory buffer settings, like the tcp ones
 15 *
 16 */
 17#include <linux/mm.h>
 18#include <linux/sysctl.h>
 19#include <linux/fs.h>
 20#include <linux/netdevice.h>
 21#include <linux/string.h>
 22#include <net/neighbour.h>
 23#include <net/dst.h>
 24#include <net/flow.h>
 25
 26#include <linux/uaccess.h>
 27
 28#include <net/dn.h>
 29#include <net/dn_dev.h>
 30#include <net/dn_route.h>
 31
 32
 33int decnet_debug_level;
 34int decnet_time_wait = 30;
 35int decnet_dn_count = 1;
 36int decnet_di_count = 3;
 37int decnet_dr_count = 3;
 38int decnet_log_martians = 1;
 39int decnet_no_fc_max_cwnd = NSP_MIN_WINDOW;
 40
 41/* Reasonable defaults, I hope, based on tcp's defaults */
 42long sysctl_decnet_mem[3] = { 768 << 3, 1024 << 3, 1536 << 3 };
 43int sysctl_decnet_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
 44int sysctl_decnet_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
 45
 46#ifdef CONFIG_SYSCTL
 47extern int decnet_dst_gc_interval;
 48static int min_decnet_time_wait[] = { 5 };
 49static int max_decnet_time_wait[] = { 600 };
 50static int min_state_count[] = { 1 };
 51static int max_state_count[] = { NSP_MAXRXTSHIFT };
 52static int min_decnet_dst_gc_interval[] = { 1 };
 53static int max_decnet_dst_gc_interval[] = { 60 };
 54static int min_decnet_no_fc_max_cwnd[] = { NSP_MIN_WINDOW };
 55static int max_decnet_no_fc_max_cwnd[] = { NSP_MAX_WINDOW };
 56static char node_name[7] = "???";
 57
 58static struct ctl_table_header *dn_table_header = NULL;
 59
 60/*
 61 * ctype.h :-)
 62 */
 63#define ISNUM(x) (((x) >= '0') && ((x) <= '9'))
 64#define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
 65#define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
 66#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
 67#define INVALID_END_CHAR(x) (ISNUM(x) || ISALPHA(x))
 68
 69static void strip_it(char *str)
 70{
 71	for(;;) {
 72		switch (*str) {
 73		case ' ':
 74		case '\n':
 75		case '\r':
 76		case ':':
 77			*str = 0;
 78			fallthrough;
 79		case 0:
 80			return;
 81		}
 82		str++;
 83	}
 84}
 85
 86/*
 87 * Simple routine to parse an ascii DECnet address
 88 * into a network order address.
 89 */
 90static int parse_addr(__le16 *addr, char *str)
 91{
 92	__u16 area, node;
 93
 94	while(*str && !ISNUM(*str)) str++;
 95
 96	if (*str == 0)
 97		return -1;
 98
 99	area = (*str++ - '0');
100	if (ISNUM(*str)) {
101		area *= 10;
102		area += (*str++ - '0');
103	}
104
105	if (*str++ != '.')
106		return -1;
107
108	if (!ISNUM(*str))
109		return -1;
110
111	node = *str++ - '0';
112	if (ISNUM(*str)) {
113		node *= 10;
114		node += (*str++ - '0');
115	}
116	if (ISNUM(*str)) {
117		node *= 10;
118		node += (*str++ - '0');
119	}
120	if (ISNUM(*str)) {
121		node *= 10;
122		node += (*str++ - '0');
123	}
124
125	if ((node > 1023) || (area > 63))
126		return -1;
127
128	if (INVALID_END_CHAR(*str))
129		return -1;
130
131	*addr = cpu_to_le16((area << 10) | node);
132
133	return 0;
134}
135
136static int dn_node_address_handler(struct ctl_table *table, int write,
137		void *buffer, size_t *lenp, loff_t *ppos)
138{
139	char addr[DN_ASCBUF_LEN];
140	size_t len;
141	__le16 dnaddr;
142
143	if (!*lenp || (*ppos && !write)) {
144		*lenp = 0;
145		return 0;
146	}
147
148	if (write) {
149		len = (*lenp < DN_ASCBUF_LEN) ? *lenp : (DN_ASCBUF_LEN-1);
150		memcpy(addr, buffer, len);
151		addr[len] = 0;
152		strip_it(addr);
153
154		if (parse_addr(&dnaddr, addr))
155			return -EINVAL;
156
157		dn_dev_devices_off();
158
159		decnet_address = dnaddr;
160
161		dn_dev_devices_on();
162
163		*ppos += len;
164
165		return 0;
166	}
167
168	dn_addr2asc(le16_to_cpu(decnet_address), addr);
169	len = strlen(addr);
170	addr[len++] = '\n';
171
172	if (len > *lenp)
173		len = *lenp;
174	memcpy(buffer, addr, len);
175	*lenp = len;
176	*ppos += len;
177
178	return 0;
179}
180
181static int dn_def_dev_handler(struct ctl_table *table, int write,
182		void *buffer, size_t *lenp, loff_t *ppos)
183{
184	size_t len;
185	struct net_device *dev;
186	char devname[17];
187
188	if (!*lenp || (*ppos && !write)) {
189		*lenp = 0;
190		return 0;
191	}
192
193	if (write) {
194		if (*lenp > 16)
195			return -E2BIG;
196
197		memcpy(devname, buffer, *lenp);
198		devname[*lenp] = 0;
199		strip_it(devname);
200
201		dev = dev_get_by_name(&init_net, devname);
202		if (dev == NULL)
203			return -ENODEV;
204
205		if (dev->dn_ptr == NULL) {
206			dev_put(dev);
207			return -ENODEV;
208		}
209
210		if (dn_dev_set_default(dev, 1)) {
211			dev_put(dev);
212			return -ENODEV;
213		}
214		*ppos += *lenp;
215
216		return 0;
217	}
218
219	dev = dn_dev_get_default();
220	if (dev == NULL) {
221		*lenp = 0;
222		return 0;
223	}
224
225	strcpy(devname, dev->name);
226	dev_put(dev);
227	len = strlen(devname);
228	devname[len++] = '\n';
229
230	if (len > *lenp) len = *lenp;
231
232	memcpy(buffer, devname, len);
233	*lenp = len;
234	*ppos += len;
235
236	return 0;
237}
238
239static struct ctl_table dn_table[] = {
240	{
241		.procname = "node_address",
242		.maxlen = 7,
243		.mode = 0644,
244		.proc_handler = dn_node_address_handler,
245	},
246	{
247		.procname = "node_name",
248		.data = node_name,
249		.maxlen = 7,
250		.mode = 0644,
251		.proc_handler = proc_dostring,
252	},
253	{
254		.procname = "default_device",
255		.maxlen = 16,
256		.mode = 0644,
257		.proc_handler = dn_def_dev_handler,
258	},
259	{
260		.procname = "time_wait",
261		.data = &decnet_time_wait,
262		.maxlen = sizeof(int),
263		.mode = 0644,
264		.proc_handler = proc_dointvec_minmax,
265		.extra1 = &min_decnet_time_wait,
266		.extra2 = &max_decnet_time_wait
267	},
268	{
269		.procname = "dn_count",
270		.data = &decnet_dn_count,
271		.maxlen = sizeof(int),
272		.mode = 0644,
273		.proc_handler = proc_dointvec_minmax,
274		.extra1 = &min_state_count,
275		.extra2 = &max_state_count
276	},
277	{
278		.procname = "di_count",
279		.data = &decnet_di_count,
280		.maxlen = sizeof(int),
281		.mode = 0644,
282		.proc_handler = proc_dointvec_minmax,
283		.extra1 = &min_state_count,
284		.extra2 = &max_state_count
285	},
286	{
287		.procname = "dr_count",
288		.data = &decnet_dr_count,
289		.maxlen = sizeof(int),
290		.mode = 0644,
291		.proc_handler = proc_dointvec_minmax,
292		.extra1 = &min_state_count,
293		.extra2 = &max_state_count
294	},
295	{
296		.procname = "dst_gc_interval",
297		.data = &decnet_dst_gc_interval,
298		.maxlen = sizeof(int),
299		.mode = 0644,
300		.proc_handler = proc_dointvec_minmax,
301		.extra1 = &min_decnet_dst_gc_interval,
302		.extra2 = &max_decnet_dst_gc_interval
303	},
304	{
305		.procname = "no_fc_max_cwnd",
306		.data = &decnet_no_fc_max_cwnd,
307		.maxlen = sizeof(int),
308		.mode = 0644,
309		.proc_handler = proc_dointvec_minmax,
310		.extra1 = &min_decnet_no_fc_max_cwnd,
311		.extra2 = &max_decnet_no_fc_max_cwnd
312	},
313       {
314		.procname = "decnet_mem",
315		.data = &sysctl_decnet_mem,
316		.maxlen = sizeof(sysctl_decnet_mem),
317		.mode = 0644,
318		.proc_handler = proc_doulongvec_minmax
319	},
320	{
321		.procname = "decnet_rmem",
322		.data = &sysctl_decnet_rmem,
323		.maxlen = sizeof(sysctl_decnet_rmem),
324		.mode = 0644,
325		.proc_handler = proc_dointvec,
326	},
327	{
328		.procname = "decnet_wmem",
329		.data = &sysctl_decnet_wmem,
330		.maxlen = sizeof(sysctl_decnet_wmem),
331		.mode = 0644,
332		.proc_handler = proc_dointvec,
333	},
334	{
335		.procname = "debug",
336		.data = &decnet_debug_level,
337		.maxlen = sizeof(int),
338		.mode = 0644,
339		.proc_handler = proc_dointvec,
340	},
341	{ }
342};
343
344void dn_register_sysctl(void)
345{
346	dn_table_header = register_net_sysctl(&init_net, "net/decnet", dn_table);
347}
348
349void dn_unregister_sysctl(void)
350{
351	unregister_net_sysctl_table(dn_table_header);
352}
353
354#else  /* CONFIG_SYSCTL */
355void dn_unregister_sysctl(void)
356{
357}
358void dn_register_sysctl(void)
359{
360}
361
362#endif