blob: 586ca9b0c96a48417d2f1a268b49f7221856b035 [file] [log] [blame]
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Small implementation of brctl for busybox.
4 *
Bernhard Reutner-Fischer6c4dade2008-09-25 12:13:34 +00005 * Copyright (C) 2008 by Bernhard Reutner-Fischer
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +00006 *
Bernhard Reutner-Fischer2b11fb42008-01-14 16:10:11 +00007 * Some helper functions from bridge-utils are
8 * Copyright (C) 2000 Lennert Buytenhek
9 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +020010 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +000011 */
Denys Vlasenko47367e12016-11-23 09:05:14 +010012//config:config BRCTL
Denys Vlasenko4eed2c62017-07-18 22:01:24 +020013//config: bool "brctl (4.7 kb)"
Denys Vlasenko47367e12016-11-23 09:05:14 +010014//config: default y
15//config: select PLATFORM_LINUX
16//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +020017//config: Manage ethernet bridges.
18//config: Supports addbr/delbr and addif/delif.
Denys Vlasenko47367e12016-11-23 09:05:14 +010019//config:
20//config:config FEATURE_BRCTL_FANCY
21//config: bool "Fancy options"
22//config: default y
23//config: depends on BRCTL
24//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +020025//config: Add support for extended option like:
26//config: setageing, setfd, sethello, setmaxage,
27//config: setpathcost, setportprio, setbridgeprio,
28//config: stp
29//config: This adds about 600 bytes.
Denys Vlasenko47367e12016-11-23 09:05:14 +010030//config:
31//config:config FEATURE_BRCTL_SHOW
32//config: bool "Support show"
33//config: default y
34//config: depends on BRCTL && FEATURE_BRCTL_FANCY
35//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +020036//config: Add support for option which prints the current config:
37//config: show
Denys Vlasenko47367e12016-11-23 09:05:14 +010038
Denys Vlasenko86e07f62017-08-06 20:14:02 +020039//applet:IF_BRCTL(APPLET_NOEXEC(brctl, brctl, BB_DIR_USR_SBIN, BB_SUID_DROP, brctl))
Denys Vlasenko47367e12016-11-23 09:05:14 +010040
41//kbuild:lib-$(CONFIG_BRCTL) += brctl.o
Pere Orga5bc8c002011-04-11 03:29:49 +020042
43//usage:#define brctl_trivial_usage
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +020044//usage: "COMMAND [BRIDGE [ARGS]]"
Pere Orga5bc8c002011-04-11 03:29:49 +020045//usage:#define brctl_full_usage "\n\n"
Denys Vlasenko29458222019-04-13 15:48:31 +020046//usage: "Manage ethernet bridges"
Pere Orga5bc8c002011-04-11 03:29:49 +020047//usage: "\nCommands:"
48//usage: IF_FEATURE_BRCTL_SHOW(
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +020049//usage: "\n show [BRIDGE]... Show bridges"
Pere Orga5bc8c002011-04-11 03:29:49 +020050//usage: )
51//usage: "\n addbr BRIDGE Create BRIDGE"
52//usage: "\n delbr BRIDGE Delete BRIDGE"
53//usage: "\n addif BRIDGE IFACE Add IFACE to BRIDGE"
54//usage: "\n delif BRIDGE IFACE Delete IFACE from BRIDGE"
55//usage: IF_FEATURE_BRCTL_FANCY(
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +020056//usage: "\n stp BRIDGE 1/yes/on|0/no/off STP on/off"
57//usage: "\n setageing BRIDGE SECONDS Set ageing time"
58//usage: "\n setfd BRIDGE SECONDS Set bridge forward delay"
59//usage: "\n sethello BRIDGE SECONDS Set hello time"
60//usage: "\n setmaxage BRIDGE SECONDS Set max message age"
Pere Orga5bc8c002011-04-11 03:29:49 +020061//usage: "\n setbridgeprio BRIDGE PRIO Set bridge priority"
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +020062//usage: "\n setportprio BRIDGE IFACE PRIO Set port priority"
63//usage: "\n setpathcost BRIDGE IFACE COST Set path cost"
Pere Orga5bc8c002011-04-11 03:29:49 +020064//usage: )
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +020065// Not yet implemented:
Denys Vlasenko94356082019-04-13 14:17:55 +020066// hairpin BRIDGE IFACE on|off Hairpin on/off
67// showmacs BRIDGE List mac addrs
68// showstp BRIDGE Show stp info
Pere Orga5bc8c002011-04-11 03:29:49 +020069
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +000070#include "libbb.h"
Denys Vlasenkoc5150e92019-04-12 18:52:31 +020071#include "common_bufsiz.h"
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +000072#include <linux/sockios.h>
73#include <net/if.h>
74
Denis Vlasenko802cab12009-01-31 20:08:21 +000075#ifndef SIOCBRADDBR
76# define SIOCBRADDBR BRCTL_ADD_BRIDGE
77#endif
78#ifndef SIOCBRDELBR
79# define SIOCBRDELBR BRCTL_DEL_BRIDGE
80#endif
81#ifndef SIOCBRADDIF
82# define SIOCBRADDIF BRCTL_ADD_IF
83#endif
84#ifndef SIOCBRDELIF
85# define SIOCBRDELIF BRCTL_DEL_IF
86#endif
87
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +000088#if ENABLE_FEATURE_BRCTL_FANCY
Denys Vlasenko94356082019-04-13 14:17:55 +020089static unsigned str_to_jiffies(const char *time_str)
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +000090{
Denys Vlasenko94356082019-04-13 14:17:55 +020091 double dd;
Maciek Borzecki46abfc02010-03-16 12:41:29 +010092 char *endptr;
Denys Vlasenko94356082019-04-13 14:17:55 +020093 dd = /*bb_*/strtod(time_str, &endptr);
94 if (endptr == time_str || dd < 0)
Denys Vlasenko0f296a32015-10-14 13:21:01 +020095 bb_error_msg_and_die(bb_msg_invalid_arg_to, time_str, "timespec");
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +000096
Denys Vlasenko94356082019-04-13 14:17:55 +020097 dd *= 100;
98 /* For purposes of brctl,
99 * capping SECONDS by ~20 million seconds is quite enough:
100 */
101 if (dd > INT_MAX)
102 dd = INT_MAX;
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000103
Denys Vlasenko94356082019-04-13 14:17:55 +0200104 return dd;
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000105}
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +0000106#endif
107
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200108#define filedata bb_common_bufsiz1
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200109
Denys Vlasenko04a0b7f2019-06-08 12:58:16 +0200110#if ENABLE_FEATURE_BRCTL_SHOW
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200111static int read_file(const char *name)
112{
113 int n = open_read_close(name, filedata, COMMON_BUFSIZE - 1);
114 if (n < 0) {
115 filedata[0] = '\0';
116 } else {
117 filedata[n] = '\0';
118 if (n != 0 && filedata[n - 1] == '\n')
119 filedata[--n] = '\0';
120 }
121 return n;
122}
123
124/* NB: we are in /sys/class/net
125 */
126static int show_bridge(const char *name, int need_hdr)
127{
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200128/* Output:
129 *bridge name bridge id STP enabled interfaces
130 *br0 8000.000000000000 no eth0
131 */
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200132 char pathbuf[IFNAMSIZ + sizeof("/bridge/bridge_id") + 32];
133 int tabs;
134 DIR *ifaces;
135 struct dirent *ent;
136 char *sfx;
137
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200138#if IFNAMSIZ == 16
139 sfx = pathbuf + sprintf(pathbuf, "%.16s/bridge/", name);
140#else
141 sfx = pathbuf + sprintf(pathbuf, "%.*s/bridge/", (int)IFNAMSIZ, name);
142#endif
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200143 strcpy(sfx, "bridge_id");
144 if (read_file(pathbuf) < 0)
145 return -1; /* this iface is not a bridge */
146
147 if (need_hdr)
148 puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces");
149 printf("%s\t\t", name);
150 printf("%s\t", filedata);
151
152 strcpy(sfx, "stp_state");
153 read_file(pathbuf);
154 if (LONE_CHAR(filedata, '0'))
155 strcpy(filedata, "no");
156 else
157 if (LONE_CHAR(filedata, '1'))
158 strcpy(filedata, "yes");
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200159 fputs(filedata, stdout);
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200160
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200161 strcpy(sfx - (sizeof("bridge/")-1), "brif");
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200162 tabs = 0;
163 ifaces = opendir(pathbuf);
164 if (ifaces) {
165 while ((ent = readdir(ifaces)) != NULL) {
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200166 if (DOT_OR_DOTDOT(ent->d_name))
167 continue; /* . or .. */
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200168 if (tabs)
169 printf("\t\t\t\t\t");
170 else
171 tabs = 1;
172 printf("\t\t%s\n", ent->d_name);
173 }
174 closedir(ifaces);
175 }
176 if (!tabs) /* bridge has no interfaces */
177 bb_putchar('\n');
178 return 0;
179}
Denys Vlasenko3e463e12019-06-08 12:35:06 +0200180#endif
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000181
Denys Vlasenko3e463e12019-06-08 12:35:06 +0200182#if ENABLE_FEATURE_BRCTL_FANCY
Denys Vlasenko94356082019-04-13 14:17:55 +0200183static void write_uint(const char *name, const char *leaf, unsigned val)
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200184{
185 char pathbuf[IFNAMSIZ + sizeof("/bridge/bridge_id") + 32];
186 int fd, n;
187
188#if IFNAMSIZ == 16
189 sprintf(pathbuf, "%.16s/%s", name, leaf);
190#else
191 sprintf(pathbuf, "%.*s/%s", (int)IFNAMSIZ, name, leaf);
192#endif
193 fd = xopen(pathbuf, O_WRONLY);
Denys Vlasenko94356082019-04-13 14:17:55 +0200194 n = sprintf(filedata, "%u\n", val);
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200195 if (write(fd, filedata, n) < 0)
196 bb_simple_perror_msg_and_die(name);
197 close(fd);
198}
Denys Vlasenko3e463e12019-06-08 12:35:06 +0200199#endif
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200200
Denis Vlasenkod0a071a2008-03-17 09:33:45 +0000201int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000202int brctl_main(int argc UNUSED_PARAM, char **argv)
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +0000203{
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +0000204 static const char keywords[] ALIGN1 =
205 "addbr\0" "delbr\0" "addif\0" "delif\0"
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000206 IF_FEATURE_BRCTL_FANCY(
Bernhard Reutner-Fischer2b11fb42008-01-14 16:10:11 +0000207 "stp\0"
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000208 "setageing\0" "setfd\0" "sethello\0" "setmaxage\0"
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200209 "setpathcost\0" "setportprio\0"
210 "setbridgeprio\0"
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000211 )
Nicolas Thillf47ce072012-09-25 14:06:01 +0200212 IF_FEATURE_BRCTL_SHOW("show\0");
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000213 enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000214 IF_FEATURE_BRCTL_FANCY(,
Denys Vlasenko60cb48c2013-01-14 15:57:44 +0100215 ARG_stp,
216 ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200217 ARG_setpathcost, ARG_setportprio,
218 ARG_setbridgeprio
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000219 )
Nicolas Thillf47ce072012-09-25 14:06:01 +0200220 IF_FEATURE_BRCTL_SHOW(, ARG_show)
Denis Vlasenkod0a071a2008-03-17 09:33:45 +0000221 };
222
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +0000223 argv++;
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200224 if (!*argv) {
225 /* bare "brctl" shows --help */
226 bb_show_usage();
227 }
228
229 xchdir("/sys/class/net");
230
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200231// while (*argv)
232 {
233 smallint key;
234 char *br;
Denis Vlasenko278a1c22008-04-06 07:17:02 +0000235
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000236 key = index_in_strings(keywords, *argv);
237 if (key == -1) /* no match found in keywords array, bail out. */
Denys Vlasenko0f296a32015-10-14 13:21:01 +0200238 bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +0000239 argv++;
Denis Vlasenko278a1c22008-04-06 07:17:02 +0000240
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +0000241#if ENABLE_FEATURE_BRCTL_SHOW
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200242 if (key == ARG_show) { /* show [BR]... */
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200243 DIR *net;
244 struct dirent *ent;
245 int need_hdr = 1;
246 int exitcode = EXIT_SUCCESS;
Denis Vlasenko278a1c22008-04-06 07:17:02 +0000247
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200248 if (*argv) {
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200249 /* "show BR1 BR2 BR3" */
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200250 do {
251 if (show_bridge(*argv, need_hdr) >= 0) {
252 need_hdr = 0;
253 } else {
254 bb_error_msg("bridge %s does not exist", *argv);
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200255//TODO: if device exists, but is not a BR, brctl from bridge-utils 1.6
256//says this instead: "device eth0 is not a bridge"
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200257 exitcode = EXIT_FAILURE;
258 }
259 } while (*++argv != NULL);
260 return exitcode;
Denis Vlasenko278a1c22008-04-06 07:17:02 +0000261 }
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200262
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200263 /* "show" (if no ifaces, shows nothing, not even header) */
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200264 net = xopendir(".");
265 while ((ent = readdir(net)) != NULL) {
266 if (DOT_OR_DOTDOT(ent->d_name))
267 continue; /* . or .. */
268 if (show_bridge(ent->d_name, need_hdr) >= 0)
269 need_hdr = 0;
270 }
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200271 if (ENABLE_FEATURE_CLEAN_UP)
272 closedir(net);
Denys Vlasenkoc5150e92019-04-12 18:52:31 +0200273 return exitcode;
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +0000274 }
275#endif
Denis Vlasenko278a1c22008-04-06 07:17:02 +0000276
277 if (!*argv) /* all but 'show' need at least one argument */
278 bb_show_usage();
279
Denis Vlasenkod0a071a2008-03-17 09:33:45 +0000280 br = *argv++;
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +0000281
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200282 if (key == ARG_addbr || key == ARG_delbr) {
283 /* addbr or delbr */
284 /* brctl from bridge-utils 1.6 still uses ioctl
285 * for SIOCBRADDBR / SIOCBRDELBR, not /sys accesses
286 */
287 int fd = xsocket(AF_INET, SOCK_STREAM, 0);
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000288 ioctl_or_perror_and_die(fd,
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200289 key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR,
290 br, "bridge %s", br
291 );
292 //close(fd);
293 //goto done;
294 /* bridge-utils 1.6 simply ignores trailing args:
295 * "brctl addbr BR1 ARGS" ignores ARGS
296 */
297 if (ENABLE_FEATURE_CLEAN_UP)
298 close(fd);
299 return EXIT_SUCCESS;
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +0000300 }
Denis Vlasenko278a1c22008-04-06 07:17:02 +0000301
Bernhard Reutner-Fischer0c0f1762010-03-17 11:23:04 +0100302 if (!*argv) /* all but 'addbr/delbr' need at least two arguments */
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000303 bb_show_usage();
Denis Vlasenko278a1c22008-04-06 07:17:02 +0000304
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000305#if ENABLE_FEATURE_BRCTL_FANCY
Bernhard Reutner-Fischer2b11fb42008-01-14 16:10:11 +0000306 if (key == ARG_stp) { /* stp */
Denys Vlasenko8a659f62010-04-03 00:52:16 +0200307 static const char no_yes[] ALIGN1 =
Maciek Borzecki30ebd7b2010-03-23 05:18:38 +0100308 "0\0" "off\0" "n\0" "no\0" /* 0 .. 3 */
309 "1\0" "on\0" "y\0" "yes\0"; /* 4 .. 7 */
Denys Vlasenko8a659f62010-04-03 00:52:16 +0200310 int onoff = index_in_strings(no_yes, *argv);
Maciek Borzecki30ebd7b2010-03-23 05:18:38 +0100311 if (onoff < 0)
Denys Vlasenko0f296a32015-10-14 13:21:01 +0200312 bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
Maciek Borzecki30ebd7b2010-03-23 05:18:38 +0100313 onoff = (unsigned)onoff / 4;
Denys Vlasenko94356082019-04-13 14:17:55 +0200314 write_uint(br, "bridge/stp_state", onoff);
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200315 //goto done_next_argv;
316 return EXIT_SUCCESS;
Bernhard Reutner-Fischer2b11fb42008-01-14 16:10:11 +0000317 }
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200318
Denis Vlasenko278a1c22008-04-06 07:17:02 +0000319 if ((unsigned)(key - ARG_setageing) < 4) { /* time related ops */
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200320 /* setageing BR N: "N*100\n" to /sys/class/net/BR/bridge/ageing_time
321 * setfd BR N: "N*100\n" to /sys/class/net/BR/bridge/forward_delay
322 * sethello BR N: "N*100\n" to /sys/class/net/BR/bridge/hello_time
323 * setmaxage BR N: "N*100\n" to /sys/class/net/BR/bridge/max_age
324 */
Denys Vlasenko94356082019-04-13 14:17:55 +0200325 write_uint(br,
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200326 nth_string(
327 "bridge/ageing_time" "\0" /* ARG_setageing */
328 "bridge/forward_delay""\0" /* ARG_setfd */
329 "bridge/hello_time" "\0" /* ARG_sethello */
330 "bridge/max_age", /* ARG_setmaxage */
331 key - ARG_setageing
332 ),
333 str_to_jiffies(*argv)
334 );
335 //goto done_next_argv;
336 return EXIT_SUCCESS;
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000337 }
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200338
339 if (key == ARG_setbridgeprio) {
Denys Vlasenko94356082019-04-13 14:17:55 +0200340 write_uint(br, "bridge/priority", xatoi_positive(*argv));
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200341 //goto done_next_argv;
342 return EXIT_SUCCESS;
343 }
344
Bernhard Reutner-Fischer2b11fb42008-01-14 16:10:11 +0000345 if (key == ARG_setpathcost
Denis Vlasenkod0a071a2008-03-17 09:33:45 +0000346 || key == ARG_setportprio
Denis Vlasenkod0a071a2008-03-17 09:33:45 +0000347 ) {
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200348 if (!argv[1])
349 bb_show_usage();
350 /* BR is not used (and ignored!) for these commands:
351 * "setpathcost BR PORT N" writes "N\n" to
352 * /sys/class/net/PORT/brport/path_cost
353 * "setportprio BR PORT N" writes "N\n" to
354 * /sys/class/net/PORT/brport/priority
355 */
Denys Vlasenko94356082019-04-13 14:17:55 +0200356 write_uint(argv[0],
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200357 nth_string(
358 "brport/path_cost" "\0" /* ARG_setpathcost */
359 "brport/priority", /* ARG_setportprio */
360 key - ARG_setpathcost
361 ),
362 xatoi_positive(argv[1])
363 );
364 //argv++;
365 //goto done_next_argv;
366 return EXIT_SUCCESS;
Bernhard Reutner-Fischer2b11fb42008-01-14 16:10:11 +0000367 }
Denys Vlasenko29458222019-04-13 15:48:31 +0200368
369/* TODO: "showmacs BR"
370 * port no\tmac addr\t\tis local?\tageing timer
371 * <sp><sp>1\txx:xx:xx:xx:xx:xx\tno\t\t<sp><sp><sp>1.31
372 * port no mac addr is local? ageing timer
373 * 1 xx:xx:xx:xx:xx:xx no 1.31
374 * Read fixed-sized records from /sys/class/net/BR/brforward:
375 * struct __fdb_entry {
376 * uint8_t mac_addr[ETH_ALEN];
377 * uint8_t port_no; //lsb
378 * uint8_t is_local;
379 * uint32_t ageing_timer_value;
380 * uint8_t port_hi;
381 * uint8_t pad0;
382 * uint16_t unused;
383 * };
384 */
Bernhard Reutner-Fischer1aac3ab2008-01-13 18:43:50 +0000385#endif
Denys Vlasenkodc1b2d42019-04-13 13:58:06 +0200386 /* always true: if (key == ARG_addif || key == ARG_delif) */ {
387 /* addif or delif */
388 struct ifreq ifr;
389 int fd = xsocket(AF_INET, SOCK_STREAM, 0);
390
391 strncpy_IFNAMSIZ(ifr.ifr_name, br);
392 ifr.ifr_ifindex = if_nametoindex(*argv);
393 if (ifr.ifr_ifindex == 0) {
394 bb_perror_msg_and_die("iface %s", *argv);
395 }
396 ioctl_or_perror_and_die(fd,
397 key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF,
398 &ifr, "bridge %s", br
399 );
400 //close(fd);
401 //goto done_next_argv;
402 if (ENABLE_FEATURE_CLEAN_UP)
403 close(fd);
404 return EXIT_SUCCESS;
405 }
406
407// done_next_argv:
408// argv++;
409// done:
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +0000410 }
Denis Vlasenko278a1c22008-04-06 07:17:02 +0000411
Bernhard Reutner-Fischerd27d9252008-01-13 15:23:27 +0000412 return EXIT_SUCCESS;
413}