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
 134
 135static int dn_node_address_strategy(ctl_table *table,
 136                                void __user *oldval, size_t __user *oldlenp,
 137                                void __user *newval, size_t newlen)
 138{
 139        size_t len;
 140        __le16 addr;
 141
 142        if (oldval && oldlenp) {
 143                if (get_user(len, oldlenp))
 144                        return -EFAULT;
 145                if (len) {
 146                        if (len != sizeof(unsigned short))
 147                                return -EINVAL;
 148                        if (put_user(decnet_address, (__le16 __user *)oldval))
 149                                return -EFAULT;
 150                }
 151        }
 152        if (newval && newlen) {
 153                if (newlen != sizeof(unsigned short))
 154                        return -EINVAL;
 155                if (get_user(addr, (__le16 __user *)newval))
 156                        return -EFAULT;
 157
 158                dn_dev_devices_off();
 159
 160                decnet_address = addr;
 161
 162                dn_dev_devices_on();
 163        }
 164        return 0;
 165}
 166
 167static int dn_node_address_handler(ctl_table *table, int write,
 168                                void __user *buffer,
 169                                size_t *lenp, loff_t *ppos)
 170{
 171        char addr[DN_ASCBUF_LEN];
 172        size_t len;
 173        __le16 dnaddr;
 174
 175        if (!*lenp || (*ppos && !write)) {
 176                *lenp = 0;
 177                return 0;
 178        }
 179
 180        if (write) {
 181                len = (*lenp < DN_ASCBUF_LEN) ? *lenp : (DN_ASCBUF_LEN-1);
 182
 183                if (copy_from_user(addr, buffer, len))
 184                        return -EFAULT;
 185
 186                addr[len] = 0;
 187                strip_it(addr);
 188
 189                if (parse_addr(&dnaddr, addr))
 190                        return -EINVAL;
 191
 192                dn_dev_devices_off();
 193
 194                decnet_address = dnaddr;
 195
 196                dn_dev_devices_on();
 197
 198                *ppos += len;
 199
 200                return 0;
 201        }
 202
 203        dn_addr2asc(le16_to_cpu(decnet_address), addr);
 204        len = strlen(addr);
 205        addr[len++] = '\n';
 206
 207        if (len > *lenp) len = *lenp;
 208
 209        if (copy_to_user(buffer, addr, len))
 210                return -EFAULT;
 211
 212        *lenp = len;
 213        *ppos += len;
 214
 215        return 0;
 216}
 217
 218
 219static int dn_def_dev_strategy(ctl_table *table,
 220                                void __user *oldval, size_t __user *oldlenp,
 221                                void __user *newval, size_t newlen)
 222{
 223        size_t len;
 224        struct net_device *dev;
 225        char devname[17];
 226        size_t namel;
 227        int rv = 0;
 228
 229        devname[0] = 0;
 230
 231        if (oldval && oldlenp) {
 232                if (get_user(len, oldlenp))
 233                        return -EFAULT;
 234                if (len) {
 235                        dev = dn_dev_get_default();
 236                        if (dev) {
 237                                strcpy(devname, dev->name);
 238                                dev_put(dev);
 239                        }
 240
 241                        namel = strlen(devname) + 1;
 242                        if (len > namel) len = namel;
 243
 244                        if (copy_to_user(oldval, devname, len))
 245                                return -EFAULT;
 246
 247                        if (put_user(len, oldlenp))
 248                                return -EFAULT;
 249                }
 250        }
 251
 252        if (newval && newlen) {
 253                if (newlen > 16)
 254                        return -E2BIG;
 255
 256                if (copy_from_user(devname, newval, newlen))
 257                        return -EFAULT;
 258
 259                devname[newlen] = 0;
 260
 261                dev = dev_get_by_name(&init_net, devname);
 262                if (dev == NULL)
 263                        return -ENODEV;
 264
 265                rv = -ENODEV;
 266                if (dev->dn_ptr != NULL)
 267                        rv = dn_dev_set_default(dev, 1);
 268                if (rv)
 269                        dev_put(dev);
 270        }
 271
 272        return rv;
 273}
 274
 275
 276static int dn_def_dev_handler(ctl_table *table, int write,
 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(&init_net, 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_MEM,
 433                .procname = "decnet_mem",
 434                .data = &sysctl_decnet_mem,
 435                .maxlen = sizeof(sysctl_decnet_mem),
 436                .mode = 0644,
 437                .proc_handler = proc_dointvec,
 438                .strategy = sysctl_intvec,
 439        },
 440        {
 441                .ctl_name = NET_DECNET_RMEM,
 442                .procname = "decnet_rmem",
 443                .data = &sysctl_decnet_rmem,
 444                .maxlen = sizeof(sysctl_decnet_rmem),
 445                .mode = 0644,
 446                .proc_handler = proc_dointvec,
 447                .strategy = sysctl_intvec,
 448        },
 449        {
 450                .ctl_name = NET_DECNET_WMEM,
 451                .procname = "decnet_wmem",
 452                .data = &sysctl_decnet_wmem,
 453                .maxlen = sizeof(sysctl_decnet_wmem),
 454                .mode = 0644,
 455                .proc_handler = proc_dointvec,
 456                .strategy = sysctl_intvec,
 457        },
 458        {
 459                .ctl_name = NET_DECNET_DEBUG_LEVEL,
 460                .procname = "debug",
 461                .data = &decnet_debug_level,
 462                .maxlen = sizeof(int),
 463                .mode = 0644,
 464                .proc_handler = proc_dointvec,
 465                .strategy = sysctl_intvec,
 466        },
 467        {0}
 468};
 469
 470static struct ctl_path dn_path[] = {
 471        { .procname = "net", .ctl_name = CTL_NET, },
 472        { .procname = "decnet", .ctl_name = NET_DECNET, },
 473        { }
 474};
 475
 476void dn_register_sysctl(void)
 477{
 478        dn_table_header = register_sysctl_paths(dn_path, dn_table);
 479}
 480
 481void dn_unregister_sysctl(void)
 482{
 483        unregister_sysctl_table(dn_table_header);
 484}
 485
 486#else  /* CONFIG_SYSCTL */
 487void dn_unregister_sysctl(void)
 488{
 489}
 490void dn_register_sysctl(void)
 491{
 492}
 493
 494#endif
 495