1 /*
2 * DECnet An implementation of the DECnet protocol suite for the LINUX
3 * operating system. DECnet is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * DECnet sysctl support functions
7 *
8 * Author: Steve Whitehouse <SteveW@ACM.org>
9 *
10 *
11 * Changes:
12 *
13 */
14 #include <linux/config.h>
15 #include <linux/mm.h>
16 #include <linux/sysctl.h>
17 #include <linux/fs.h>
18 #include <linux/netdevice.h>
19 #include <linux/string.h>
20 #include <net/neighbour.h>
21 #include <net/dst.h>
22
23 #include <asm/uaccess.h>
24
25 #include <net/dn.h>
26 #include <net/dn_dev.h>
27 #include <net/dn_route.h>
28
29
30 int decnet_debug_level = 0;
31 int decnet_time_wait = 30;
32 int decnet_dn_count = 1;
33 int decnet_di_count = 3;
34 int decnet_dr_count = 3;
35 int decnet_log_martians = 1;
36
37 #ifdef CONFIG_SYSCTL
38 extern int decnet_dst_gc_interval;
39 static int min_decnet_time_wait[] = { 5 };
40 static int max_decnet_time_wait[] = { 600 };
41 static int min_state_count[] = { 1 };
42 static int max_state_count[] = { NSP_MAXRXTSHIFT };
43 static int min_decnet_dst_gc_interval[] = { 1 };
44 static int max_decnet_dst_gc_interval[] = { 60 };
45 static char node_name[7] = "???";
46
47 static struct ctl_table_header *dn_table_header = NULL;
48
49 /*
50 * ctype.h :-)
51 */
52 #define ISNUM(x) (((x) >= '') && ((x) <= '9'))
53 #define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
54 #define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
55 #define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
56 #define INVALID_END_CHAR(x) (ISNUM(x) || ISALPHA(x))
57
58 static void strip_it(char *str)
59 {
60 for(;;) {
61 switch(*str) {
62 case ' ':
63 case '\n':
64 case '\r':
65 case ':':
66 *str = 0;
67 case 0:
68 return;
69 }
70 str++;
71 }
72 }
73
74 /*
75 * Simple routine to parse an ascii DECnet address
76 * into a network order address.
77 */
78 static int parse_addr(dn_address *addr, char *str)
79 {
80 dn_address area, node;
81
82 while(*str && !ISNUM(*str)) str++;
83
84 if (*str == 0)
85 return -1;
86
87 area = (*str++ - '');
88 if (ISNUM(*str)) {
89 area *= 10;
90 area += (*str++ - '');
91 }
92
93 if (*str++ != '.')
94 return -1;
95
96 if (!ISNUM(*str))
97 return -1;
98
99 node = *str++ - '';
100 if (ISNUM(*str)) {
101 node *= 10;
102 node += (*str++ - '');
103 }
104 if (ISNUM(*str)) {
105 node *= 10;
106 node += (*str++ - '');
107 }
108 if (ISNUM(*str)) {
109 node *= 10;
110 node += (*str++ - '');
111 }
112
113 if ((node > 1023) || (area > 63))
114 return -1;
115
116 if (INVALID_END_CHAR(*str))
117 return -1;
118
119 *addr = dn_htons((area << 10) | node);
120
121 return 0;
122 }
123
124
125 static int dn_node_address_strategy(ctl_table *table, int *name, int nlen,
126 void *oldval, size_t *oldlenp,
127 void *newval, size_t newlen,
128 void **context)
129 {
130 int len;
131 dn_address addr;
132
133 if (oldval && oldlenp) {
134 if (get_user(len, oldlenp))
135 return -EFAULT;
136 if (len) {
137 if (len != sizeof(unsigned short))
138 return -EINVAL;
139 if (put_user(decnet_address, (unsigned short *)oldval))
140 return -EFAULT;
141 }
142 }
143 if (newval && newlen) {
144 if (newlen != sizeof(unsigned short))
145 return -EINVAL;
146 if (get_user(addr, (unsigned short *)newval))
147 return -EFAULT;
148
149 dn_dev_devices_off();
150
151 decnet_address = addr;
152 dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address));
153
154 dn_dev_devices_on();
155 }
156 return 0;
157 }
158
159 static int dn_node_address_handler(ctl_table *table, int write,
160 struct file *filp,
161 void *buffer, size_t *lenp)
162 {
163 char addr[DN_ASCBUF_LEN];
164 int len;
165 dn_address dnaddr;
166
167 if (!*lenp || (filp->f_pos && !write)) {
168 *lenp = 0;
169 return 0;
170 }
171
172 if (write) {
173 int len = (*lenp < DN_ASCBUF_LEN) ? *lenp : (DN_ASCBUF_LEN-1);
174
175 if (copy_from_user(addr, buffer, len))
176 return -EFAULT;
177
178 addr[len] = 0;
179 strip_it(addr);
180
181 if (parse_addr(&dnaddr, addr))
182 return -EINVAL;
183
184 dn_dev_devices_off();
185
186 decnet_address = dnaddr;
187 dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address));
188
189 dn_dev_devices_on();
190
191 filp->f_pos += len;
192
193 return 0;
194 }
195
196 dn_addr2asc(dn_ntohs(decnet_address), addr);
197 len = strlen(addr);
198 addr[len++] = '\n';
199
200 if (len > *lenp) len = *lenp;
201
202 if (copy_to_user(buffer, addr, len))
203 return -EFAULT;
204
205 *lenp = len;
206 filp->f_pos += len;
207
208 return 0;
209 }
210
211
212 static int dn_def_dev_strategy(ctl_table *table, int *name, int nlen,
213 void *oldval, size_t *oldlenp,
214 void *newval, size_t newlen,
215 void **context)
216 {
217 size_t len;
218 struct net_device *dev = decnet_default_device;
219 char devname[17];
220 size_t namel;
221
222 devname[0] = 0;
223
224 if (oldval && oldlenp) {
225 if (get_user(len, oldlenp))
226 return -EFAULT;
227 if (len) {
228 if (dev)
229 strcpy(devname, dev->name);
230
231 namel = strlen(devname) + 1;
232 if (len > namel) len = namel;
233
234 if (copy_to_user(oldval, devname, len))
235 return -EFAULT;
236
237 if (put_user(len, oldlenp))
238 return -EFAULT;
239 }
240 }
241
242 if (newval && newlen) {
243 if (newlen > 16)
244 return -E2BIG;
245
246 if (copy_from_user(devname, newval, newlen))
247 return -EFAULT;
248
249 devname[newlen] = 0;
250
251 if ((dev = __dev_get_by_name(devname)) == NULL)
252 return -ENODEV;
253
254 if (dev->dn_ptr == NULL)
255 return -ENODEV;
256
257 decnet_default_device = dev;
258 }
259
260 return 0;
261 }
262
263
264 static int dn_def_dev_handler(ctl_table *table, int write,
265 struct file * filp,
266 void *buffer, size_t *lenp)
267 {
268 int len;
269 struct net_device *dev = decnet_default_device;
270 char devname[17];
271
272 if (!*lenp || (filp->f_pos && !write)) {
273 *lenp = 0;
274 return 0;
275 }
276
277 if (write) {
278 if (*lenp > 16)
279 return -E2BIG;
280
281 if (copy_from_user(devname, buffer, *lenp))
282 return -EFAULT;
283
284 devname[*lenp] = 0;
285 strip_it(devname);
286
287 if ((dev = __dev_get_by_name(devname)) == NULL)
288 return -ENODEV;
289
290 if (dev->dn_ptr == NULL)
291 return -ENODEV;
292
293 decnet_default_device = dev;
294 filp->f_pos += *lenp;
295
296 return 0;
297 }
298
299 if (dev == NULL) {
300 *lenp = 0;
301 return 0;
302 }
303
304 strcpy(devname, dev->name);
305 len = strlen(devname);
306 devname[len++] = '\n';
307
308 if (len > *lenp) len = *lenp;
309
310 if (copy_to_user(buffer, devname, len))
311 return -EFAULT;
312
313 *lenp = len;
314 filp->f_pos += len;
315
316 return 0;
317 }
318
319 static ctl_table dn_table[] = {
320 {NET_DECNET_NODE_ADDRESS, "node_address", NULL, 7, 0644, NULL,
321 dn_node_address_handler, dn_node_address_strategy, NULL,
322 NULL, NULL},
323 {NET_DECNET_NODE_NAME, "node_name", node_name, 7, 0644, NULL,
324 &proc_dostring, &sysctl_string, NULL, NULL, NULL},
325 {NET_DECNET_DEFAULT_DEVICE, "default_device", NULL, 16, 0644, NULL,
326 dn_def_dev_handler, dn_def_dev_strategy, NULL, NULL, NULL},
327 {NET_DECNET_TIME_WAIT, "time_wait", &decnet_time_wait,
328 sizeof(int), 0644,
329 NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
330 &min_decnet_time_wait, &max_decnet_time_wait},
331 {NET_DECNET_DN_COUNT, "dn_count", &decnet_dn_count,
332 sizeof(int), 0644,
333 NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
334 &min_state_count, &max_state_count},
335 {NET_DECNET_DI_COUNT, "di_count", &decnet_di_count,
336 sizeof(int), 0644,
337 NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
338 &min_state_count, &max_state_count},
339 {NET_DECNET_DR_COUNT, "dr_count", &decnet_dr_count,
340 sizeof(int), 0644,
341 NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
342 &min_state_count, &max_state_count},
343 {NET_DECNET_DST_GC_INTERVAL, "dst_gc_interval", &decnet_dst_gc_interval,
344 sizeof(int), 0644,
345 NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
346 &min_decnet_dst_gc_interval, &max_decnet_dst_gc_interval},
347 {NET_DECNET_DEBUG_LEVEL, "debug", &decnet_debug_level,
348 sizeof(int), 0644,
349 NULL, &proc_dointvec, &sysctl_intvec, NULL,
350 NULL, NULL},
351 {0}
352 };
353
354 static ctl_table dn_dir_table[] = {
355 {NET_DECNET, "decnet", NULL, 0, 0555, dn_table},
356 {0}
357 };
358
359 static ctl_table dn_root_table[] = {
360 {CTL_NET, "net", NULL, 0, 0555, dn_dir_table},
361 {0}
362 };
363
364 void dn_register_sysctl(void)
365 {
366 dn_table_header = register_sysctl_table(dn_root_table, 1);
367 }
368
369 void dn_unregister_sysctl(void)
370 {
371 unregister_sysctl_table(dn_table_header);
372 }
373
374 #else /* CONFIG_SYSCTL */
375 void dn_unregister_sysctl(void)
376 {
377 }
378 void dn_register_sysctl(void)
379 {
380 }
381
382 #endif
383
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.