linux-bk/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 *
  14 */
  15#include <linux/config.h>
  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#ifdef CONFIG_SYSCTL
  41extern int decnet_dst_gc_interval;
  42static int min_decnet_time_wait[] = { 5 };
  43static int max_decnet_time_wait[] = { 600 };
  44static int min_state_count[] = { 1 };
  45static int max_state_count[] = { NSP_MAXRXTSHIFT };
  46static int min_decnet_dst_gc_interval[] = { 1 };
  47static int max_decnet_dst_gc_interval[] = { 60 };
  48static int min_decnet_no_fc_max_cwnd[] = { NSP_MIN_WINDOW };
  49static int max_decnet_no_fc_max_cwnd[] = { NSP_MAX_WINDOW };
  50static char node_name[7] = "???";
  51
  52static struct ctl_table_header *dn_table_header = NULL;
  53
  54/*
  55 * ctype.h :-)
  56 */
  57#define ISNUM(x) (((x) >= '0') && ((x) <= '9'))
  58#define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
  59#define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
  60#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
  61#define INVALID_END_CHAR(x) (ISNUM(x) || ISALPHA(x))
  62
  63static void strip_it(char *str)
  64{
  65        for(;;) {
  66                switch(*str) {
  67                        case ' ':
  68                        case '\n':
  69                        case '\r':
  70                        case ':':
  71                                *str = 0;
  72                        case 0:
  73                                return;
  74                }
  75                str++;
  76        }
  77}
  78
  79/*
  80 * Simple routine to parse an ascii DECnet address
  81 * into a network order address.
  82 */
  83static int parse_addr(dn_address *addr, char *str)
  84{
  85        dn_address area, node;
  86
  87        while(*str && !ISNUM(*str)) str++;
  88
  89        if (*str == 0)
  90                return -1;
  91
  92        area = (*str++ - '0');
  93        if (ISNUM(*str)) {
  94                area *= 10;
  95                area += (*str++ - '0');
  96        }
  97
  98        if (*str++ != '.')
  99                return -1;
 100
 101        if (!ISNUM(*str))
 102                return -1;
 103
 104        node = *str++ - '0';
 105        if (ISNUM(*str)) {
 106                node *= 10;
 107                node += (*str++ - '0');
 108        }
 109        if (ISNUM(*str)) {
 110                node *= 10;
 111                node += (*str++ - '0');
 112        }
 113        if (ISNUM(*str)) {
 114                node *= 10;
 115                node += (*str++ - '0');
 116        }
 117
 118        if ((node > 1023) || (area > 63))
 119                return -1;
 120
 121        if (INVALID_END_CHAR(*str))
 122                return -1;
 123
 124        *addr = dn_htons((area << 10) | node);
 125
 126        return 0;
 127}
 128
 129
 130static int dn_node_address_strategy(ctl_table *table, int __user *name, int nlen,
 131                                void __user *oldval, size_t __user *oldlenp,
 132                                void __user *newval, size_t newlen,
 133                                void **context)
 134{
 135        size_t len;
 136        dn_address addr;
 137
 138        if (oldval && oldlenp) {
 139                if (get_user(len, oldlenp))
 140                        return -EFAULT;
 141                if (len) {
 142                        if (len != sizeof(unsigned short))
 143                                return -EINVAL;
 144                        if (put_user(decnet_address, (unsigned short __user *)oldval))
 145                                return -EFAULT;
 146                }
 147        }
 148        if (newval && newlen) {
 149                if (newlen != sizeof(unsigned short))
 150                        return -EINVAL;
 151                if (get_user(addr, (unsigned short __user *)newval))
 152                        return -EFAULT;
 153
 154                dn_dev_devices_off();
 155
 156                decnet_address = addr;
 157
 158                dn_dev_devices_on();
 159        }
 160        return 0;
 161}
 162
 163static int dn_node_address_handler(ctl_table *table, int write, 
 164                                struct file *filp,
 165                                void __user *buffer,
 166                                size_t *lenp, loff_t *ppos)
 167{
 168        char addr[DN_ASCBUF_LEN];
 169        size_t len;
 170        dn_address dnaddr;
 171
 172        if (!*lenp || (*ppos && !write)) {
 173                *lenp = 0;
 174                return 0;
 175        }
 176
 177        if (write) {
 178                int len = (*lenp < DN_ASCBUF_LEN) ? *lenp : (DN_ASCBUF_LEN-1);
 179
 180                if (copy_from_user(addr, buffer, len))
 181                        return -EFAULT;
 182
 183                addr[len] = 0;
 184                strip_it(addr);
 185
 186                if (parse_addr(&dnaddr, addr))
 187                        return -EINVAL;
 188
 189                dn_dev_devices_off();
 190
 191                decnet_address = dnaddr;
 192
 193                dn_dev_devices_on();
 194
 195                *ppos += len;
 196
 197                return 0;
 198        }
 199
 200        dn_addr2asc(dn_ntohs(decnet_address), addr);
 201        len = strlen(addr);
 202        addr[len++] = '\n';
 203
 204        if (len > *lenp) len = *lenp;
 205
 206        if (copy_to_user(buffer, addr, len))
 207                return -EFAULT;
 208
 209        *lenp = len;
 210        *ppos += len;
 211
 212        return 0;
 213}
 214
 215
 216static int dn_def_dev_strategy(ctl_table *table, int __user *name, int nlen,
 217                                void __user *oldval, size_t __user *oldlenp,
 218                                void __user *newval, size_t newlen,
 219                                void **context)
 220{
 221        size_t len;
 222        struct net_device *dev;
 223        char devname[17];
 224        size_t namel;
 225        int rv = 0;
 226
 227        devname[0] = 0;
 228
 229        if (oldval && oldlenp) {
 230                if (get_user(len, oldlenp))
 231                        return -EFAULT;
 232                if (len) {
 233                        dev = dn_dev_get_default();
 234                        if (dev) {
 235                                strcpy(devname, dev->name);
 236                                dev_put(dev);
 237                        }
 238
 239                        namel = strlen(devname) + 1;
 240                        if (len > namel) len = namel;   
 241
 242                        if (copy_to_user(oldval, devname, len))
 243                                return -EFAULT;
 244
 245                        if (put_user(len, oldlenp))
 246                                return -EFAULT;
 247                }
 248        }
 249
 250        if (newval && newlen) {
 251                if (newlen > 16)
 252                        return -E2BIG;
 253
 254                if (copy_from_user(devname, newval, newlen))
 255                        return -EFAULT;
 256
 257                devname[newlen] = 0;
 258
 259                dev = dev_get_by_name(devname);
 260                if (dev == NULL)
 261                        return -ENODEV;
 262
 263                rv = -ENODEV;
 264                if (dev->dn_ptr != NULL) {
 265                        rv = dn_dev_set_default(dev, 1);
 266                        if (rv)
 267                                dev_put(dev);
 268                }
 269        }
 270
 271        return rv;
 272}
 273
 274
 275static int dn_def_dev_handler(ctl_table *table, int write, 
 276                                struct file * filp,
 277                                void __user *buffer,
 278                                size_t *lenp, loff_t *ppos)
 279{
 280        size_t len;
 281        struct net_device *dev;
 282        char devname[17];
 283
 284        if (!*lenp || (*ppos && !write)) {
 285                *lenp = 0;
 286                return 0;
 287        }
 288
 289        if (write) {
 290                if (*lenp > 16)
 291                        return -E2BIG;
 292
 293                if (copy_from_user(devname, buffer, *lenp))
 294                        return -EFAULT;
 295
 296                devname[*lenp] = 0;
 297                strip_it(devname);
 298
 299                dev = dev_get_by_name(devname);
 300                if (dev == NULL)
 301                        return -ENODEV;
 302
 303                if (dev->dn_ptr == NULL) {
 304                        dev_put(dev);
 305                        return -ENODEV;
 306                }
 307
 308                if (dn_dev_set_default(dev, 1)) {
 309                        dev_put(dev);
 310                        return -ENODEV;
 311                }
 312                *ppos += *lenp;
 313
 314                return 0;
 315        }
 316
 317        dev = dn_dev_get_default();
 318        if (dev == NULL) {
 319                *lenp = 0;
 320                return 0;
 321        }
 322
 323        strcpy(devname, dev->name);
 324        dev_put(dev);
 325        len = strlen(devname);
 326        devname[len++] = '\n';
 327
 328        if (len > *lenp) len = *lenp;
 329
 330        if (copy_to_user(buffer, devname, len))
 331                return -EFAULT;
 332
 333        *lenp = len;
 334        *ppos += len;
 335
 336        return 0;
 337}
 338
 339static ctl_table dn_table[] = {
 340        {
 341                .ctl_name = NET_DECNET_NODE_ADDRESS, 
 342                .procname = "node_address", 
 343                .maxlen = 7, 
 344                .mode = 0644, 
 345                .proc_handler = dn_node_address_handler,
 346                .strategy = dn_node_address_strategy,
 347        },
 348        {
 349                .ctl_name = NET_DECNET_NODE_NAME,
 350                .procname = "node_name",
 351                .data = node_name, 
 352                .maxlen = 7,
 353                .mode = 0644,
 354                .proc_handler = &proc_dostring,
 355                .strategy = &sysctl_string,
 356        },
 357        {
 358                .ctl_name = NET_DECNET_DEFAULT_DEVICE,
 359                .procname = "default_device", 
 360                .maxlen = 16, 
 361                .mode = 0644,
 362                .proc_handler = dn_def_dev_handler,
 363                .strategy = dn_def_dev_strategy,
 364        },
 365        {
 366                .ctl_name = NET_DECNET_TIME_WAIT,
 367                .procname = "time_wait",
 368                .data = &decnet_time_wait,
 369                .maxlen = sizeof(int),
 370                .mode = 0644,
 371                .proc_handler = &proc_dointvec_minmax,
 372                .strategy = &sysctl_intvec,
 373                .extra1 = &min_decnet_time_wait,
 374                .extra2 = &max_decnet_time_wait
 375        },
 376        {
 377                .ctl_name = NET_DECNET_DN_COUNT,
 378                .procname = "dn_count",
 379                .data = &decnet_dn_count,
 380                .maxlen = sizeof(int),
 381                .mode = 0644,
 382                .proc_handler = &proc_dointvec_minmax,
 383                .strategy = &sysctl_intvec,
 384                .extra1 = &min_state_count,
 385                .extra2 = &max_state_count
 386        },
 387        {
 388                .ctl_name = NET_DECNET_DI_COUNT,
 389                .procname = "di_count",
 390                .data = &decnet_di_count,
 391                .maxlen = sizeof(int),
 392                .mode = 0644,
 393                .proc_handler = &proc_dointvec_minmax,
 394                .strategy = &sysctl_intvec,
 395                .extra1 = &min_state_count,
 396                .extra2 = &max_state_count
 397        },
 398        {
 399                .ctl_name = NET_DECNET_DR_COUNT,
 400                .procname = "dr_count",
 401                .data = &decnet_dr_count,
 402                .maxlen = sizeof(int),
 403                .mode = 0644,
 404                .proc_handler = &proc_dointvec_minmax,
 405                .strategy = &sysctl_intvec,
 406                .extra1 = &min_state_count,
 407                .extra2 = &max_state_count
 408        },
 409        {
 410                .ctl_name = NET_DECNET_DST_GC_INTERVAL,
 411                .procname = "dst_gc_interval",
 412                .data = &decnet_dst_gc_interval,
 413                .maxlen = sizeof(int),
 414                .mode = 0644,
 415                .proc_handler = &proc_dointvec_minmax,
 416                .strategy = &sysctl_intvec,
 417                .extra1 = &min_decnet_dst_gc_interval,
 418                .extra2 = &max_decnet_dst_gc_interval
 419        },
 420        {
 421                .ctl_name = NET_DECNET_NO_FC_MAX_CWND,
 422                .procname = "no_fc_max_cwnd",
 423                .data = &decnet_no_fc_max_cwnd,
 424                .maxlen = sizeof(int),
 425                .mode = 0644,
 426                .proc_handler = &proc_dointvec_minmax,
 427                .strategy = &sysctl_intvec,
 428                .extra1 = &min_decnet_no_fc_max_cwnd,
 429                .extra2 = &max_decnet_no_fc_max_cwnd
 430        },
 431        {
 432                .ctl_name = NET_DECNET_DEBUG_LEVEL,
 433                .procname = "debug",
 434                .data = &decnet_debug_level,
 435                .maxlen = sizeof(int),
 436                .mode = 0644,
 437                .proc_handler = &proc_dointvec,
 438                .strategy = &sysctl_intvec,
 439        },
 440        {0}
 441};
 442
 443static ctl_table dn_dir_table[] = {
 444        {
 445                .ctl_name = NET_DECNET, 
 446                .procname = "decnet", 
 447                .mode = 0555, 
 448                .child = dn_table},
 449        {0}
 450};
 451
 452static ctl_table dn_root_table[] = {
 453        {
 454                .ctl_name = CTL_NET, 
 455                .procname = "net", 
 456                .mode = 0555, 
 457                .child = dn_dir_table
 458        },
 459        {0}
 460};
 461
 462void dn_register_sysctl(void)
 463{
 464        dn_table_header = register_sysctl_table(dn_root_table, 1);
 465}
 466
 467void dn_unregister_sysctl(void)
 468{
 469        unregister_sysctl_table(dn_table_header);
 470}
 471
 472#else  /* CONFIG_SYSCTL */
 473void dn_unregister_sysctl(void)
 474{
 475}
 476void dn_register_sysctl(void)
 477{
 478}
 479
 480#endif
 481
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.