busybox/networking/vconfig.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * vconfig implementation for busybox
   4 *
   5 * Copyright (C) 2001  Manuel Novoa III  <mjn3@codepoet.org>
   6 *
   7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
   8 */
   9
  10/* BB_AUDIT SUSv3 N/A */
  11
  12#include "libbb.h"
  13#include <net/if.h>
  14
  15/* Stuff from linux/if_vlan.h, kernel version 2.4.23 */
  16enum vlan_ioctl_cmds {
  17        ADD_VLAN_CMD,
  18        DEL_VLAN_CMD,
  19        SET_VLAN_INGRESS_PRIORITY_CMD,
  20        SET_VLAN_EGRESS_PRIORITY_CMD,
  21        GET_VLAN_INGRESS_PRIORITY_CMD,
  22        GET_VLAN_EGRESS_PRIORITY_CMD,
  23        SET_VLAN_NAME_TYPE_CMD,
  24        SET_VLAN_FLAG_CMD
  25};
  26enum vlan_name_types {
  27        VLAN_NAME_TYPE_PLUS_VID, /* Name will look like:  vlan0005 */
  28        VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like:  eth1.0005 */
  29        VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like:  vlan5 */
  30        VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like:  eth0.5 */
  31        VLAN_NAME_TYPE_HIGHEST
  32};
  33
  34struct vlan_ioctl_args {
  35        int cmd; /* Should be one of the vlan_ioctl_cmds enum above. */
  36        char device1[24];
  37
  38        union {
  39                char device2[24];
  40                int VID;
  41                unsigned int skb_priority;
  42                unsigned int name_type;
  43                unsigned int bind_type;
  44                unsigned int flag; /* Matches vlan_dev_info flags */
  45        } u;
  46
  47        short vlan_qos;
  48};
  49
  50#define VLAN_GROUP_ARRAY_LEN 4096
  51#define SIOCSIFVLAN     0x8983          /* Set 802.1Q VLAN options */
  52
  53/* On entry, table points to the length of the current string
  54 * plus NUL terminator plus data length for the subsequent entry.
  55 * The return value is the last data entry for the matching string. */
  56static const char *xfind_str(const char *table, const char *str)
  57{
  58        while (strcasecmp(str, table+1) != 0) {
  59                table += table[0];
  60                if (!*table) {
  61                        bb_show_usage();
  62                }
  63        }
  64        return table - 1;
  65}
  66
  67static const char cmds[] ALIGN1 = {
  68        4, ADD_VLAN_CMD, 7,
  69        'a', 'd', 'd', 0,
  70        3, DEL_VLAN_CMD, 7,
  71        'r', 'e', 'm', 0,
  72        3, SET_VLAN_NAME_TYPE_CMD, 17,
  73        's', 'e', 't', '_',
  74        'n', 'a', 'm', 'e', '_',
  75        't', 'y', 'p', 'e', 0,
  76        5, SET_VLAN_FLAG_CMD, 12,
  77        's', 'e', 't', '_',
  78        'f', 'l', 'a', 'g', 0,
  79        5, SET_VLAN_EGRESS_PRIORITY_CMD, 18,
  80        's', 'e', 't', '_',
  81        'e', 'g', 'r', 'e', 's', 's', '_',
  82        'm', 'a', 'p', 0,
  83        5, SET_VLAN_INGRESS_PRIORITY_CMD, 16,
  84        's', 'e', 't', '_',
  85        'i', 'n', 'g', 'r', 'e', 's', 's', '_',
  86        'm', 'a', 'p', 0,
  87};
  88
  89static const char name_types[] ALIGN1 = {
  90        VLAN_NAME_TYPE_PLUS_VID, 16,
  91        'V', 'L', 'A', 'N',
  92        '_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
  93        0,
  94        VLAN_NAME_TYPE_PLUS_VID_NO_PAD, 22,
  95        'V', 'L', 'A', 'N',
  96        '_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
  97        '_', 'N', 'O', '_', 'P', 'A', 'D', 0,
  98        VLAN_NAME_TYPE_RAW_PLUS_VID, 15,
  99        'D', 'E', 'V',
 100        '_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
 101        0,
 102        VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, 20,
 103        'D', 'E', 'V',
 104        '_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
 105        '_', 'N', 'O', '_', 'P', 'A', 'D', 0,
 106};
 107
 108static const char conf_file_name[] ALIGN1 = "/proc/net/vlan/config";
 109
 110int vconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 111int vconfig_main(int argc, char **argv)
 112{
 113        struct vlan_ioctl_args ifr;
 114        const char *p;
 115        int fd;
 116
 117        if (argc < 3) {
 118                bb_show_usage();
 119        }
 120
 121        /* Don't bother closing the filedes.  It will be closed on cleanup. */
 122        /* Will die if 802.1q is not present */
 123        xopen(conf_file_name, O_RDONLY);
 124
 125        memset(&ifr, 0, sizeof(ifr));
 126
 127        ++argv;
 128        p = xfind_str(cmds+2, *argv);
 129        ifr.cmd = *p;
 130        if (argc != p[-1]) {
 131                bb_show_usage();
 132        }
 133
 134        if (ifr.cmd == SET_VLAN_NAME_TYPE_CMD) { /* set_name_type */
 135                ifr.u.name_type = *xfind_str(name_types+1, argv[1]);
 136        } else {
 137                strncpy_IFNAMSIZ(ifr.device1, argv[1]);
 138                p = argv[2];
 139
 140                /* I suppose one could try to combine some of the function calls below,
 141                 * since ifr.u.flag, ifr.u.VID, and ifr.u.skb_priority are all same-sized
 142                 * (unsigned) int members of a unions.  But because of the range checking,
 143                 * doing so wouldn't save that much space and would also make maintainence
 144                 * more of a pain. */
 145                if (ifr.cmd == SET_VLAN_FLAG_CMD) { /* set_flag */
 146                        ifr.u.flag = xatoul_range(p, 0, 1);
 147                        /* DM: in order to set reorder header, qos must be set */
 148                        ifr.vlan_qos = xatoul_range(argv[3], 0, 7);
 149                } else if (ifr.cmd == ADD_VLAN_CMD) { /* add */
 150                        ifr.u.VID = xatoul_range(p, 0, VLAN_GROUP_ARRAY_LEN-1);
 151                } else if (ifr.cmd != DEL_VLAN_CMD) { /* set_{egress|ingress}_map */
 152                        ifr.u.skb_priority = xatou(p);
 153                        ifr.vlan_qos = xatoul_range(argv[3], 0, 7);
 154                }
 155        }
 156
 157        fd = xsocket(AF_INET, SOCK_STREAM, 0);
 158        ioctl_or_perror_and_die(fd, SIOCSIFVLAN, &ifr,
 159                                                "ioctl error for %s", *argv);
 160
 161        return 0;
 162}
 163