Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 1 | /* vi: set sw=4 ts=4: */ |
| 2 | /* |
| 3 | * Small implementation of brctl for busybox. |
| 4 | * |
Bernhard Reutner-Fischer | 6c4dade | 2008-09-25 12:13:34 +0000 | [diff] [blame] | 5 | * Copyright (C) 2008 by Bernhard Reutner-Fischer |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 6 | * |
Bernhard Reutner-Fischer | 2b11fb4 | 2008-01-14 16:10:11 +0000 | [diff] [blame] | 7 | * Some helper functions from bridge-utils are |
| 8 | * Copyright (C) 2000 Lennert Buytenhek |
| 9 | * |
Denys Vlasenko | 0ef64bd | 2010-08-16 20:14:46 +0200 | [diff] [blame] | 10 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 11 | */ |
Denys Vlasenko | 47367e1 | 2016-11-23 09:05:14 +0100 | [diff] [blame] | 12 | //config:config BRCTL |
Denys Vlasenko | 4eed2c6 | 2017-07-18 22:01:24 +0200 | [diff] [blame] | 13 | //config: bool "brctl (4.7 kb)" |
Denys Vlasenko | 47367e1 | 2016-11-23 09:05:14 +0100 | [diff] [blame] | 14 | //config: default y |
| 15 | //config: select PLATFORM_LINUX |
| 16 | //config: help |
Denys Vlasenko | 72089cf | 2017-07-21 09:50:55 +0200 | [diff] [blame] | 17 | //config: Manage ethernet bridges. |
| 18 | //config: Supports addbr/delbr and addif/delif. |
Denys Vlasenko | 47367e1 | 2016-11-23 09:05:14 +0100 | [diff] [blame] | 19 | //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 Vlasenko | 72089cf | 2017-07-21 09:50:55 +0200 | [diff] [blame] | 25 | //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 Vlasenko | 47367e1 | 2016-11-23 09:05:14 +0100 | [diff] [blame] | 30 | //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 Vlasenko | 72089cf | 2017-07-21 09:50:55 +0200 | [diff] [blame] | 36 | //config: Add support for option which prints the current config: |
| 37 | //config: show |
Denys Vlasenko | 47367e1 | 2016-11-23 09:05:14 +0100 | [diff] [blame] | 38 | |
Denys Vlasenko | 86e07f6 | 2017-08-06 20:14:02 +0200 | [diff] [blame] | 39 | //applet:IF_BRCTL(APPLET_NOEXEC(brctl, brctl, BB_DIR_USR_SBIN, BB_SUID_DROP, brctl)) |
Denys Vlasenko | 47367e1 | 2016-11-23 09:05:14 +0100 | [diff] [blame] | 40 | |
| 41 | //kbuild:lib-$(CONFIG_BRCTL) += brctl.o |
Pere Orga | 5bc8c00 | 2011-04-11 03:29:49 +0200 | [diff] [blame] | 42 | |
| 43 | //usage:#define brctl_trivial_usage |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 44 | //usage: "COMMAND [BRIDGE [ARGS]]" |
Pere Orga | 5bc8c00 | 2011-04-11 03:29:49 +0200 | [diff] [blame] | 45 | //usage:#define brctl_full_usage "\n\n" |
Denys Vlasenko | 2945822 | 2019-04-13 15:48:31 +0200 | [diff] [blame] | 46 | //usage: "Manage ethernet bridges" |
Pere Orga | 5bc8c00 | 2011-04-11 03:29:49 +0200 | [diff] [blame] | 47 | //usage: "\nCommands:" |
| 48 | //usage: IF_FEATURE_BRCTL_SHOW( |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 49 | //usage: "\n show [BRIDGE]... Show bridges" |
Pere Orga | 5bc8c00 | 2011-04-11 03:29:49 +0200 | [diff] [blame] | 50 | //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 Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 56 | //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 Orga | 5bc8c00 | 2011-04-11 03:29:49 +0200 | [diff] [blame] | 61 | //usage: "\n setbridgeprio BRIDGE PRIO Set bridge priority" |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 62 | //usage: "\n setportprio BRIDGE IFACE PRIO Set port priority" |
| 63 | //usage: "\n setpathcost BRIDGE IFACE COST Set path cost" |
Pere Orga | 5bc8c00 | 2011-04-11 03:29:49 +0200 | [diff] [blame] | 64 | //usage: ) |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 65 | // Not yet implemented: |
Denys Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 66 | // hairpin BRIDGE IFACE on|off Hairpin on/off |
| 67 | // showmacs BRIDGE List mac addrs |
| 68 | // showstp BRIDGE Show stp info |
Pere Orga | 5bc8c00 | 2011-04-11 03:29:49 +0200 | [diff] [blame] | 69 | |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 70 | #include "libbb.h" |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 71 | #include "common_bufsiz.h" |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 72 | #include <linux/sockios.h> |
| 73 | #include <net/if.h> |
| 74 | |
Denis Vlasenko | 802cab1 | 2009-01-31 20:08:21 +0000 | [diff] [blame] | 75 | #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-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 88 | #if ENABLE_FEATURE_BRCTL_FANCY |
Denys Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 89 | static unsigned str_to_jiffies(const char *time_str) |
Bernhard Reutner-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 90 | { |
Denys Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 91 | double dd; |
Maciek Borzecki | 46abfc0 | 2010-03-16 12:41:29 +0100 | [diff] [blame] | 92 | char *endptr; |
Denys Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 93 | dd = /*bb_*/strtod(time_str, &endptr); |
| 94 | if (endptr == time_str || dd < 0) |
Denys Vlasenko | 0f296a3 | 2015-10-14 13:21:01 +0200 | [diff] [blame] | 95 | bb_error_msg_and_die(bb_msg_invalid_arg_to, time_str, "timespec"); |
Bernhard Reutner-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 96 | |
Denys Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 97 | 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-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 103 | |
Denys Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 104 | return dd; |
Bernhard Reutner-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 105 | } |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 106 | #endif |
| 107 | |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 108 | #define filedata bb_common_bufsiz1 |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 109 | |
Denys Vlasenko | 04a0b7f | 2019-06-08 12:58:16 +0200 | [diff] [blame] | 110 | #if ENABLE_FEATURE_BRCTL_SHOW |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 111 | static 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 | */ |
| 126 | static int show_bridge(const char *name, int need_hdr) |
| 127 | { |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 128 | /* Output: |
| 129 | *bridge name bridge id STP enabled interfaces |
| 130 | *br0 8000.000000000000 no eth0 |
| 131 | */ |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 132 | char pathbuf[IFNAMSIZ + sizeof("/bridge/bridge_id") + 32]; |
| 133 | int tabs; |
| 134 | DIR *ifaces; |
| 135 | struct dirent *ent; |
| 136 | char *sfx; |
| 137 | |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 138 | #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 Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 143 | 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 Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 159 | fputs(filedata, stdout); |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 160 | |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 161 | strcpy(sfx - (sizeof("bridge/")-1), "brif"); |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 162 | tabs = 0; |
| 163 | ifaces = opendir(pathbuf); |
| 164 | if (ifaces) { |
| 165 | while ((ent = readdir(ifaces)) != NULL) { |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 166 | if (DOT_OR_DOTDOT(ent->d_name)) |
| 167 | continue; /* . or .. */ |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 168 | 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 Vlasenko | 3e463e1 | 2019-06-08 12:35:06 +0200 | [diff] [blame] | 180 | #endif |
Bernhard Reutner-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 181 | |
Denys Vlasenko | 3e463e1 | 2019-06-08 12:35:06 +0200 | [diff] [blame] | 182 | #if ENABLE_FEATURE_BRCTL_FANCY |
Denys Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 183 | static void write_uint(const char *name, const char *leaf, unsigned val) |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 184 | { |
| 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 Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 194 | n = sprintf(filedata, "%u\n", val); |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 195 | if (write(fd, filedata, n) < 0) |
| 196 | bb_simple_perror_msg_and_die(name); |
| 197 | close(fd); |
| 198 | } |
Denys Vlasenko | 3e463e1 | 2019-06-08 12:35:06 +0200 | [diff] [blame] | 199 | #endif |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 200 | |
Denis Vlasenko | d0a071a | 2008-03-17 09:33:45 +0000 | [diff] [blame] | 201 | int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
Denis Vlasenko | a60f84e | 2008-07-05 09:18:54 +0000 | [diff] [blame] | 202 | int brctl_main(int argc UNUSED_PARAM, char **argv) |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 203 | { |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 204 | static const char keywords[] ALIGN1 = |
| 205 | "addbr\0" "delbr\0" "addif\0" "delif\0" |
Denis Vlasenko | 5e34ff2 | 2009-04-21 11:09:40 +0000 | [diff] [blame] | 206 | IF_FEATURE_BRCTL_FANCY( |
Bernhard Reutner-Fischer | 2b11fb4 | 2008-01-14 16:10:11 +0000 | [diff] [blame] | 207 | "stp\0" |
Bernhard Reutner-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 208 | "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 209 | "setpathcost\0" "setportprio\0" |
| 210 | "setbridgeprio\0" |
Bernhard Reutner-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 211 | ) |
Nicolas Thill | f47ce07 | 2012-09-25 14:06:01 +0200 | [diff] [blame] | 212 | IF_FEATURE_BRCTL_SHOW("show\0"); |
Bernhard Reutner-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 213 | enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif |
Denis Vlasenko | 5e34ff2 | 2009-04-21 11:09:40 +0000 | [diff] [blame] | 214 | IF_FEATURE_BRCTL_FANCY(, |
Denys Vlasenko | 60cb48c | 2013-01-14 15:57:44 +0100 | [diff] [blame] | 215 | ARG_stp, |
| 216 | ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 217 | ARG_setpathcost, ARG_setportprio, |
| 218 | ARG_setbridgeprio |
Bernhard Reutner-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 219 | ) |
Nicolas Thill | f47ce07 | 2012-09-25 14:06:01 +0200 | [diff] [blame] | 220 | IF_FEATURE_BRCTL_SHOW(, ARG_show) |
Denis Vlasenko | d0a071a | 2008-03-17 09:33:45 +0000 | [diff] [blame] | 221 | }; |
| 222 | |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 223 | argv++; |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 224 | if (!*argv) { |
| 225 | /* bare "brctl" shows --help */ |
| 226 | bb_show_usage(); |
| 227 | } |
| 228 | |
| 229 | xchdir("/sys/class/net"); |
| 230 | |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 231 | // while (*argv) |
| 232 | { |
| 233 | smallint key; |
| 234 | char *br; |
Denis Vlasenko | 278a1c2 | 2008-04-06 07:17:02 +0000 | [diff] [blame] | 235 | |
Bernhard Reutner-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 236 | key = index_in_strings(keywords, *argv); |
| 237 | if (key == -1) /* no match found in keywords array, bail out. */ |
Denys Vlasenko | 0f296a3 | 2015-10-14 13:21:01 +0200 | [diff] [blame] | 238 | bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 239 | argv++; |
Denis Vlasenko | 278a1c2 | 2008-04-06 07:17:02 +0000 | [diff] [blame] | 240 | |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 241 | #if ENABLE_FEATURE_BRCTL_SHOW |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 242 | if (key == ARG_show) { /* show [BR]... */ |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 243 | DIR *net; |
| 244 | struct dirent *ent; |
| 245 | int need_hdr = 1; |
| 246 | int exitcode = EXIT_SUCCESS; |
Denis Vlasenko | 278a1c2 | 2008-04-06 07:17:02 +0000 | [diff] [blame] | 247 | |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 248 | if (*argv) { |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 249 | /* "show BR1 BR2 BR3" */ |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 250 | 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 Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 255 | //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 Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 257 | exitcode = EXIT_FAILURE; |
| 258 | } |
| 259 | } while (*++argv != NULL); |
| 260 | return exitcode; |
Denis Vlasenko | 278a1c2 | 2008-04-06 07:17:02 +0000 | [diff] [blame] | 261 | } |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 262 | |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 263 | /* "show" (if no ifaces, shows nothing, not even header) */ |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 264 | 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 Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 271 | if (ENABLE_FEATURE_CLEAN_UP) |
| 272 | closedir(net); |
Denys Vlasenko | c5150e9 | 2019-04-12 18:52:31 +0200 | [diff] [blame] | 273 | return exitcode; |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 274 | } |
| 275 | #endif |
Denis Vlasenko | 278a1c2 | 2008-04-06 07:17:02 +0000 | [diff] [blame] | 276 | |
| 277 | if (!*argv) /* all but 'show' need at least one argument */ |
| 278 | bb_show_usage(); |
| 279 | |
Denis Vlasenko | d0a071a | 2008-03-17 09:33:45 +0000 | [diff] [blame] | 280 | br = *argv++; |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 281 | |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 282 | 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-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 288 | ioctl_or_perror_and_die(fd, |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 289 | 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-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 300 | } |
Denis Vlasenko | 278a1c2 | 2008-04-06 07:17:02 +0000 | [diff] [blame] | 301 | |
Bernhard Reutner-Fischer | 0c0f176 | 2010-03-17 11:23:04 +0100 | [diff] [blame] | 302 | if (!*argv) /* all but 'addbr/delbr' need at least two arguments */ |
Bernhard Reutner-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 303 | bb_show_usage(); |
Denis Vlasenko | 278a1c2 | 2008-04-06 07:17:02 +0000 | [diff] [blame] | 304 | |
Bernhard Reutner-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 305 | #if ENABLE_FEATURE_BRCTL_FANCY |
Bernhard Reutner-Fischer | 2b11fb4 | 2008-01-14 16:10:11 +0000 | [diff] [blame] | 306 | if (key == ARG_stp) { /* stp */ |
Denys Vlasenko | 8a659f6 | 2010-04-03 00:52:16 +0200 | [diff] [blame] | 307 | static const char no_yes[] ALIGN1 = |
Maciek Borzecki | 30ebd7b | 2010-03-23 05:18:38 +0100 | [diff] [blame] | 308 | "0\0" "off\0" "n\0" "no\0" /* 0 .. 3 */ |
| 309 | "1\0" "on\0" "y\0" "yes\0"; /* 4 .. 7 */ |
Denys Vlasenko | 8a659f6 | 2010-04-03 00:52:16 +0200 | [diff] [blame] | 310 | int onoff = index_in_strings(no_yes, *argv); |
Maciek Borzecki | 30ebd7b | 2010-03-23 05:18:38 +0100 | [diff] [blame] | 311 | if (onoff < 0) |
Denys Vlasenko | 0f296a3 | 2015-10-14 13:21:01 +0200 | [diff] [blame] | 312 | bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); |
Maciek Borzecki | 30ebd7b | 2010-03-23 05:18:38 +0100 | [diff] [blame] | 313 | onoff = (unsigned)onoff / 4; |
Denys Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 314 | write_uint(br, "bridge/stp_state", onoff); |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 315 | //goto done_next_argv; |
| 316 | return EXIT_SUCCESS; |
Bernhard Reutner-Fischer | 2b11fb4 | 2008-01-14 16:10:11 +0000 | [diff] [blame] | 317 | } |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 318 | |
Denis Vlasenko | 278a1c2 | 2008-04-06 07:17:02 +0000 | [diff] [blame] | 319 | if ((unsigned)(key - ARG_setageing) < 4) { /* time related ops */ |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 320 | /* 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 Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 325 | write_uint(br, |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 326 | 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-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 337 | } |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 338 | |
| 339 | if (key == ARG_setbridgeprio) { |
Denys Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 340 | write_uint(br, "bridge/priority", xatoi_positive(*argv)); |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 341 | //goto done_next_argv; |
| 342 | return EXIT_SUCCESS; |
| 343 | } |
| 344 | |
Bernhard Reutner-Fischer | 2b11fb4 | 2008-01-14 16:10:11 +0000 | [diff] [blame] | 345 | if (key == ARG_setpathcost |
Denis Vlasenko | d0a071a | 2008-03-17 09:33:45 +0000 | [diff] [blame] | 346 | || key == ARG_setportprio |
Denis Vlasenko | d0a071a | 2008-03-17 09:33:45 +0000 | [diff] [blame] | 347 | ) { |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 348 | 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 Vlasenko | 9435608 | 2019-04-13 14:17:55 +0200 | [diff] [blame] | 356 | write_uint(argv[0], |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 357 | 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-Fischer | 2b11fb4 | 2008-01-14 16:10:11 +0000 | [diff] [blame] | 367 | } |
Denys Vlasenko | 2945822 | 2019-04-13 15:48:31 +0200 | [diff] [blame] | 368 | |
| 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-Fischer | 1aac3ab | 2008-01-13 18:43:50 +0000 | [diff] [blame] | 385 | #endif |
Denys Vlasenko | dc1b2d4 | 2019-04-13 13:58:06 +0200 | [diff] [blame] | 386 | /* 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-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 410 | } |
Denis Vlasenko | 278a1c2 | 2008-04-06 07:17:02 +0000 | [diff] [blame] | 411 | |
Bernhard Reutner-Fischer | d27d925 | 2008-01-13 15:23:27 +0000 | [diff] [blame] | 412 | return EXIT_SUCCESS; |
| 413 | } |