brctl.c 8.5 KB

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