123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- /*
- * DECnet An implementation of the DECnet protocol suite for the LINUX
- * operating system. DECnet is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * DECnet sysctl support functions
- *
- * Author: Steve Whitehouse <SteveW@ACM.org>
- *
- *
- * Changes:
- * Steve Whitehouse - C99 changes and default device handling
- * Steve Whitehouse - Memory buffer settings, like the tcp ones
- *
- */
- #include <linux/mm.h>
- #include <linux/sysctl.h>
- #include <linux/fs.h>
- #include <linux/netdevice.h>
- #include <linux/string.h>
- #include <net/neighbour.h>
- #include <net/dst.h>
- #include <net/flow.h>
- #include <asm/uaccess.h>
- #include <net/dn.h>
- #include <net/dn_dev.h>
- #include <net/dn_route.h>
- int decnet_debug_level;
- int decnet_time_wait = 30;
- int decnet_dn_count = 1;
- int decnet_di_count = 3;
- int decnet_dr_count = 3;
- int decnet_log_martians = 1;
- int decnet_no_fc_max_cwnd = NSP_MIN_WINDOW;
- /* Reasonable defaults, I hope, based on tcp's defaults */
- long sysctl_decnet_mem[3] = { 768 << 3, 1024 << 3, 1536 << 3 };
- int sysctl_decnet_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
- int sysctl_decnet_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
- #ifdef CONFIG_SYSCTL
- extern int decnet_dst_gc_interval;
- static int min_decnet_time_wait[] = { 5 };
- static int max_decnet_time_wait[] = { 600 };
- static int min_state_count[] = { 1 };
- static int max_state_count[] = { NSP_MAXRXTSHIFT };
- static int min_decnet_dst_gc_interval[] = { 1 };
- static int max_decnet_dst_gc_interval[] = { 60 };
- static int min_decnet_no_fc_max_cwnd[] = { NSP_MIN_WINDOW };
- static int max_decnet_no_fc_max_cwnd[] = { NSP_MAX_WINDOW };
- static char node_name[7] = "???";
- static struct ctl_table_header *dn_table_header = NULL;
- /*
- * ctype.h :-)
- */
- #define ISNUM(x) (((x) >= '0') && ((x) <= '9'))
- #define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
- #define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
- #define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
- #define INVALID_END_CHAR(x) (ISNUM(x) || ISALPHA(x))
- static void strip_it(char *str)
- {
- for(;;) {
- switch (*str) {
- case ' ':
- case '\n':
- case '\r':
- case ':':
- *str = 0;
- /* Fallthrough */
- case 0:
- return;
- }
- str++;
- }
- }
- /*
- * Simple routine to parse an ascii DECnet address
- * into a network order address.
- */
- static int parse_addr(__le16 *addr, char *str)
- {
- __u16 area, node;
- while(*str && !ISNUM(*str)) str++;
- if (*str == 0)
- return -1;
- area = (*str++ - '0');
- if (ISNUM(*str)) {
- area *= 10;
- area += (*str++ - '0');
- }
- if (*str++ != '.')
- return -1;
- if (!ISNUM(*str))
- return -1;
- node = *str++ - '0';
- if (ISNUM(*str)) {
- node *= 10;
- node += (*str++ - '0');
- }
- if (ISNUM(*str)) {
- node *= 10;
- node += (*str++ - '0');
- }
- if (ISNUM(*str)) {
- node *= 10;
- node += (*str++ - '0');
- }
- if ((node > 1023) || (area > 63))
- return -1;
- if (INVALID_END_CHAR(*str))
- return -1;
- *addr = cpu_to_le16((area << 10) | node);
- return 0;
- }
- static int dn_node_address_handler(struct ctl_table *table, int write,
- void __user *buffer,
- size_t *lenp, loff_t *ppos)
- {
- char addr[DN_ASCBUF_LEN];
- size_t len;
- __le16 dnaddr;
- if (!*lenp || (*ppos && !write)) {
- *lenp = 0;
- return 0;
- }
- if (write) {
- len = (*lenp < DN_ASCBUF_LEN) ? *lenp : (DN_ASCBUF_LEN-1);
- if (copy_from_user(addr, buffer, len))
- return -EFAULT;
- addr[len] = 0;
- strip_it(addr);
- if (parse_addr(&dnaddr, addr))
- return -EINVAL;
- dn_dev_devices_off();
- decnet_address = dnaddr;
- dn_dev_devices_on();
- *ppos += len;
- return 0;
- }
- dn_addr2asc(le16_to_cpu(decnet_address), addr);
- len = strlen(addr);
- addr[len++] = '\n';
- if (len > *lenp) len = *lenp;
- if (copy_to_user(buffer, addr, len))
- return -EFAULT;
- *lenp = len;
- *ppos += len;
- return 0;
- }
- static int dn_def_dev_handler(struct ctl_table *table, int write,
- void __user *buffer,
- size_t *lenp, loff_t *ppos)
- {
- size_t len;
- struct net_device *dev;
- char devname[17];
- if (!*lenp || (*ppos && !write)) {
- *lenp = 0;
- return 0;
- }
- if (write) {
- if (*lenp > 16)
- return -E2BIG;
- if (copy_from_user(devname, buffer, *lenp))
- return -EFAULT;
- devname[*lenp] = 0;
- strip_it(devname);
- dev = dev_get_by_name(&init_net, devname);
- if (dev == NULL)
- return -ENODEV;
- if (dev->dn_ptr == NULL) {
- dev_put(dev);
- return -ENODEV;
- }
- if (dn_dev_set_default(dev, 1)) {
- dev_put(dev);
- return -ENODEV;
- }
- *ppos += *lenp;
- return 0;
- }
- dev = dn_dev_get_default();
- if (dev == NULL) {
- *lenp = 0;
- return 0;
- }
- strcpy(devname, dev->name);
- dev_put(dev);
- len = strlen(devname);
- devname[len++] = '\n';
- if (len > *lenp) len = *lenp;
- if (copy_to_user(buffer, devname, len))
- return -EFAULT;
- *lenp = len;
- *ppos += len;
- return 0;
- }
- static struct ctl_table dn_table[] = {
- {
- .procname = "node_address",
- .maxlen = 7,
- .mode = 0644,
- .proc_handler = dn_node_address_handler,
- },
- {
- .procname = "node_name",
- .data = node_name,
- .maxlen = 7,
- .mode = 0644,
- .proc_handler = proc_dostring,
- },
- {
- .procname = "default_device",
- .maxlen = 16,
- .mode = 0644,
- .proc_handler = dn_def_dev_handler,
- },
- {
- .procname = "time_wait",
- .data = &decnet_time_wait,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_minmax,
- .extra1 = &min_decnet_time_wait,
- .extra2 = &max_decnet_time_wait
- },
- {
- .procname = "dn_count",
- .data = &decnet_dn_count,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_minmax,
- .extra1 = &min_state_count,
- .extra2 = &max_state_count
- },
- {
- .procname = "di_count",
- .data = &decnet_di_count,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_minmax,
- .extra1 = &min_state_count,
- .extra2 = &max_state_count
- },
- {
- .procname = "dr_count",
- .data = &decnet_dr_count,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_minmax,
- .extra1 = &min_state_count,
- .extra2 = &max_state_count
- },
- {
- .procname = "dst_gc_interval",
- .data = &decnet_dst_gc_interval,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_minmax,
- .extra1 = &min_decnet_dst_gc_interval,
- .extra2 = &max_decnet_dst_gc_interval
- },
- {
- .procname = "no_fc_max_cwnd",
- .data = &decnet_no_fc_max_cwnd,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_minmax,
- .extra1 = &min_decnet_no_fc_max_cwnd,
- .extra2 = &max_decnet_no_fc_max_cwnd
- },
- {
- .procname = "decnet_mem",
- .data = &sysctl_decnet_mem,
- .maxlen = sizeof(sysctl_decnet_mem),
- .mode = 0644,
- .proc_handler = proc_doulongvec_minmax
- },
- {
- .procname = "decnet_rmem",
- .data = &sysctl_decnet_rmem,
- .maxlen = sizeof(sysctl_decnet_rmem),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- {
- .procname = "decnet_wmem",
- .data = &sysctl_decnet_wmem,
- .maxlen = sizeof(sysctl_decnet_wmem),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- {
- .procname = "debug",
- .data = &decnet_debug_level,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- { }
- };
- void dn_register_sysctl(void)
- {
- dn_table_header = register_net_sysctl(&init_net, "net/decnet", dn_table);
- }
- void dn_unregister_sysctl(void)
- {
- unregister_net_sysctl_table(dn_table_header);
- }
- #else /* CONFIG_SYSCTL */
- void dn_unregister_sysctl(void)
- {
- }
- void dn_register_sysctl(void)
- {
- }
- #endif
|