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