• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
33 int decnet_debug_level;
34 int decnet_time_wait = 30;
35 int decnet_dn_count = 1;
36 int decnet_di_count = 3;
37 int decnet_dr_count = 3;
38 int decnet_log_martians = 1;
39 int decnet_no_fc_max_cwnd = NSP_MIN_WINDOW;
40 
41 /* Reasonable defaults, I hope, based on tcp's defaults */
42 long sysctl_decnet_mem[3] = { 768 << 3, 1024 << 3, 1536 << 3 };
43 int sysctl_decnet_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
44 int sysctl_decnet_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
45 
46 #ifdef CONFIG_SYSCTL
47 extern int decnet_dst_gc_interval;
48 static int min_decnet_time_wait[] = { 5 };
49 static int max_decnet_time_wait[] = { 600 };
50 static int min_state_count[] = { 1 };
51 static int max_state_count[] = { NSP_MAXRXTSHIFT };
52 static int min_decnet_dst_gc_interval[] = { 1 };
53 static int max_decnet_dst_gc_interval[] = { 60 };
54 static int min_decnet_no_fc_max_cwnd[] = { NSP_MIN_WINDOW };
55 static int max_decnet_no_fc_max_cwnd[] = { NSP_MAX_WINDOW };
56 static char node_name[7] = "???";
57 
58 static 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 
strip_it(char * str)69 static 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  */
parse_addr(__le16 * addr,char * str)90 static 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 
dn_node_address_handler(struct ctl_table * table,int write,void __user * buffer,size_t * lenp,loff_t * ppos)136 static int dn_node_address_handler(struct ctl_table *table, int write,
137 				void __user *buffer,
138 				size_t *lenp, loff_t *ppos)
139 {
140 	char addr[DN_ASCBUF_LEN];
141 	size_t len;
142 	__le16 dnaddr;
143 
144 	if (!*lenp || (*ppos && !write)) {
145 		*lenp = 0;
146 		return 0;
147 	}
148 
149 	if (write) {
150 		len = (*lenp < DN_ASCBUF_LEN) ? *lenp : (DN_ASCBUF_LEN-1);
151 
152 		if (copy_from_user(addr, buffer, len))
153 			return -EFAULT;
154 
155 		addr[len] = 0;
156 		strip_it(addr);
157 
158 		if (parse_addr(&dnaddr, addr))
159 			return -EINVAL;
160 
161 		dn_dev_devices_off();
162 
163 		decnet_address = dnaddr;
164 
165 		dn_dev_devices_on();
166 
167 		*ppos += len;
168 
169 		return 0;
170 	}
171 
172 	dn_addr2asc(le16_to_cpu(decnet_address), addr);
173 	len = strlen(addr);
174 	addr[len++] = '\n';
175 
176 	if (len > *lenp) len = *lenp;
177 
178 	if (copy_to_user(buffer, addr, len))
179 		return -EFAULT;
180 
181 	*lenp = len;
182 	*ppos += len;
183 
184 	return 0;
185 }
186 
dn_def_dev_handler(struct ctl_table * table,int write,void __user * buffer,size_t * lenp,loff_t * ppos)187 static int dn_def_dev_handler(struct ctl_table *table, int write,
188 				void __user *buffer,
189 				size_t *lenp, loff_t *ppos)
190 {
191 	size_t len;
192 	struct net_device *dev;
193 	char devname[17];
194 
195 	if (!*lenp || (*ppos && !write)) {
196 		*lenp = 0;
197 		return 0;
198 	}
199 
200 	if (write) {
201 		if (*lenp > 16)
202 			return -E2BIG;
203 
204 		if (copy_from_user(devname, buffer, *lenp))
205 			return -EFAULT;
206 
207 		devname[*lenp] = 0;
208 		strip_it(devname);
209 
210 		dev = dev_get_by_name(&init_net, devname);
211 		if (dev == NULL)
212 			return -ENODEV;
213 
214 		if (dev->dn_ptr == NULL) {
215 			dev_put(dev);
216 			return -ENODEV;
217 		}
218 
219 		if (dn_dev_set_default(dev, 1)) {
220 			dev_put(dev);
221 			return -ENODEV;
222 		}
223 		*ppos += *lenp;
224 
225 		return 0;
226 	}
227 
228 	dev = dn_dev_get_default();
229 	if (dev == NULL) {
230 		*lenp = 0;
231 		return 0;
232 	}
233 
234 	strcpy(devname, dev->name);
235 	dev_put(dev);
236 	len = strlen(devname);
237 	devname[len++] = '\n';
238 
239 	if (len > *lenp) len = *lenp;
240 
241 	if (copy_to_user(buffer, devname, len))
242 		return -EFAULT;
243 
244 	*lenp = len;
245 	*ppos += len;
246 
247 	return 0;
248 }
249 
250 static struct ctl_table dn_table[] = {
251 	{
252 		.procname = "node_address",
253 		.maxlen = 7,
254 		.mode = 0644,
255 		.proc_handler = dn_node_address_handler,
256 	},
257 	{
258 		.procname = "node_name",
259 		.data = node_name,
260 		.maxlen = 7,
261 		.mode = 0644,
262 		.proc_handler = proc_dostring,
263 	},
264 	{
265 		.procname = "default_device",
266 		.maxlen = 16,
267 		.mode = 0644,
268 		.proc_handler = dn_def_dev_handler,
269 	},
270 	{
271 		.procname = "time_wait",
272 		.data = &decnet_time_wait,
273 		.maxlen = sizeof(int),
274 		.mode = 0644,
275 		.proc_handler = proc_dointvec_minmax,
276 		.extra1 = &min_decnet_time_wait,
277 		.extra2 = &max_decnet_time_wait
278 	},
279 	{
280 		.procname = "dn_count",
281 		.data = &decnet_dn_count,
282 		.maxlen = sizeof(int),
283 		.mode = 0644,
284 		.proc_handler = proc_dointvec_minmax,
285 		.extra1 = &min_state_count,
286 		.extra2 = &max_state_count
287 	},
288 	{
289 		.procname = "di_count",
290 		.data = &decnet_di_count,
291 		.maxlen = sizeof(int),
292 		.mode = 0644,
293 		.proc_handler = proc_dointvec_minmax,
294 		.extra1 = &min_state_count,
295 		.extra2 = &max_state_count
296 	},
297 	{
298 		.procname = "dr_count",
299 		.data = &decnet_dr_count,
300 		.maxlen = sizeof(int),
301 		.mode = 0644,
302 		.proc_handler = proc_dointvec_minmax,
303 		.extra1 = &min_state_count,
304 		.extra2 = &max_state_count
305 	},
306 	{
307 		.procname = "dst_gc_interval",
308 		.data = &decnet_dst_gc_interval,
309 		.maxlen = sizeof(int),
310 		.mode = 0644,
311 		.proc_handler = proc_dointvec_minmax,
312 		.extra1 = &min_decnet_dst_gc_interval,
313 		.extra2 = &max_decnet_dst_gc_interval
314 	},
315 	{
316 		.procname = "no_fc_max_cwnd",
317 		.data = &decnet_no_fc_max_cwnd,
318 		.maxlen = sizeof(int),
319 		.mode = 0644,
320 		.proc_handler = proc_dointvec_minmax,
321 		.extra1 = &min_decnet_no_fc_max_cwnd,
322 		.extra2 = &max_decnet_no_fc_max_cwnd
323 	},
324        {
325 		.procname = "decnet_mem",
326 		.data = &sysctl_decnet_mem,
327 		.maxlen = sizeof(sysctl_decnet_mem),
328 		.mode = 0644,
329 		.proc_handler = proc_doulongvec_minmax
330 	},
331 	{
332 		.procname = "decnet_rmem",
333 		.data = &sysctl_decnet_rmem,
334 		.maxlen = sizeof(sysctl_decnet_rmem),
335 		.mode = 0644,
336 		.proc_handler = proc_dointvec,
337 	},
338 	{
339 		.procname = "decnet_wmem",
340 		.data = &sysctl_decnet_wmem,
341 		.maxlen = sizeof(sysctl_decnet_wmem),
342 		.mode = 0644,
343 		.proc_handler = proc_dointvec,
344 	},
345 	{
346 		.procname = "debug",
347 		.data = &decnet_debug_level,
348 		.maxlen = sizeof(int),
349 		.mode = 0644,
350 		.proc_handler = proc_dointvec,
351 	},
352 	{ }
353 };
354 
dn_register_sysctl(void)355 void dn_register_sysctl(void)
356 {
357 	dn_table_header = register_net_sysctl(&init_net, "net/decnet", dn_table);
358 }
359 
dn_unregister_sysctl(void)360 void dn_unregister_sysctl(void)
361 {
362 	unregister_net_sysctl_table(dn_table_header);
363 }
364 
365 #else  /* CONFIG_SYSCTL */
dn_unregister_sysctl(void)366 void dn_unregister_sysctl(void)
367 {
368 }
dn_register_sysctl(void)369 void dn_register_sysctl(void)
370 {
371 }
372 
373 #endif
374