97 #define APP_VERSION "1.1.0"
98 #define APP_RELDATE "December 1, 2003"
99 #define APP_NAME "ifenslave"
104 "o Detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n"
105 "o 2.4 kernel support added on 2001/02/16 by Chad N. Tindel\n"
106 " (ctindel at ieee dot org).\n";
108 static const char *usage_msg =
109 "Usage: ifenslave [-f] <master-if> <slave-if> [<slave-if>...]\n"
110 " ifenslave -d <master-if> <slave-if> [<slave-if>...]\n"
111 " ifenslave -c <master-if> <slave-if>\n"
112 " ifenslave --help\n";
114 static const char *help_msg =
116 " To create a bond device, simply follow these three steps :\n"
117 " - ensure that the required drivers are properly loaded :\n"
118 " # modprobe bonding ; modprobe <3c59x|eepro100|pcnet32|tulip|...>\n"
119 " - assign an IP address to the bond device :\n"
120 " # ifconfig bond0 <addr> netmask <mask> broadcast <bcast>\n"
121 " - attach all the interfaces you need to the bond device :\n"
122 " # ifenslave [{-f|--force}] bond0 eth0 [eth1 [eth2]...]\n"
123 " If bond0 didn't have a MAC address, it will take eth0's. Then, all\n"
124 " interfaces attached AFTER this assignment will get the same MAC addr.\n"
125 " (except for ALB/TLB modes)\n"
127 " To set the bond device down and automatically release all the slaves :\n"
128 " # ifconfig bond0 down\n"
130 " To detach a dead interface without setting the bond device down :\n"
131 " # ifenslave {-d|--detach} bond0 eth0 [eth1 [eth2]...]\n"
133 " To change active slave :\n"
134 " # ifenslave {-c|--change-active} bond0 eth0\n"
136 " To show master interface info\n"
137 " # ifenslave bond0\n"
139 " To show all interfaces info\n"
140 " # ifenslave {-a|--all-interfaces}\n"
142 " To be more verbose\n"
143 " # ifenslave {-v|--verbose} ...\n"
145 " # ifenslave {-u|--usage} Show usage\n"
146 " # ifenslave {-V|--version} Show version\n"
147 " # ifenslave {-h|--help} This message\n"
158 #include <sys/types.h>
159 #include <sys/socket.h>
160 #include <sys/ioctl.h>
162 #include <net/if_arp.h>
163 #include <linux/if_ether.h>
167 typedef unsigned long long u64;
170 typedef __uint8_t
u8;
171 #include <linux/ethtool.h>
175 {
"all-interfaces", 0, 0,
'a'},
176 {
"change-active", 0, 0,
'c'},
177 {
"detach", 0, 0,
'd'},
178 {
"force", 0, 0,
'f'},
180 {
"usage", 0, 0,
'u'},
181 {
"verbose", 0, 0,
'v'},
182 {
"version", 0, 0,
'V'},
226 static int get_drv_info(
char *master_ifname);
227 static int get_if_settings(
char *ifname,
struct dev_ifr ifra[]);
228 static int get_slave_flags(
char *slave_ifname);
229 static int set_master_hwaddr(
char *master_ifname,
struct sockaddr *hwaddr);
230 static int set_slave_hwaddr(
char *slave_ifname,
struct sockaddr *hwaddr);
231 static int set_slave_mtu(
char *slave_ifname,
int mtu);
232 static int set_if_flags(
char *ifname,
short flags);
233 static int set_if_up(
char *ifname,
short flags);
234 static int set_if_down(
char *ifname,
short flags);
235 static int clear_if_addr(
char *ifname);
236 static int set_if_addr(
char *master_ifname,
char *slave_ifname);
237 static int change_active(
char *master_ifname,
char *slave_ifname);
238 static int enslave(
char *master_ifname,
char *slave_ifname);
239 static int release(
char *master_ifname,
char *slave_ifname);
240 #define v_print(fmt, args...) \
242 fprintf(stderr, fmt, ## args )
246 char **spp, *master_ifname, *slave_ifname;
251 while ((c = getopt_long(argc, argv,
"acdfhuvV", longopts, 0)) !=
EOF) {
253 case 'a':
opt_a++; exclusive++;
break;
254 case 'c':
opt_c++; exclusive++;
break;
255 case 'd':
opt_d++; exclusive++;
break;
256 case 'f':
opt_f++; exclusive++;
break;
257 case 'h':
opt_h++; exclusive++;
break;
258 case 'u':
opt_u++; exclusive++;
break;
259 case 'v':
opt_v++;
break;
260 case 'V':
opt_V++; exclusive++;
break;
263 fprintf(stderr,
"%s", usage_msg);
271 fprintf(stderr,
"%s", usage_msg);
305 if (optind == argc) {
312 fprintf(stderr,
"%s", usage_msg);
320 master_ifname = *spp++;
322 if (master_ifname ==
NULL) {
323 fprintf(stderr,
"%s", usage_msg);
329 res = get_drv_info(master_ifname);
332 "Master '%s': Error: handshake with driver failed. "
338 slave_ifname = *spp++;
340 if (slave_ifname ==
NULL) {
342 fprintf(stderr,
"%s", usage_msg);
354 res = get_if_settings(master_ifname, master_ifra);
358 "Master '%s': Error: get settings failed: %s. "
369 "Illegal operation; the specified interface '%s' "
370 "is not a master. Aborting\n",
377 if (!(master_flags.ifr_flags &
IFF_UP)) {
379 "Illegal operation; the specified master interface "
389 unsigned char *hwaddr =
393 if (master_family != 1 && !
opt_f) {
395 "Illegal operation: The specified master "
396 "interface '%s' is not ethernet-like.\n "
397 "This program is designed to work with "
398 "ethernet-like network interfaces.\n "
399 "Use the '-f' option to force the "
407 for (i = 0; i < 6; i++) {
408 if (hwaddr[i] != 0) {
415 v_print(
"current hardware address of master '%s' "
416 "is %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
419 hwaddr[0], hwaddr[1],
420 hwaddr[2], hwaddr[3],
421 hwaddr[4], hwaddr[5],
429 res = get_slave_flags(slave_ifname);
432 "Slave '%s': Error: get flags failed. "
437 res = change_active(master_ifname, slave_ifname);
440 "Master '%s', Slave '%s': Error: "
441 "Change active failed\n",
442 master_ifname, slave_ifname);
449 rv = get_slave_flags(slave_ifname);
454 "Slave '%s': Error: get flags "
455 "failed. Skipping\n",
460 rv =
release(master_ifname, slave_ifname);
463 "Master '%s', Slave '%s': Error: "
465 master_ifname, slave_ifname);
470 rv = get_if_settings(slave_ifname, slave_ifra);
475 "Slave '%s': Error: get "
476 "settings failed: %s. "
482 rv = enslave(master_ifname, slave_ifname);
485 "Master '%s', Slave '%s': Error: "
487 master_ifname, slave_ifname);
491 }
while ((slave_ifname = *spp++) !=
NULL);
502 static short mif_flags;
505 static int if_getconfig(
char *ifname)
509 struct sockaddr dstaddr, broadaddr, netmask;
510 unsigned char *hwaddr;
512 strcpy(ifr.ifr_name, ifname);
515 mif_flags = ifr.ifr_flags;
516 printf(
"The result of SIOCGIFFLAGS on %s is %x.\n",
517 ifname, ifr.ifr_flags);
519 strcpy(ifr.ifr_name, ifname);
522 printf(
"The result of SIOCGIFADDR is %2.2x.%2.2x.%2.2x.%2.2x.\n",
523 ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1],
524 ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]);
526 strcpy(ifr.ifr_name, ifname);
531 hwaddr = (
unsigned char *)ifr.ifr_hwaddr.sa_data;
532 printf(
"The result of SIOCGIFHWADDR is type %d "
533 "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
534 ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
535 hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
537 strcpy(ifr.ifr_name, ifname);
541 metric = ifr.ifr_metric;
542 printf(
"The result of SIOCGIFMETRIC is %d\n", metric);
544 strcpy(ifr.ifr_name, ifname);
549 printf(
"The result of SIOCGIFMTU is %d\n", mtu);
551 strcpy(ifr.ifr_name, ifname);
555 dstaddr = ifr.ifr_dstaddr;
557 strcpy(ifr.ifr_name, ifname);
561 broadaddr = ifr.ifr_broadaddr;
563 strcpy(ifr.ifr_name, ifname);
567 netmask = ifr.ifr_netmask;
579 if (ifname == (
char *)
NULL) {
580 ifc.ifc_len =
sizeof(buff);
583 perror(
"SIOCGIFCONF failed");
588 for (i = ifc.ifc_len /
sizeof(
struct ifreq); --i >= 0; ifr++) {
589 if (if_getconfig(ifr->ifr_name) < 0) {
591 "%s: unknown interface.\n",
596 if (((mif_flags &
IFF_UP) == 0) && !
opt_a)
continue;
600 if (if_getconfig(ifname) < 0) {
602 "%s: unknown interface.\n", ifname);
607 static int get_drv_info(
char *master_ifname)
613 memset(&ifr, 0,
sizeof(ifr));
627 v_print(
"Master '%s': Error: get bonding info failed %s\n",
634 v_print(
"Master '%s': Error: got invalid string as an ABI "
635 "version from the bonding module\n",
646 static int change_active(
char *master_ifname,
char *slave_ifname)
651 if (!(slave_flags.ifr_flags &
IFF_SLAVE)) {
653 "Illegal operation: The specified slave interface "
654 "'%s' is not a slave\n",
664 v_print(
"Master '%s': Error: SIOCBONDCHANGEACTIVE failed: "
673 static int enslave(
char *master_ifname,
char *slave_ifname)
680 "Illegal operation: The specified slave interface "
681 "'%s' is already a slave\n",
686 res = set_if_down(slave_ifname, slave_flags.ifr_flags);
689 "Slave '%s': Error: bring interface down failed\n",
698 set_if_addr(master_ifname, slave_ifname);
700 res = clear_if_addr(slave_ifname);
703 "Slave '%s': Error: clear address failed\n",
709 if (master_mtu.ifr_mtu != slave_mtu.ifr_mtu) {
710 res = set_slave_mtu(slave_ifname, master_mtu.ifr_mtu);
713 "Slave '%s': Error: set MTU failed\n",
728 res = set_slave_hwaddr(slave_ifname,
732 "Slave '%s': Error: set hw address "
741 res = set_if_up(slave_ifname, slave_flags.ifr_flags);
744 "Slave '%s': Error: bring interface "
763 res = set_if_down(master_ifname, master_flags.ifr_flags);
766 "Master '%s': Error: bring interface "
773 res = set_master_hwaddr(master_ifname,
777 "Master '%s': Error: set hw address "
787 res = set_if_up(master_ifname, master_flags.ifr_flags);
790 "Master '%s': Error: bring interface "
793 goto undo_master_mac;
806 v_print(
"Master '%s': Error: SIOCBONDENSLAVE failed: %s\n",
812 goto undo_master_mac;
819 set_master_hwaddr(master_ifname, &(
master_hwaddr.ifr_hwaddr));
823 set_slave_hwaddr(slave_ifname, &(
slave_hwaddr.ifr_hwaddr));
825 set_slave_mtu(slave_ifname, slave_mtu.ifr_mtu);
829 static int release(
char *master_ifname,
char *slave_ifname)
834 if (!(slave_flags.ifr_flags &
IFF_SLAVE)) {
836 "Illegal operation: The specified slave interface "
837 "'%s' is not a slave\n",
847 v_print(
"Master '%s': Error: SIOCBONDRELEASE failed: %s\n",
854 res = set_if_down(slave_ifname, slave_flags.ifr_flags);
857 "Slave '%s': Error: bring interface "
864 set_slave_mtu(slave_ifname, 1500);
869 static int get_if_settings(
char *ifname,
struct dev_ifr ifra[])
876 res = ioctl(
skfd, ifra[i].req_type, ifra[i].req_ifr);
879 v_print(
"Interface '%s': Error: %s failed: %s\n",
880 ifname, ifra[i].req_name,
890 static int get_slave_flags(
char *slave_ifname)
898 v_print(
"Slave '%s': Error: SIOCGIFFLAGS failed: %s\n",
901 v_print(
"Slave %s: flags %04X.\n",
902 slave_ifname, slave_flags.ifr_flags);
908 static int set_master_hwaddr(
char *master_ifname,
struct sockaddr *hwaddr)
910 unsigned char *
addr = (
unsigned char *)hwaddr->
sa_data;
919 v_print(
"Master '%s': Error: SIOCSIFHWADDR failed: %s\n",
923 v_print(
"Master '%s': hardware address set to "
924 "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
925 master_ifname, addr[0], addr[1], addr[2],
926 addr[3], addr[4], addr[5]);
932 static int set_slave_hwaddr(
char *slave_ifname,
struct sockaddr *hwaddr)
934 unsigned char *addr = (
unsigned char *)hwaddr->
sa_data;
944 v_print(
"Slave '%s': Error: SIOCSIFHWADDR failed: %s\n",
948 v_print(
" The device is busy: it must be idle "
949 "before running this command.\n");
951 v_print(
" The device does not support setting "
953 " Your kernel likely does not support slave "
956 v_print(
" The device's address type does not match "
957 "the master's address type.\n");
961 v_print(
"Slave '%s': hardware address set to "
962 "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
963 slave_ifname, addr[0], addr[1], addr[2],
964 addr[3], addr[4], addr[5]);
970 static int set_slave_mtu(
char *slave_ifname,
int mtu)
981 v_print(
"Slave '%s': Error: SIOCSIFMTU failed: %s\n",
984 v_print(
"Slave '%s': MTU set to %d.\n", slave_ifname, mtu);
990 static int set_if_flags(
char *ifname,
short flags)
995 ifr.ifr_flags =
flags;
1001 v_print(
"Interface '%s': Error: SIOCSIFFLAGS failed: %s\n",
1004 v_print(
"Interface '%s': flags set to %04X.\n", ifname, flags);
1010 static int set_if_up(
char *ifname,
short flags)
1012 return set_if_flags(ifname, flags |
IFF_UP);
1015 static int set_if_down(
char *ifname,
short flags)
1017 return set_if_flags(ifname, flags & ~
IFF_UP);
1020 static int clear_if_addr(
char *ifname)
1026 ifr.ifr_addr.sa_family =
AF_INET;
1027 memset(ifr.ifr_addr.sa_data, 0,
sizeof(ifr.ifr_addr.sa_data));
1032 v_print(
"Interface '%s': Error: SIOCSIFADDR failed: %s\n",
1035 v_print(
"Interface '%s': address cleared\n", ifname);
1041 static int set_if_addr(
char *master_ifname,
char *slave_ifname)
1062 res = ioctl(
skfd, ifra[i].g_ioctl, &ifr);
1066 v_print(
"Interface '%s': Error: SIOCG%s failed: %s\n",
1067 master_ifname, ifra[i].req_name,
1070 ifr.ifr_addr.sa_family =
AF_INET;
1071 memset(ifr.ifr_addr.sa_data, 0,
1072 sizeof(ifr.ifr_addr.sa_data));
1076 res = ioctl(
skfd, ifra[i].s_ioctl, &ifr);
1078 int saved_errno =
errno;
1080 v_print(
"Interface '%s': Error: SIOCS%s failed: %s\n",
1081 slave_ifname, ifra[i].req_name,
1086 ipaddr = (
unsigned char *)ifr.ifr_addr.sa_data;
1087 v_print(
"Interface '%s': set IP %s to %d.%d.%d.%d\n",
1088 slave_ifname, ifra[i].
desc,
1089 ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);