123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- /* brctl.c - ethernet bridge control
- *
- * Copyright 2013 Ashwini Kumar <ak.ashwini1981@gmail.com>
- * Copyright 2013 Kyungwan Han <asura321@gmail.com>
- *
- * No Standard
- USE_BRCTL(NEWTOY(brctl, "<1", TOYFLAG_USR|TOYFLAG_SBIN))
- config BRCTL
- bool "brctl"
- default n
- help
- usage: brctl COMMAND [BRIDGE [INTERFACE]]
- Manage ethernet bridges
- Commands:
- show Show a list of bridges
- addbr BRIDGE Create BRIDGE
- delbr BRIDGE Delete BRIDGE
- addif BRIDGE IFACE Add IFACE to BRIDGE
- delif BRIDGE IFACE Delete IFACE from BRIDGE
- setageing BRIDGE TIME Set ageing time
- setfd BRIDGE TIME Set bridge forward delay
- sethello BRIDGE TIME Set hello time
- setmaxage BRIDGE TIME Set max message age
- setpathcost BRIDGE PORT COST Set path cost
- setportprio BRIDGE PORT PRIO Set port priority
- setbridgeprio BRIDGE PRIO Set bridge priority
- stp BRIDGE [1/yes/on|0/no/off] STP on/off
- */
- #define FOR_brctl
- #include "toys.h"
- #include <linux/if_bridge.h>
- GLOBALS(
- int sockfd;
- )
- #define MAX_BRIDGES 1024 //same is no of ports supported
- static void get_ports(char *bridge, int *indices)
- {
- struct ifreq ifr;
- int ifindices[MAX_BRIDGES];
- unsigned long args[4] = { BRCTL_GET_PORT_LIST,
- (unsigned long) ifindices, MAX_BRIDGES, 0 };
- memset(ifindices, 0, MAX_BRIDGES);
- args[1] = (unsigned long)ifindices;
- xstrncpy(ifr.ifr_name, bridge, IFNAMSIZ);
- ifr.ifr_data = (char *)args;
- xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
- if (indices) memcpy(indices, ifindices, sizeof(ifindices));
- }
- void get_br_info(char *bridge, struct __bridge_info *info)
- {
- struct ifreq ifr;
- unsigned long args[4] = { BRCTL_GET_BRIDGE_INFO,
- (unsigned long) info, 0, 0 };
- memset(info, 0, sizeof(*info));
- xstrncpy(ifr.ifr_name, bridge, IFNAMSIZ);
- ifr.ifr_data = (char *)args;
- if (ioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr) < 0) {
- perror_msg("%s: can't get info %s\n", bridge, strerror(errno));
- return;
- }
- }
- void br_show(char **argv)
- {
- struct __bridge_info info;
- int num, cnt, i, j, ifindices[MAX_BRIDGES], pindices[MAX_BRIDGES];
- unsigned long args[4] = { BRCTL_GET_BRIDGES,
- (unsigned long)ifindices, MAX_BRIDGES,0 };
- char br[IF_NAMESIZE], ifn[IF_NAMESIZE];
- num = ioctl(TT.sockfd, SIOCGIFBR, args); //ret is num of bridges found
- if (num < 0) error_exit("get bridges fail");
- printf("bridge name\tbridge id\t\tSTP enabled\tinterfaces\n");
- for (i = 0; i < num; i++) {
- unsigned char *id;
- if (!if_indextoname(ifindices[i], br)) perror_exit("interface not found");
- get_br_info(br, &info);
- id = (unsigned char*)&(info.bridge_id);
- printf("%s\t\t",br);
- printf("%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x", id[0], id[1],
- id[2], id[3], id[4], id[5], id[6], id[7]);
- printf("\t%s\t\t",(info.stp_enabled)?"yes" : "no");
- memset(pindices, 0, sizeof(pindices));
- get_ports(br, pindices);
- for (j = 0, cnt = 0; j < MAX_BRIDGES; j++) {
- if (!pindices[j]) continue;
- if (!if_indextoname(pindices[j], ifn)) {
- error_msg("no name for index :%d", pindices[j]);
- continue;
- }
- if (cnt) printf("\n\t\t\t\t\t\t\t");
- printf("%s", ifn);
- cnt++;
- }
- xputc('\n');
- }
- }
- void br_addbr(char **argv)
- {
- char br[IFNAMSIZ];
- unsigned long args[4] = {BRCTL_ADD_BRIDGE, (unsigned long) br, 0, 0};
- #ifdef SIOCBRADDBR
- xioctl(TT.sockfd, SIOCBRADDBR, argv[0]);
- #else
- xstrncpy(br, argv[0], IFNAMSIZ);
- xioctl(TT.sockfd, SIOCSIFBR, args);
- #endif
- }
- void br_delbr(char **argv)
- {
- char br[IFNAMSIZ];
- unsigned long args[4] = {BRCTL_DEL_BRIDGE, (unsigned long) br, 0, 0};
- #ifdef SIOCBRDELBR
- xioctl(TT.sockfd, SIOCBRDELBR, argv[0]);
- #else
- xstrncpy(br, argv[0], IFNAMSIZ);
- xioctl(TT.sockfd, SIOCSIFBR, args);
- #endif
- }
- void br_addif(char **argv)
- {
- int index;
- struct ifreq ifr;
- unsigned long args[4] = {BRCTL_ADD_IF, 0, 0, 0};
- if (!(index = if_nametoindex(argv[1]))) perror_exit("interface %s", argv[1]);
- #ifdef SIOCBRADDIF
- ifr.ifr_ifindex = index;
- xioctl(TT.sockfd, SIOCBRADDIF, &ifr);
- #else
- args[1] = index;
- xstrncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
- ifr.ifr_data = (char *)args;
- xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
- #endif
- }
- void br_delif(char **argv)
- {
- int index;
- struct ifreq ifr;
- unsigned long args[4] = {BRCTL_DEL_IF, 0, 0, 0};
- if (!(index = if_nametoindex(argv[1]))) perror_exit("interface %s",argv[1]);
- #ifdef SIOCBRDELIF
- ifr.ifr_ifindex = ifindex;
- xioctl(TT.sockfd, SIOCBRDELIF, &ifr);
- #else
- args[1] = index;
- xstrncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
- ifr.ifr_data = (char *)args;
- xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
- #endif
- }
- static void strtotimeval(struct timeval *tv, char *time)
- {
- double secs;
- if (sscanf(time, "%lf", &secs) != 1) error_exit("time format not proper");
- tv->tv_sec = secs;
- tv->tv_usec = 1000000 * (secs - tv->tv_sec);
- }
- static unsigned long tv_to_jify(struct timeval *tv)
- {
- unsigned long long jify;
- jify = 1000000ULL * tv->tv_sec + tv->tv_usec;
- return (jify/10000);
- }
- void set_time(char *br, unsigned long cmd, unsigned long val)
- {
- struct ifreq ifr;
- unsigned long args[4] = {cmd, val, 0, 0};
- xstrncpy(ifr.ifr_name, br, IFNAMSIZ);
- ifr.ifr_data = (char *)args;
- xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
- }
- void br_set_ageing_time(char **argv)
- {
- struct timeval tv;
- strtotimeval(&tv, argv[1]);
- set_time(argv[0], BRCTL_SET_AGEING_TIME, tv_to_jify(&tv));
- }
- void br_set_fwd_delay(char **argv)
- {
- struct timeval tv;
- strtotimeval(&tv, argv[1]);
- set_time(argv[0], BRCTL_SET_BRIDGE_FORWARD_DELAY, tv_to_jify(&tv));
- }
- void br_set_hello_time(char **argv)
- {
- struct timeval tv;
- strtotimeval(&tv, argv[1]);
- set_time(argv[0], BRCTL_SET_BRIDGE_HELLO_TIME, tv_to_jify(&tv));
- }
- void br_set_max_age(char **argv)
- {
- struct timeval tv;
- strtotimeval(&tv, argv[1]);
- set_time(argv[0], BRCTL_SET_BRIDGE_MAX_AGE, tv_to_jify(&tv));
- }
- void br_set_bridge_prio(char **argv)
- {
- int prio;
- if (sscanf(argv[1], "%i", &prio) != 1) error_exit("prio not proper");
- set_time(argv[0], BRCTL_SET_BRIDGE_PRIORITY, prio);
- }
- void br_set_stp(char **argv)
- {
- int i;
- struct stp {
- char *n;
- int set;
- } ss[] = {{"1", 1}, {"yes", 1},{"on", 1},
- {"0", 0}, {"no", 0},{"off", 0}};
- for (i = 0; i < ARRAY_LEN(ss); i++) {
- if (!strcmp(ss[i].n, argv[1])) break;
- }
- if (i >= ARRAY_LEN(ss)) error_exit("invalid stp state");
- set_time(argv[0], BRCTL_SET_BRIDGE_STP_STATE, ss[i].set);
- }
- void set_cost_prio(char *br, char *port, unsigned long cmd, unsigned long val)
- {
- struct ifreq ifr;
- int i, index, pindices[MAX_BRIDGES];
- unsigned long args[4] = {cmd, 0, val, 0};
-
- if (!(index = if_nametoindex(port))) error_exit("invalid port");
-
- memset(pindices, 0, sizeof(pindices));
- get_ports(br, pindices);
- for (i = 0; i < MAX_BRIDGES; i++) {
- if (index == pindices[i]) break;
- }
- if (i >= MAX_BRIDGES) error_exit("%s not in bridge", port);
- args[1] = i;
- xstrncpy(ifr.ifr_name, br, IFNAMSIZ);
- ifr.ifr_data = (char *)args;
- xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
- }
- void br_set_path_cost(char **argv)
- {
- int cost;
- cost = atolx_range(argv[2], 0, INT_MAX);
- set_cost_prio(argv[0], argv[1], BRCTL_SET_PATH_COST, cost);
- }
- void br_set_port_prio(char **argv)
- {
- int prio;
- prio = atolx_range(argv[2], 0, INT_MAX);
- set_cost_prio(argv[0], argv[1], BRCTL_SET_PORT_PRIORITY, prio);
- }
- void brctl_main(void)
- {
- int i;
- struct cmds {
- char *cmd;
- int nargs;
- void (*f)(char **argv);
- } cc[] = {{"show", 0, br_show},
- {"addbr", 1, br_addbr}, {"delbr", 1, br_delbr},
- {"addif", 2, br_addif}, {"delif", 2, br_delif},
- {"setageing", 2, br_set_ageing_time},
- {"setfd", 2, br_set_fwd_delay},
- {"sethello", 2, br_set_hello_time},
- {"setmaxage", 2, br_set_max_age},
- {"setpathcost", 3, br_set_path_cost},
- {"setportprio", 3, br_set_port_prio},
- {"setbridgeprio", 2, br_set_bridge_prio},
- {"stp", 2, br_set_stp},
- };
- TT.sockfd = xsocket(AF_INET, SOCK_STREAM, 0);
- while (*toys.optargs) {
- for (i = 0; i < ARRAY_LEN(cc); i++) {
- struct cmds *t = cc + i;
- if (strcmp(t->cmd, *toys.optargs)) continue;
- toys.optargs++, toys.optc--;
- if (toys.optc < t->nargs) help_exit("check args");
- t->f(toys.optargs);
- toys.optargs += t->nargs;
- toys.optc -= t->nargs;
- break;
- }
- if (i == ARRAY_LEN(cc)) help_exit("invalid option '%s'", *toys.optargs);
- }
- xclose(TT.sockfd);
- }
|