Home | History | Annotate | Download | only in pending
      1 /* brctl.c - ethernet bridge control
      2  *
      3  * Copyright 2013 Ashwini Kumar <ak.ashwini1981 (at) gmail.com>
      4  * Copyright 2013 Kyungwan Han <asura321 (at) gmail.com>
      5  *
      6  * No Standard
      7 
      8 USE_BRCTL(NEWTOY(brctl, "<1", TOYFLAG_USR|TOYFLAG_SBIN))
      9 
     10 config BRCTL
     11   bool "brctl"
     12   default n
     13   help
     14     usage: brctl COMMAND [BRIDGE [INTERFACE]]
     15 
     16     Manage ethernet bridges
     17 
     18     Commands:
     19     show                  Show a list of bridges
     20     addbr BRIDGE          Create BRIDGE
     21     delbr BRIDGE          Delete BRIDGE
     22     addif BRIDGE IFACE    Add IFACE to BRIDGE
     23     delif BRIDGE IFACE    Delete IFACE from BRIDGE
     24     setageing BRIDGE TIME Set ageing time
     25     setfd BRIDGE TIME     Set bridge forward delay
     26     sethello BRIDGE TIME  Set hello time
     27     setmaxage BRIDGE TIME Set max message age
     28     setpathcost BRIDGE PORT COST   Set path cost
     29     setportprio BRIDGE PORT PRIO   Set port priority
     30     setbridgeprio BRIDGE PRIO      Set bridge priority
     31     stp BRIDGE [1/yes/on|0/no/off] STP on/off
     32 */
     33 
     34 #define FOR_brctl
     35 #include "toys.h"
     36 #include <linux/if_bridge.h>
     37 
     38 GLOBALS(
     39     int sockfd;
     40 )
     41 #define MAX_BRIDGES 1024 //same is no of ports supported
     42 
     43 static void get_ports(char *bridge, int *indices)
     44 {
     45   struct ifreq ifr;
     46   int ifindices[MAX_BRIDGES];
     47   unsigned long args[4] = { BRCTL_GET_PORT_LIST,
     48     (unsigned long) ifindices, MAX_BRIDGES, 0 };
     49 
     50   memset(ifindices, 0, MAX_BRIDGES);
     51   args[1] = (unsigned long)ifindices;
     52   xstrncpy(ifr.ifr_name, bridge, IFNAMSIZ);
     53   ifr.ifr_data = (char *)args;
     54   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
     55   if (indices) memcpy(indices, ifindices, sizeof(ifindices));
     56 }
     57 
     58 void get_br_info(char *bridge, struct __bridge_info *info)
     59 {
     60   struct ifreq ifr;
     61   unsigned long args[4] = { BRCTL_GET_BRIDGE_INFO,
     62     (unsigned long) info, 0, 0 };
     63 
     64   memset(info, 0, sizeof(*info));
     65   xstrncpy(ifr.ifr_name, bridge, IFNAMSIZ);
     66   ifr.ifr_data = (char *)args;
     67 
     68   if (ioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr) < 0) {
     69     perror_msg("%s: can't get info %s\n", bridge, strerror(errno));
     70     return;
     71   }
     72 }
     73 
     74 void br_show(char **argv)
     75 {
     76   struct __bridge_info info;
     77   int num, cnt, i, j, ifindices[MAX_BRIDGES], pindices[MAX_BRIDGES];
     78   unsigned long args[4] = { BRCTL_GET_BRIDGES,
     79     (unsigned long)ifindices, MAX_BRIDGES,0 };
     80   char br[IF_NAMESIZE], ifn[IF_NAMESIZE];
     81 
     82   num = ioctl(TT.sockfd, SIOCGIFBR, args); //ret is num of bridges found
     83   if (num < 0) error_exit("get bridges fail");
     84   printf("bridge name\tbridge id\t\tSTP enabled\tinterfaces\n");
     85 
     86   for (i = 0; i < num; i++) {
     87     unsigned char *id;
     88 
     89     if (!if_indextoname(ifindices[i], br)) perror_exit("interface not found");
     90     get_br_info(br, &info);
     91     id = (unsigned char*)&(info.bridge_id);
     92     printf("%s\t\t",br);
     93     printf("%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x", id[0], id[1],
     94         id[2], id[3], id[4], id[5], id[6], id[7]);
     95     printf("\t%s\t\t",(info.stp_enabled)?"yes" : "no");
     96 
     97     memset(pindices, 0, sizeof(pindices));
     98     get_ports(br, pindices);
     99     for (j = 0, cnt = 0; j < MAX_BRIDGES; j++) {
    100       if (!pindices[j]) continue;
    101       if (!if_indextoname(pindices[j], ifn)) {
    102         error_msg("no name for index :%d", pindices[j]);
    103         continue;
    104       }
    105       if (cnt) printf("\n\t\t\t\t\t\t\t");
    106       printf("%s", ifn);
    107       cnt++;
    108     }
    109     xputc('\n');
    110   }
    111 }
    112 
    113 void br_addbr(char **argv)
    114 {
    115   char br[IFNAMSIZ];
    116   unsigned long args[4] = {BRCTL_ADD_BRIDGE, (unsigned long) br, 0, 0};
    117 
    118 #ifdef SIOCBRADDBR
    119   xioctl(TT.sockfd, SIOCBRADDBR, argv[0]);
    120 #else
    121   xstrncpy(br, argv[0], IFNAMSIZ);
    122   xioctl(TT.sockfd, SIOCSIFBR, args);
    123 #endif
    124 }
    125 
    126 void br_delbr(char **argv)
    127 {
    128   char br[IFNAMSIZ];
    129   unsigned long args[4] = {BRCTL_DEL_BRIDGE, (unsigned long) br, 0, 0};
    130 
    131 #ifdef SIOCBRDELBR
    132   xioctl(TT.sockfd, SIOCBRDELBR, argv[0]);
    133 #else
    134   xstrncpy(br, argv[0], IFNAMSIZ);
    135   xioctl(TT.sockfd, SIOCSIFBR, args);
    136 #endif
    137 }
    138 
    139 void br_addif(char **argv)
    140 {
    141   int index;
    142   struct ifreq ifr;
    143   unsigned long args[4] = {BRCTL_ADD_IF, 0, 0, 0};
    144 
    145   if (!(index = if_nametoindex(argv[1]))) perror_exit("interface %s", argv[1]);
    146 #ifdef SIOCBRADDIF
    147   ifr.ifr_ifindex = index;
    148   xioctl(TT.sockfd, SIOCBRADDIF, &ifr);
    149 #else
    150   args[1] = index;
    151   xstrncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
    152   ifr.ifr_data = (char *)args;
    153   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
    154 #endif
    155 }
    156 
    157 void br_delif(char **argv)
    158 {
    159   int index;
    160   struct ifreq ifr;
    161   unsigned long args[4] = {BRCTL_DEL_IF, 0, 0, 0};
    162 
    163   if (!(index = if_nametoindex(argv[1]))) perror_exit("interface %s",argv[1]);
    164 #ifdef SIOCBRDELIF
    165   ifr.ifr_ifindex = ifindex;
    166   xioctl(TT.sockfd, SIOCBRDELIF, &ifr);
    167 #else
    168   args[1] = index;
    169   xstrncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
    170   ifr.ifr_data = (char *)args;
    171   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
    172 #endif
    173 }
    174 
    175 static void strtotimeval(struct timeval *tv, char *time)
    176 {
    177   double secs;
    178 
    179   if (sscanf(time, "%lf", &secs) != 1) error_exit("time format not proper");
    180   tv->tv_sec = secs;
    181   tv->tv_usec = 1000000 * (secs - tv->tv_sec);
    182 }
    183 
    184 static unsigned long tv_to_jify(struct timeval *tv)
    185 {
    186   unsigned long long jify;
    187 
    188   jify = 1000000ULL * tv->tv_sec + tv->tv_usec;
    189   return (jify/10000);
    190 }
    191 
    192 void set_time(char *br, unsigned long cmd, unsigned long val)
    193 {
    194   struct ifreq ifr;
    195   unsigned long args[4] = {cmd, val, 0, 0};
    196 
    197   xstrncpy(ifr.ifr_name, br, IFNAMSIZ);
    198   ifr.ifr_data = (char *)args;
    199   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
    200 }
    201 
    202 void br_set_ageing_time(char **argv)
    203 {
    204   struct timeval tv;
    205 
    206   strtotimeval(&tv, argv[1]);
    207   set_time(argv[0], BRCTL_SET_AGEING_TIME, tv_to_jify(&tv));
    208 }
    209 
    210 void br_set_fwd_delay(char **argv)
    211 {
    212   struct timeval tv;
    213 
    214   strtotimeval(&tv, argv[1]);
    215   set_time(argv[0], BRCTL_SET_BRIDGE_FORWARD_DELAY, tv_to_jify(&tv));
    216 }
    217 
    218 void br_set_hello_time(char **argv)
    219 {
    220   struct timeval tv;
    221 
    222   strtotimeval(&tv, argv[1]);
    223   set_time(argv[0], BRCTL_SET_BRIDGE_HELLO_TIME, tv_to_jify(&tv));
    224 }
    225 
    226 void br_set_max_age(char **argv)
    227 {
    228   struct timeval tv;
    229 
    230   strtotimeval(&tv, argv[1]);
    231   set_time(argv[0], BRCTL_SET_BRIDGE_MAX_AGE, tv_to_jify(&tv));
    232 }
    233 
    234 void br_set_bridge_prio(char **argv)
    235 {
    236   int prio;
    237 
    238   if (sscanf(argv[1], "%i", &prio) != 1) error_exit("prio not proper");
    239   set_time(argv[0], BRCTL_SET_BRIDGE_PRIORITY, prio);
    240 }
    241 
    242 void br_set_stp(char **argv)
    243 {
    244   int i;
    245   struct stp {
    246     char *n;
    247     int set;
    248   } ss[] = {{"1", 1}, {"yes", 1},{"on", 1},
    249     {"0", 0}, {"no", 0},{"off", 0}};
    250 
    251   for (i = 0; i < ARRAY_LEN(ss); i++) {
    252     if (!strcmp(ss[i].n, argv[1])) break;
    253   }
    254   if (i >= ARRAY_LEN(ss)) error_exit("invalid stp state");
    255   set_time(argv[0], BRCTL_SET_BRIDGE_STP_STATE, ss[i].set);
    256 }
    257 
    258 void set_cost_prio(char *br, char *port, unsigned long cmd, unsigned long val)
    259 {
    260   struct ifreq ifr;
    261   int i, index, pindices[MAX_BRIDGES];
    262   unsigned long args[4] = {cmd, 0, val, 0};
    263 
    264   if (!(index = if_nametoindex(port))) error_exit("invalid port");
    265 
    266   memset(pindices, 0, sizeof(pindices));
    267   get_ports(br, pindices);
    268   for (i = 0; i < MAX_BRIDGES; i++) {
    269     if (index == pindices[i]) break;
    270   }
    271   if (i >= MAX_BRIDGES) error_exit("%s not in bridge", port);
    272   args[1] = i;
    273   xstrncpy(ifr.ifr_name, br, IFNAMSIZ);
    274   ifr.ifr_data = (char *)args;
    275   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
    276 }
    277 
    278 void br_set_path_cost(char **argv)
    279 {
    280   int cost;
    281 
    282   cost = atolx_range(argv[2], 0, INT_MAX);
    283   set_cost_prio(argv[0], argv[1], BRCTL_SET_PATH_COST, cost);
    284 }
    285 
    286 void br_set_port_prio(char **argv)
    287 {
    288   int prio;
    289 
    290   prio = atolx_range(argv[2], 0, INT_MAX);
    291   set_cost_prio(argv[0], argv[1], BRCTL_SET_PORT_PRIORITY, prio);
    292 
    293 }
    294 
    295 void brctl_main(void)
    296 {
    297   int i;
    298   struct cmds {
    299     char *cmd;
    300     int nargs;
    301     void (*f)(char **argv);
    302   } cc[] = {{"show", 0, br_show},
    303     {"addbr", 1, br_addbr}, {"delbr", 1, br_delbr},
    304     {"addif", 2, br_addif}, {"delif", 2, br_delif},
    305     {"setageing", 2, br_set_ageing_time},
    306     {"setfd", 2, br_set_fwd_delay},
    307     {"sethello", 2, br_set_hello_time},
    308     {"setmaxage", 2, br_set_max_age},
    309     {"setpathcost", 3, br_set_path_cost},
    310     {"setportprio", 3, br_set_port_prio},
    311     {"setbridgeprio", 2, br_set_bridge_prio},
    312     {"stp", 2, br_set_stp},
    313   };
    314 
    315   TT.sockfd = xsocket(AF_INET, SOCK_STREAM, 0);
    316   while (*toys.optargs) {
    317     for (i = 0; i < ARRAY_LEN(cc); i++) {
    318       struct cmds *t = cc + i;
    319 
    320       if (strcmp(t->cmd, *toys.optargs)) continue;
    321 
    322       toys.optargs++, toys.optc--;
    323       if (toys.optc < t->nargs) help_exit("check args");
    324       t->f(toys.optargs);
    325       toys.optargs += t->nargs;
    326       toys.optc -= t->nargs;
    327       break;
    328     }
    329 
    330     if (i == ARRAY_LEN(cc)) help_exit("invalid option '%s'", *toys.optargs);
    331   }
    332   xclose(TT.sockfd);
    333 }
    334