toybox/toys/pending/brctl.c
<<
>>
Prefs
   1/* brctl.c - ethernet bridge control
   2 *
   3 * Copyright 2013 Ashwini Kumar <ak.ashwini1981@gmail.com>
   4 * Copyright 2013 Kyungwan Han <asura321@gmail.com>
   5 *
   6 * No Standard
   7
   8USE_BRCTL(NEWTOY(brctl, "<1", TOYFLAG_USR|TOYFLAG_SBIN))
   9
  10config 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
  38GLOBALS(
  39    int sockfd;
  40)
  41#define MAX_BRIDGES 1024 //same is no of ports supported
  42
  43static 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
  58void 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
  74void 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
 113void 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
 126void 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
 139void 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
 157void 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
 175static 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
 184static 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
 192void 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
 202void 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
 210void 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
 218void 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
 226void 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
 234void 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
 242void 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
 258void 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
 278void 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
 286void 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
 295void 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