aboutsummaryrefslogtreecommitdiff
path: root/networking/ifenslave.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-07 22:14:25 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-07 22:14:25 +0000
commitc8fa04f9b16f429b76e58b7cd410b5d92db42bb5 (patch)
treeac8b0dcc2aec6bf3824712641130f38151c9221f /networking/ifenslave.c
parent0876822ded1b1c7ad633c76f6c878ce678bbe42e (diff)
downloadbusybox-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
Diffstat (limited to 'networking/ifenslave.c')
-rw-r--r--networking/ifenslave.c466
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
136static void get_drv_info(char *master_ifname); 136/* NOINLINEs are placed where it results in smaller code (gcc 4.3.1) */
137static int get_if_settings(char *ifname, struct dev_data *dd);
138static int get_slave_flags(char *slave_ifname);
139static int set_hwaddr(char *ifname, struct sockaddr *hwaddr);
140static int set_mtu(char *ifname, int mtu);
141static int set_if_flags(char *ifname, int flags);
142static int set_if_up(char *ifname, int flags);
143static int set_if_down(char *ifname, int flags);
144static int clear_if_addr(char *ifname);
145static int set_if_addr(char *master_ifname, char *slave_ifname);
146static void change_active(char *master_ifname, char *slave_ifname);
147static int enslave(char *master_ifname, char *slave_ifname);
148static int release(char *master_ifname, char *slave_ifname);
149 137
150static void strncpy_IFNAMSIZ(char *dst, const char *src) 138static 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
166int ifenslave_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 154static int get_if_settings(char *ifname, struct dev_data *dd)
167int 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 */ 165static 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 */ 170static 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); 178static 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 */ 186static 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 */ 194static 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 */ 202static 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) { 210static 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
314static void get_drv_info(char *master_ifname) 219static 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
335static void change_active(char *master_ifname, char *slave_ifname) 259static 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
356static int enslave(char *master_ifname, char *slave_ifname) 280static 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
505static int get_if_settings(char *ifname, struct dev_data *dd) 429static 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
516static int get_slave_flags(char *slave_ifname) 450int ifenslave_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
451int 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
521static 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
529static 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
537static 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
545static 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
553static 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
561static 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
570static 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}