linux/net/decnet/sysctl_net_decnet.c
<<
>>
Prefs
   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
  32int decnet_debug_level;
  33int decnet_time_wait = 30;
  34int decnet_dn_count = 1;
  35int decnet_di_count = 3;
  36int decnet_dr_count = 3;
  37int decnet_log_martians = 1;
  38int decnet_no_fc_max_cwnd = NSP_MIN_WINDOW;
  39
  40/* Reasonable defaults, I hope, based on tcp's defaults */
  41int sysctl_decnet_mem[3] = { 768 << 3, 1024 << 3, 1536 << 3 };
  42int sysctl_decnet_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
  43int sysctl_decnet_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
  44
  45#ifdef CONFIG_SYSCTL
  46extern int decnet_dst_gc_interval;
  47static int min_decnet_time_wait[] = { 5 };
  48static int max_decnet_time_wait[] = { 600 };
  49static int min_state_count[] = { 1 };
  50static int max_state_count[] = { NSP_MAXRXTSHIFT };
  51static int min_decnet_dst_gc_interval[] = { 1 };
  52static int max_decnet_dst_gc_interval[] = { 60 };
  53static int min_decnet_no_fc_max_cwnd[] = { NSP_MIN_WINDOW };
  54static int max_decnet_no_fc_max_cwnd[] = { NSP_MAX_WINDOW };
  55static char node_name[7] = "???";
  56
  57static 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
  68static 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                        case 0:
  78                                return;
  79                }
  80                str++;
  81        }
  82}
  83
  84/*
  85 * Simple routine to parse an ascii DECnet address
  86 * into a network order address.
  87 */
  88static int parse_addr(__le16 *addr, char *str)
  89{
  90        __u16 area, node;
  91
  92        while(*str && !ISNUM(*str)) str++;
  93
  94        if (*str == 0)
  95                return -1;
  96
  97        area = (*str++ - '0');
  98        if (ISNUM(*str)) {
  99                area *= 10;
 100                area += (*str++ - '0');
 101        }
 102
 103        if (*str++ != '.')
 104                return -1;
 105
 106        if (!ISNUM(*str))
 107                return -1;
 108
 109        node = *str++ - '0';
 110        if (ISNUM(*str)) {
 111                node *= 10;
 112                node += (*str++ - '0');
 113        }
 114        if (ISNUM(*str)) {
 115                node *= 10;
 116                node += (*str++ - '0');
 117        }
 118        if (ISNUM(*str)) {
 119                node *= 10;
 120                node += (*str++ - '0');
 121        }
 122
 123        if ((node > 1023) || (area > 63))
 124                return -1;
 125
 126        if (INVALID_END_CHAR(*str))
 127                return -1;
 128
 129        *addr = cpu_to_le16((area << 10) | node);
 130
 131        return 0;
 132}
 133
 134static int dn_node_address_handler(ctl_table *table, int write,
 135                                void __user *buffer,
 136                                size_t *lenp, loff_t *ppos)
 137{
 138        char addr[DN_ASCBUF_LEN];
 139        size_t len;
 140        __le16 dnaddr;
 141
 142        if (!*lenp || (*ppos && !write)) {
 143                *lenp = 0;
 144                return 0;
 145        }
 146
 147        if (write) {
 148                len = (*lenp < DN_ASCBUF_LEN) ? *lenp : (DN_ASCBUF_LEN-1);
 149
 150                if (copy_from_user(addr, buffer, len))
 151                        return -EFAULT;
 152
 153                addr[len] = 0;
 154                strip_it(addr);
 155
 156                if (parse_addr(&dnaddr, addr))
 157                        return -EINVAL;
 158
 159                dn_dev_devices_off();
 160
 161                decnet_address = dnaddr;
 162
 163                dn_dev_devices_on();
 164
 165                *ppos += len;
 166
 167                return 0;
 168        }
 169
 170        dn_addr2asc(le16_to_cpu(decnet_address), addr);
 171        len = strlen(addr);
 172        addr[len++] = '\n';
 173
 174        if (len > *lenp) len = *lenp;
 175
 176        if (copy_to_user(buffer, addr, len))
 177                return -EFAULT;
 178
 179        *lenp = len;
 180        *ppos += len;
 181
 182        return 0;
 183}
 184
 185static int dn_def_dev_handler(ctl_table *table, int write,
 186                                void __user *buffer,
 187                                size_t *lenp, loff_t *ppos)
 188{
 189        size_t len;
 190        struct net_device *dev;
 191        char devname[17];
 192
 193        if (!*lenp || (*ppos && !write)) {
 194                *lenp = 0;
 195                return 0;
 196        }
 197
 198        if (write) {
 199                if (*lenp > 16)
 200                        return -E2BIG;
 201
 202                if (copy_from_user(devname, buffer, *lenp))
 203                        return -EFAULT;
 204
 205                devname[*lenp] = 0;
 206                strip_it(devname);
 207
 208                dev = dev_get_by_name(&init_net, devname);
 209                if (dev == NULL)
 210                        return -ENODEV;
 211
 212                if (dev->dn_ptr == NULL) {
 213                        dev_put(dev);
 214                        return -ENODEV;
 215                }
 216
 217                if (dn_dev_set_default(dev, 1)) {
 218                        dev_put(dev);
 219                        return -ENODEV;
 220                }
 221                *ppos += *lenp;
 222
 223                return 0;
 224        }
 225
 226        dev = dn_dev_get_default();
 227        if (dev == NULL) {
 228                *lenp = 0;
 229                return 0;
 230        }
 231
 232        strcpy(devname, dev->name);
 233        dev_put(dev);
 234        len = strlen(devname);
 235        devname[len++] = '\n';
 236
 237        if (len > *lenp) len = *lenp;
 238
 239        if (copy_to_user(buffer, devname, len))
 240                return -EFAULT;
 241
 242        *lenp = len;
 243        *ppos += len;
 244
 245        return 0;
 246}
 247
 248static ctl_table dn_table[] = {
 249        {
 250                .procname = "node_address",
 251                .maxlen = 7,
 252                .mode = 0644,
 253                .proc_handler = dn_node_address_handler,
 254        },
 255        {
 256                .procname = "node_name",
 257                .data = node_name,
 258                .maxlen = 7,
 259                .mode = 0644,
 260                .proc_handler = proc_dostring,
 261        },
 262        {
 263                .procname = "default_device",
 264                .maxlen = 16,
 265                .mode = 0644,
 266                .proc_handler = dn_def_dev_handler,
 267        },
 268        {
 269                .procname = "time_wait",
 270                .data = &decnet_time_wait,
 271                .maxlen = sizeof(int),
 272                .mode = 0644,
 273                .proc_handler = proc_dointvec_minmax,
 274                .extra1 = &min_decnet_time_wait,
 275                .extra2 = &max_decnet_time_wait
 276        },
 277        {
 278                .procname = "dn_count",
 279                .data = &decnet_dn_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 = "di_count",
 288                .data = &decnet_di_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 = "dr_count",
 297                .data = &decnet_dr_count,
 298                .maxlen = sizeof(int),
 299                .mode = 0644,
 300                .proc_handler = proc_dointvec_minmax,
 301                .extra1 = &min_state_count,
 302                .extra2 = &max_state_count
 303        },
 304        {
 305                .procname = "dst_gc_interval",
 306                .data = &decnet_dst_gc_interval,
 307                .maxlen = sizeof(int),
 308                .mode = 0644,
 309                .proc_handler = proc_dointvec_minmax,
 310                .extra1 = &min_decnet_dst_gc_interval,
 311                .extra2 = &max_decnet_dst_gc_interval
 312        },
 313        {
 314                .procname = "no_fc_max_cwnd",
 315                .data = &decnet_no_fc_max_cwnd,
 316                .maxlen = sizeof(int),
 317                .mode = 0644,
 318                .proc_handler = proc_dointvec_minmax,
 319                .extra1 = &min_decnet_no_fc_max_cwnd,
 320                .extra2 = &max_decnet_no_fc_max_cwnd
 321        },
 322       {
 323                .procname = "decnet_mem",
 324                .data = &sysctl_decnet_mem,
 325                .maxlen = sizeof(sysctl_decnet_mem),
 326                .mode = 0644,
 327                .proc_handler = proc_dointvec,
 328        },
 329        {
 330                .procname = "decnet_rmem",
 331                .data = &sysctl_decnet_rmem,
 332                .maxlen = sizeof(sysctl_decnet_rmem),
 333                .mode = 0644,
 334                .proc_handler = proc_dointvec,
 335        },
 336        {
 337                .procname = "decnet_wmem",
 338                .data = &sysctl_decnet_wmem,
 339                .maxlen = sizeof(sysctl_decnet_wmem),
 340                .mode = 0644,
 341                .proc_handler = proc_dointvec,
 342        },
 343        {
 344                .procname = "debug",
 345                .data = &decnet_debug_level,
 346                .maxlen = sizeof(int),
 347                .mode = 0644,
 348                .proc_handler = proc_dointvec,
 349        },
 350        { }
 351};
 352
 353static struct ctl_path dn_path[] = {
 354        { .procname = "net", },
 355        { .procname = "decnet", },
 356        { }
 357};
 358
 359void dn_register_sysctl(void)
 360{
 361        dn_table_header = register_sysctl_paths(dn_path, dn_table);
 362}
 363
 364void dn_unregister_sysctl(void)
 365{
 366        unregister_sysctl_table(dn_table_header);
 367}
 368
 369#else  /* CONFIG_SYSCTL */
 370void dn_unregister_sysctl(void)
 371{
 372}
 373void dn_register_sysctl(void)
 374{
 375}
 376
 377#endif
 378
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.