diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-07 22:14:25 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-07 22:14:25 +0000 |
commit | c8fa04f9b16f429b76e58b7cd410b5d92db42bb5 (patch) | |
tree | ac8b0dcc2aec6bf3824712641130f38151c9221f | |
parent | 0876822ded1b1c7ad633c76f6c878ce678bbe42e (diff) | |
download | busybox-w32-c8fa04f9b16f429b76e58b7cd410b5d92db42bb5.tar.gz busybox-w32-c8fa04f9b16f429b76e58b7cd410b5d92db42bb5.tar.bz2 busybox-w32-c8fa04f9b16f429b76e58b7cd410b5d92db42bb5.zip |
ifenslave: further shrink by suppressing excessive inlining
ifenslave: reorder functions to avoid forward declarations
function old new delta
enslave - 531 +531
get_drv_info - 176 +176
ifenslave_main 1411 671 -740
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 0/1 up/down: 707/-740) Total: -33 bytes
text data bss dec hex filename
809737 624 7060 817421 c790d busybox_old
809704 624 7060 817388 c78ec busybox_unstripped
-rw-r--r-- | networking/ifenslave.c | 466 |
1 files changed, 227 insertions, 239 deletions
diff --git a/networking/ifenslave.c b/networking/ifenslave.c index 071cac722..44839868a 100644 --- a/networking/ifenslave.c +++ b/networking/ifenslave.c | |||
@@ -133,19 +133,7 @@ struct globals { | |||
133 | } while (0) | 133 | } while (0) |
134 | 134 | ||
135 | 135 | ||
136 | static void get_drv_info(char *master_ifname); | 136 | /* NOINLINEs are placed where it results in smaller code (gcc 4.3.1) */ |
137 | static int get_if_settings(char *ifname, struct dev_data *dd); | ||
138 | static int get_slave_flags(char *slave_ifname); | ||
139 | static int set_hwaddr(char *ifname, struct sockaddr *hwaddr); | ||
140 | static int set_mtu(char *ifname, int mtu); | ||
141 | static int set_if_flags(char *ifname, int flags); | ||
142 | static int set_if_up(char *ifname, int flags); | ||
143 | static int set_if_down(char *ifname, int flags); | ||
144 | static int clear_if_addr(char *ifname); | ||
145 | static int set_if_addr(char *master_ifname, char *slave_ifname); | ||
146 | static void change_active(char *master_ifname, char *slave_ifname); | ||
147 | static int enslave(char *master_ifname, char *slave_ifname); | ||
148 | static int release(char *master_ifname, char *slave_ifname); | ||
149 | 137 | ||
150 | static void strncpy_IFNAMSIZ(char *dst, const char *src) | 138 | static void strncpy_IFNAMSIZ(char *dst, const char *src) |
151 | { | 139 | { |
@@ -163,173 +151,109 @@ static int set_ifrname_and_do_ioctl(unsigned request, struct ifreq *ifr, const c | |||
163 | return ioctl_on_skfd(request, ifr); | 151 | return ioctl_on_skfd(request, ifr); |
164 | } | 152 | } |
165 | 153 | ||
166 | int ifenslave_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 154 | static int get_if_settings(char *ifname, struct dev_data *dd) |
167 | int ifenslave_main(int argc ATTRIBUTE_UNUSED, char **argv) | ||
168 | { | 155 | { |
169 | char *master_ifname, *slave_ifname; | ||
170 | int rv; | ||
171 | int res; | 156 | int res; |
172 | unsigned opt; | ||
173 | enum { | ||
174 | OPT_c = (1 << 0), | ||
175 | OPT_d = (1 << 1), | ||
176 | OPT_f = (1 << 2), | ||
177 | }; | ||
178 | #if ENABLE_GETOPT_LONG | ||
179 | static const char ifenslave_longopts[] ALIGN1 = | ||
180 | "change-active\0" No_argument "c" | ||
181 | "detach\0" No_argument "d" | ||
182 | "force\0" No_argument "f" | ||
183 | ; | ||
184 | |||
185 | applet_long_options = ifenslave_longopts; | ||
186 | #endif | ||
187 | INIT_G(); | ||
188 | 157 | ||
189 | opt = getopt32(argv, "cdf"); | 158 | res = set_ifrname_and_do_ioctl(SIOCGIFMTU, &dd->mtu, ifname); |
190 | argv += optind; | 159 | res |= set_ifrname_and_do_ioctl(SIOCGIFFLAGS, &dd->flags, ifname); |
191 | if (opt & (opt-1)) /* options check */ | 160 | res |= set_ifrname_and_do_ioctl(SIOCGIFHWADDR, &dd->hwaddr, ifname); |
192 | bb_show_usage(); | ||
193 | |||
194 | master_ifname = *argv++; | ||
195 | 161 | ||
196 | /* No interface names - show all interfaces. */ | 162 | return res; |
197 | if (!master_ifname) { | 163 | } |
198 | display_interfaces(NULL); | ||
199 | return EXIT_SUCCESS; | ||
200 | } | ||
201 | 164 | ||
202 | /* Open a basic socket */ | 165 | static int get_slave_flags(char *slave_ifname) |
203 | xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), skfd); | 166 | { |
167 | return set_ifrname_and_do_ioctl(SIOCGIFFLAGS, &slave.flags, slave_ifname); | ||
168 | } | ||
204 | 169 | ||
205 | /* Exchange abi version with bonding module */ | 170 | static int set_hwaddr(char *ifname, struct sockaddr *hwaddr) |
206 | get_drv_info(master_ifname); | 171 | { |
172 | struct ifreq ifr; | ||
207 | 173 | ||
208 | slave_ifname = *argv++; | 174 | memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(*hwaddr)); |
209 | if (!slave_ifname) { | 175 | return set_ifrname_and_do_ioctl(SIOCSIFHWADDR, &ifr, ifname); |
210 | if (opt & (OPT_d|OPT_c)) { | 176 | } |
211 | /* --change or --detach, and no slaves given - | ||
212 | * show all interfaces. */ | ||
213 | display_interfaces(slave_ifname /* == NULL */); | ||
214 | return 2; /* why 2? */ | ||
215 | } | ||
216 | /* A single arg means show the | ||
217 | * configuration for this interface | ||
218 | */ | ||
219 | display_interfaces(master_ifname); | ||
220 | return EXIT_SUCCESS; | ||
221 | } | ||
222 | 177 | ||
223 | res = get_if_settings(master_ifname, &master); | 178 | static int set_mtu(char *ifname, int mtu) |
224 | if (res) { | 179 | { |
225 | /* Probably a good reason not to go on */ | 180 | struct ifreq ifr; |
226 | bb_perror_msg_and_die("%s: can't get settings", master_ifname); | ||
227 | } | ||
228 | 181 | ||
229 | /* check if master is indeed a master; | 182 | ifr.ifr_mtu = mtu; |
230 | * if not then fail any operation | 183 | return set_ifrname_and_do_ioctl(SIOCSIFMTU, &ifr, ifname); |
231 | */ | 184 | } |
232 | if (!(master.flags.ifr_flags & IFF_MASTER)) | ||
233 | bb_error_msg_and_die("%s is not a master", master_ifname); | ||
234 | 185 | ||
235 | /* check if master is up; if not then fail any operation */ | 186 | static int set_if_flags(char *ifname, int flags) |
236 | if (!(master.flags.ifr_flags & IFF_UP)) | 187 | { |
237 | bb_error_msg_and_die("%s is not up", master_ifname); | 188 | struct ifreq ifr; |
238 | 189 | ||
239 | /* No opts: neither -c[hange] nor -d[etach] -> it's "enslave" then; | 190 | ifr.ifr_flags = flags; |
240 | * and -f[orce] is not there too */ | 191 | return set_ifrname_and_do_ioctl(SIOCSIFFLAGS, &ifr, ifname); |
241 | if (!opt) { | 192 | } |
242 | /* The family '1' is ARPHRD_ETHER for ethernet. */ | ||
243 | if (master.hwaddr.ifr_hwaddr.sa_family != 1) { | ||
244 | bb_error_msg_and_die( | ||
245 | "%s is not ethernet-like (-f overrides)", | ||
246 | master_ifname); | ||
247 | } | ||
248 | } | ||
249 | 193 | ||
250 | /* Accepts only one slave */ | 194 | static int set_if_up(char *ifname, int flags) |
251 | if (opt & OPT_c) { | 195 | { |
252 | /* change active slave */ | 196 | int res = set_if_flags(ifname, flags | IFF_UP); |
253 | if (get_slave_flags(slave_ifname)) { | 197 | if (res) |
254 | bb_perror_msg_and_die( | 198 | bb_perror_msg("%s: can't up", ifname); |
255 | "%s: can't get flags", slave_ifname); | 199 | return res; |
256 | } | 200 | } |
257 | change_active(master_ifname, slave_ifname); | ||
258 | return EXIT_SUCCESS; | ||
259 | } | ||
260 | 201 | ||
261 | /* Accept multiple slaves */ | 202 | static int set_if_down(char *ifname, int flags) |
262 | res = 0; | 203 | { |
263 | do { | 204 | int res = set_if_flags(ifname, flags & ~IFF_UP); |
264 | if (opt & OPT_d) { | 205 | if (res) |
265 | /* detach a slave interface from the master */ | 206 | bb_perror_msg("%s: can't down", ifname); |
266 | rv = get_slave_flags(slave_ifname); | 207 | return res; |
267 | if (rv) { | 208 | } |
268 | /* Can't work with this slave, */ | ||
269 | /* remember the error and skip it */ | ||
270 | bb_perror_msg( | ||
271 | "skipping %s: can't get flags", | ||
272 | slave_ifname); | ||
273 | res = rv; | ||
274 | continue; | ||
275 | } | ||
276 | rv = release(master_ifname, slave_ifname); | ||
277 | if (rv) { | ||
278 | bb_perror_msg( | ||
279 | "master %s, slave %s: " | ||
280 | "can't release", | ||
281 | master_ifname, slave_ifname); | ||
282 | res = rv; | ||
283 | } | ||
284 | } else { | ||
285 | /* attach a slave interface to the master */ | ||
286 | rv = get_if_settings(slave_ifname, &slave); | ||
287 | if (rv) { | ||
288 | /* Can't work with this slave, */ | ||
289 | /* remember the error and skip it */ | ||
290 | bb_perror_msg( | ||
291 | "skipping %s: can't get settings", | ||
292 | slave_ifname); | ||
293 | res = rv; | ||
294 | continue; | ||
295 | } | ||
296 | rv = enslave(master_ifname, slave_ifname); | ||
297 | if (rv) { | ||
298 | bb_perror_msg( | ||
299 | "master %s, slave %s: " | ||
300 | "can't enslave", | ||
301 | master_ifname, slave_ifname); | ||
302 | res = rv; | ||
303 | } | ||
304 | } | ||
305 | } while ((slave_ifname = *argv++) != NULL); | ||
306 | 209 | ||
307 | if (ENABLE_FEATURE_CLEAN_UP) { | 210 | static int clear_if_addr(char *ifname) |
308 | close(skfd); | 211 | { |
309 | } | 212 | struct ifreq ifr; |
310 | 213 | ||
311 | return res; | 214 | ifr.ifr_addr.sa_family = AF_INET; |
215 | memset(ifr.ifr_addr.sa_data, 0, sizeof(ifr.ifr_addr.sa_data)); | ||
216 | return set_ifrname_and_do_ioctl(SIOCSIFADDR, &ifr, ifname); | ||
312 | } | 217 | } |
313 | 218 | ||
314 | static void get_drv_info(char *master_ifname) | 219 | static int set_if_addr(char *master_ifname, char *slave_ifname) |
315 | { | 220 | { |
221 | #if (SIOCGIFADDR | SIOCSIFADDR \ | ||
222 | | SIOCGIFDSTADDR | SIOCSIFDSTADDR \ | ||
223 | | SIOCGIFBRDADDR | SIOCSIFBRDADDR \ | ||
224 | | SIOCGIFNETMASK | SIOCSIFNETMASK) <= 0xffff | ||
225 | #define INT uint16_t | ||
226 | #else | ||
227 | #define INT int | ||
228 | #endif | ||
229 | static const struct { | ||
230 | INT g_ioctl; | ||
231 | INT s_ioctl; | ||
232 | } ifra[] = { | ||
233 | { SIOCGIFADDR, SIOCSIFADDR }, | ||
234 | { SIOCGIFDSTADDR, SIOCSIFDSTADDR }, | ||
235 | { SIOCGIFBRDADDR, SIOCSIFBRDADDR }, | ||
236 | { SIOCGIFNETMASK, SIOCSIFNETMASK }, | ||
237 | }; | ||
238 | |||
316 | struct ifreq ifr; | 239 | struct ifreq ifr; |
317 | struct ethtool_drvinfo info; | 240 | int res; |
241 | unsigned i; | ||
318 | 242 | ||
319 | memset(&ifr, 0, sizeof(ifr)); | 243 | for (i = 0; i < ARRAY_SIZE(ifra); i++) { |
320 | ifr.ifr_data = (caddr_t)&info; | 244 | res = set_ifrname_and_do_ioctl(ifra[i].g_ioctl, &ifr, master_ifname); |
321 | info.cmd = ETHTOOL_GDRVINFO; | 245 | if (res < 0) { |
322 | strncpy(info.driver, "ifenslave", 32); | 246 | ifr.ifr_addr.sa_family = AF_INET; |
323 | snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION); | 247 | memset(ifr.ifr_addr.sa_data, 0, |
324 | if (set_ifrname_and_do_ioctl(SIOCETHTOOL, &ifr, master_ifname) < 0) { | 248 | sizeof(ifr.ifr_addr.sa_data)); |
325 | if (errno == EOPNOTSUPP) | 249 | } |
326 | return; | 250 | |
327 | bb_perror_msg_and_die("%s: SIOCETHTOOL error", master_ifname); | 251 | res = set_ifrname_and_do_ioctl(ifra[i].s_ioctl, &ifr, slave_ifname); |
252 | if (res < 0) | ||
253 | return res; | ||
328 | } | 254 | } |
329 | 255 | ||
330 | abi_ver = bb_strtou(info.fw_version, NULL, 0); | 256 | return 0; |
331 | if (errno) | ||
332 | bb_error_msg_and_die("%s: SIOCETHTOOL error", master_ifname); | ||
333 | } | 257 | } |
334 | 258 | ||
335 | static void change_active(char *master_ifname, char *slave_ifname) | 259 | static void change_active(char *master_ifname, char *slave_ifname) |
@@ -353,7 +277,7 @@ static void change_active(char *master_ifname, char *slave_ifname) | |||
353 | } | 277 | } |
354 | } | 278 | } |
355 | 279 | ||
356 | static int enslave(char *master_ifname, char *slave_ifname) | 280 | static NOINLINE int enslave(char *master_ifname, char *slave_ifname) |
357 | { | 281 | { |
358 | struct ifreq ifr; | 282 | struct ifreq ifr; |
359 | int res; | 283 | int res; |
@@ -502,107 +426,171 @@ static int release(char *master_ifname, char *slave_ifname) | |||
502 | return res; | 426 | return res; |
503 | } | 427 | } |
504 | 428 | ||
505 | static int get_if_settings(char *ifname, struct dev_data *dd) | 429 | static NOINLINE void get_drv_info(char *master_ifname) |
506 | { | 430 | { |
507 | int res; | 431 | struct ifreq ifr; |
432 | struct ethtool_drvinfo info; | ||
508 | 433 | ||
509 | res = set_ifrname_and_do_ioctl(SIOCGIFMTU, &dd->mtu, ifname); | 434 | memset(&ifr, 0, sizeof(ifr)); |
510 | res |= set_ifrname_and_do_ioctl(SIOCGIFFLAGS, &dd->flags, ifname); | 435 | ifr.ifr_data = (caddr_t)&info; |
511 | res |= set_ifrname_and_do_ioctl(SIOCGIFHWADDR, &dd->hwaddr, ifname); | 436 | info.cmd = ETHTOOL_GDRVINFO; |
437 | strncpy(info.driver, "ifenslave", 32); | ||
438 | snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION); | ||
439 | if (set_ifrname_and_do_ioctl(SIOCETHTOOL, &ifr, master_ifname) < 0) { | ||
440 | if (errno == EOPNOTSUPP) | ||
441 | return; | ||
442 | bb_perror_msg_and_die("%s: SIOCETHTOOL error", master_ifname); | ||
443 | } | ||
512 | 444 | ||
513 | return res; | 445 | abi_ver = bb_strtou(info.fw_version, NULL, 0); |
446 | if (errno) | ||
447 | bb_error_msg_and_die("%s: SIOCETHTOOL error", master_ifname); | ||
514 | } | 448 | } |
515 | 449 | ||
516 | static int get_slave_flags(char *slave_ifname) | 450 | int ifenslave_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
451 | int ifenslave_main(int argc ATTRIBUTE_UNUSED, char **argv) | ||
517 | { | 452 | { |
518 | return set_ifrname_and_do_ioctl(SIOCGIFFLAGS, &slave.flags, slave_ifname); | 453 | char *master_ifname, *slave_ifname; |
519 | } | 454 | int rv; |
455 | int res; | ||
456 | unsigned opt; | ||
457 | enum { | ||
458 | OPT_c = (1 << 0), | ||
459 | OPT_d = (1 << 1), | ||
460 | OPT_f = (1 << 2), | ||
461 | }; | ||
462 | #if ENABLE_GETOPT_LONG | ||
463 | static const char ifenslave_longopts[] ALIGN1 = | ||
464 | "change-active\0" No_argument "c" | ||
465 | "detach\0" No_argument "d" | ||
466 | "force\0" No_argument "f" | ||
467 | ; | ||
520 | 468 | ||
521 | static int set_hwaddr(char *ifname, struct sockaddr *hwaddr) | 469 | applet_long_options = ifenslave_longopts; |
522 | { | 470 | #endif |
523 | struct ifreq ifr; | 471 | INIT_G(); |
524 | 472 | ||
525 | memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(*hwaddr)); | 473 | opt = getopt32(argv, "cdf"); |
526 | return set_ifrname_and_do_ioctl(SIOCSIFHWADDR, &ifr, ifname); | 474 | argv += optind; |
527 | } | 475 | if (opt & (opt-1)) /* options check */ |
476 | bb_show_usage(); | ||
528 | 477 | ||
529 | static int set_mtu(char *ifname, int mtu) | 478 | master_ifname = *argv++; |
530 | { | ||
531 | struct ifreq ifr; | ||
532 | 479 | ||
533 | ifr.ifr_mtu = mtu; | 480 | /* No interface names - show all interfaces. */ |
534 | return set_ifrname_and_do_ioctl(SIOCSIFMTU, &ifr, ifname); | 481 | if (!master_ifname) { |
535 | } | 482 | display_interfaces(NULL); |
483 | return EXIT_SUCCESS; | ||
484 | } | ||
536 | 485 | ||
537 | static int set_if_flags(char *ifname, int flags) | 486 | /* Open a basic socket */ |
538 | { | 487 | xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), skfd); |
539 | struct ifreq ifr; | ||
540 | 488 | ||
541 | ifr.ifr_flags = flags; | 489 | /* Exchange abi version with bonding module */ |
542 | return set_ifrname_and_do_ioctl(SIOCSIFFLAGS, &ifr, ifname); | 490 | get_drv_info(master_ifname); |
543 | } | ||
544 | 491 | ||
545 | static int set_if_up(char *ifname, int flags) | 492 | slave_ifname = *argv++; |
546 | { | 493 | if (!slave_ifname) { |
547 | int res = set_if_flags(ifname, flags | IFF_UP); | 494 | if (opt & (OPT_d|OPT_c)) { |
548 | if (res) | 495 | /* --change or --detach, and no slaves given - |
549 | bb_perror_msg("%s: can't up", ifname); | 496 | * show all interfaces. */ |
550 | return res; | 497 | display_interfaces(slave_ifname /* == NULL */); |
551 | } | 498 | return 2; /* why 2? */ |
499 | } | ||
500 | /* A single arg means show the | ||
501 | * configuration for this interface | ||
502 | */ | ||
503 | display_interfaces(master_ifname); | ||
504 | return EXIT_SUCCESS; | ||
505 | } | ||
552 | 506 | ||
553 | static int set_if_down(char *ifname, int flags) | 507 | res = get_if_settings(master_ifname, &master); |
554 | { | 508 | if (res) { |
555 | int res = set_if_flags(ifname, flags & ~IFF_UP); | 509 | /* Probably a good reason not to go on */ |
556 | if (res) | 510 | bb_perror_msg_and_die("%s: can't get settings", master_ifname); |
557 | bb_perror_msg("%s: can't down", ifname); | 511 | } |
558 | return res; | ||
559 | } | ||
560 | 512 | ||
561 | static int clear_if_addr(char *ifname) | 513 | /* check if master is indeed a master; |
562 | { | 514 | * if not then fail any operation |
563 | struct ifreq ifr; | 515 | */ |
516 | if (!(master.flags.ifr_flags & IFF_MASTER)) | ||
517 | bb_error_msg_and_die("%s is not a master", master_ifname); | ||
564 | 518 | ||
565 | ifr.ifr_addr.sa_family = AF_INET; | 519 | /* check if master is up; if not then fail any operation */ |
566 | memset(ifr.ifr_addr.sa_data, 0, sizeof(ifr.ifr_addr.sa_data)); | 520 | if (!(master.flags.ifr_flags & IFF_UP)) |
567 | return set_ifrname_and_do_ioctl(SIOCSIFADDR, &ifr, ifname); | 521 | bb_error_msg_and_die("%s is not up", master_ifname); |
568 | } | ||
569 | 522 | ||
570 | static int set_if_addr(char *master_ifname, char *slave_ifname) | 523 | /* No opts: neither -c[hange] nor -d[etach] -> it's "enslave" then; |
571 | { | 524 | * and -f[orce] is not there too */ |
572 | #if (SIOCGIFADDR | SIOCSIFADDR \ | 525 | if (!opt) { |
573 | | SIOCGIFDSTADDR | SIOCSIFDSTADDR \ | 526 | /* The family '1' is ARPHRD_ETHER for ethernet. */ |
574 | | SIOCGIFBRDADDR | SIOCSIFBRDADDR \ | 527 | if (master.hwaddr.ifr_hwaddr.sa_family != 1) { |
575 | | SIOCGIFNETMASK | SIOCSIFNETMASK) <= 0xffff | 528 | bb_error_msg_and_die( |
576 | #define INT uint16_t | 529 | "%s is not ethernet-like (-f overrides)", |
577 | #else | 530 | master_ifname); |
578 | #define INT int | 531 | } |
579 | #endif | 532 | } |
580 | static const struct { | ||
581 | INT g_ioctl; | ||
582 | INT s_ioctl; | ||
583 | } ifra[] = { | ||
584 | { SIOCGIFADDR, SIOCSIFADDR }, | ||
585 | { SIOCGIFDSTADDR, SIOCSIFDSTADDR }, | ||
586 | { SIOCGIFBRDADDR, SIOCSIFBRDADDR }, | ||
587 | { SIOCGIFNETMASK, SIOCSIFNETMASK }, | ||
588 | }; | ||
589 | 533 | ||
590 | struct ifreq ifr; | 534 | /* Accepts only one slave */ |
591 | int res; | 535 | if (opt & OPT_c) { |
592 | unsigned i; | 536 | /* change active slave */ |
537 | if (get_slave_flags(slave_ifname)) { | ||
538 | bb_perror_msg_and_die( | ||
539 | "%s: can't get flags", slave_ifname); | ||
540 | } | ||
541 | change_active(master_ifname, slave_ifname); | ||
542 | return EXIT_SUCCESS; | ||
543 | } | ||
593 | 544 | ||
594 | for (i = 0; i < ARRAY_SIZE(ifra); i++) { | 545 | /* Accept multiple slaves */ |
595 | res = set_ifrname_and_do_ioctl(ifra[i].g_ioctl, &ifr, master_ifname); | 546 | res = 0; |
596 | if (res < 0) { | 547 | do { |
597 | ifr.ifr_addr.sa_family = AF_INET; | 548 | if (opt & OPT_d) { |
598 | memset(ifr.ifr_addr.sa_data, 0, | 549 | /* detach a slave interface from the master */ |
599 | sizeof(ifr.ifr_addr.sa_data)); | 550 | rv = get_slave_flags(slave_ifname); |
551 | if (rv) { | ||
552 | /* Can't work with this slave, */ | ||
553 | /* remember the error and skip it */ | ||
554 | bb_perror_msg( | ||
555 | "skipping %s: can't get flags", | ||
556 | slave_ifname); | ||
557 | res = rv; | ||
558 | continue; | ||
559 | } | ||
560 | rv = release(master_ifname, slave_ifname); | ||
561 | if (rv) { | ||
562 | bb_perror_msg( | ||
563 | "master %s, slave %s: " | ||
564 | "can't release", | ||
565 | master_ifname, slave_ifname); | ||
566 | res = rv; | ||
567 | } | ||
568 | } else { | ||
569 | /* attach a slave interface to the master */ | ||
570 | rv = get_if_settings(slave_ifname, &slave); | ||
571 | if (rv) { | ||
572 | /* Can't work with this slave, */ | ||
573 | /* remember the error and skip it */ | ||
574 | bb_perror_msg( | ||
575 | "skipping %s: can't get settings", | ||
576 | slave_ifname); | ||
577 | res = rv; | ||
578 | continue; | ||
579 | } | ||
580 | rv = enslave(master_ifname, slave_ifname); | ||
581 | if (rv) { | ||
582 | bb_perror_msg( | ||
583 | "master %s, slave %s: " | ||
584 | "can't enslave", | ||
585 | master_ifname, slave_ifname); | ||
586 | res = rv; | ||
587 | } | ||
600 | } | 588 | } |
589 | } while ((slave_ifname = *argv++) != NULL); | ||
601 | 590 | ||
602 | res = set_ifrname_and_do_ioctl(ifra[i].s_ioctl, &ifr, slave_ifname); | 591 | if (ENABLE_FEATURE_CLEAN_UP) { |
603 | if (res < 0) | 592 | close(skfd); |
604 | return res; | ||
605 | } | 593 | } |
606 | 594 | ||
607 | return 0; | 595 | return res; |
608 | } | 596 | } |