* - Code cleanup and style changes
* set version to 1.1.0
*/
+//config:config IFENSLAVE
+//config: bool "ifenslave"
+//config: default y
+//config: select PLATFORM_LINUX
+//config: help
+//config: Userspace application to bind several interfaces
+//config: to a logical interface (use with kernel bonding driver).
+
+//applet:IF_IFENSLAVE(APPLET(ifenslave, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_IFENSLAVE) += ifenslave.o interface.o
+
+//usage:#define ifenslave_trivial_usage
+//usage: "[-cdf] MASTER_IFACE SLAVE_IFACE..."
+//usage:#define ifenslave_full_usage "\n\n"
+//usage: "Configure network interfaces for parallel routing\n"
+//usage: "\n -c,--change-active Change active slave"
+//usage: "\n -d,--detach Remove slave interface from bonding device"
+//usage: "\n -f,--force Force, even if interface is not Ethernet"
+/* //usage: "\n -r,--receive-slave Create a receive-only slave" */
+//usage:
+//usage:#define ifenslave_example_usage
+//usage: "To create a bond device, simply follow these three steps:\n"
+//usage: "- ensure that the required drivers are properly loaded:\n"
+//usage: " # modprobe bonding ; modprobe <3c59x|eepro100|pcnet32|tulip|...>\n"
+//usage: "- assign an IP address to the bond device:\n"
+//usage: " # ifconfig bond0 <addr> netmask <mask> broadcast <bcast>\n"
+//usage: "- attach all the interfaces you need to the bond device:\n"
+//usage: " # ifenslave bond0 eth0 eth1 eth2\n"
+//usage: " If bond0 didn't have a MAC address, it will take eth0's. Then, all\n"
+//usage: " interfaces attached AFTER this assignment will get the same MAC addr.\n\n"
+//usage: " To detach a dead interface without setting the bond device down:\n"
+//usage: " # ifenslave -d bond0 eth1\n\n"
+//usage: " To set the bond device down and automatically release all the slaves:\n"
+//usage: " # ifconfig bond0 down\n\n"
+//usage: " To change active slave:\n"
+//usage: " # ifenslave -c bond0 eth0\n"
#include "libbb.h"
-#include <net/if_arp.h>
+/* #include <net/if.h> - no. linux/if_bonding.h pulls in linux/if.h */
+#include <linux/if.h>
+//#include <net/if_arp.h> - not needed?
#include <linux/if_bonding.h>
#include <linux/sockios.h>
-
-typedef unsigned long long u64; /* hack, so we may include kernel's ethtool.h */
-typedef uint32_t u32; /* ditto */
-typedef uint16_t u16; /* ditto */
-typedef uint8_t u8; /* ditto */
+#include "fix_u32.h" /* hack, so we may include kernel's ethtool.h */
#include <linux/ethtool.h>
+#ifndef BOND_ABI_VERSION
+# define BOND_ABI_VERSION 2
+#endif
+#ifndef IFNAMSIZ
+# define IFNAMSIZ 16
+#endif
struct dev_data {
/* NOINLINEs are placed where it results in smaller code (gcc 4.3.1) */
-static void strncpy_IFNAMSIZ(char *dst, const char *src)
-{
- strncpy(dst, src, IFNAMSIZ);
-}
-
static int ioctl_on_skfd(unsigned request, struct ifreq *ifr)
{
return ioctl(skfd, request, ifr);
static int set_ifrname_and_do_ioctl(unsigned request, struct ifreq *ifr, const char *ifname)
{
- strncpy_IFNAMSIZ(ifr->ifr_name, ifname);
+ strncpy_IFNAMSIZ(ifr->ifr_name, ifname);
return ioctl_on_skfd(request, ifr);
}
if (res < 0) {
ifr.ifr_addr.sa_family = AF_INET;
memset(ifr.ifr_addr.sa_data, 0,
- sizeof(ifr.ifr_addr.sa_data));
+ sizeof(ifr.ifr_addr.sa_data));
}
res = set_ifrname_and_do_ioctl(ifra[i].s_ioctl, &ifr, slave_ifname);
struct ifreq ifr;
if (!(slave.flags.ifr_flags & IFF_SLAVE)) {
- bb_error_msg_and_die(
- "%s is not a slave",
- slave_ifname);
+ bb_error_msg_and_die("%s is not a slave", slave_ifname);
}
strncpy_IFNAMSIZ(ifr.ifr_slave, slave_ifname);
int res = 0;
if (!(slave.flags.ifr_flags & IFF_SLAVE)) {
- bb_error_msg("%s is not a slave",
- slave_ifname);
+ bb_error_msg("%s is not a slave", slave_ifname);
return 1;
}
}
int ifenslave_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int ifenslave_main(int argc ATTRIBUTE_UNUSED, char **argv)
+int ifenslave_main(int argc UNUSED_PARAM, char **argv)
{
char *master_ifname, *slave_ifname;
int rv;
OPT_d = (1 << 1),
OPT_f = (1 << 2),
};
-#if ENABLE_GETOPT_LONG
+#if ENABLE_LONG_OPTS
static const char ifenslave_longopts[] ALIGN1 =
- "change-active\0" No_argument "c"
- "detach\0" No_argument "d"
- "force\0" No_argument "f"
+ "change-active\0" No_argument "c"
+ "detach\0" No_argument "d"
+ "force\0" No_argument "f"
+ /* "all-interfaces\0" No_argument "a" */
;
applet_long_options = ifenslave_longopts;
#endif
INIT_G();
- opt = getopt32(argv, "cdf");
+ opt = getopt32(argv, "cdfa");
argv += optind;
- if (opt & (opt-1)) /* options check */
+ if (opt & (opt-1)) /* Only one option can be given */
bb_show_usage();
master_ifname = *argv++;
return EXIT_SUCCESS;
}
- res = get_if_settings(master_ifname, &master);
- if (res) {
+ if (get_if_settings(master_ifname, &master)) {
/* Probably a good reason not to go on */
bb_perror_msg_and_die("%s: can't get settings", master_ifname);
}
- /* check if master is indeed a master;
+ /* Check if master is indeed a master;
* if not then fail any operation
*/
if (!(master.flags.ifr_flags & IFF_MASTER))
bb_error_msg_and_die("%s is not a master", master_ifname);
- /* check if master is up; if not then fail any operation */
+ /* Check if master is up; if not then fail any operation */
if (!(master.flags.ifr_flags & IFF_UP))
bb_error_msg_and_die("%s is not up", master_ifname);
- /* No opts: neither -c[hange] nor -d[etach] -> it's "enslave" then;
- * and -f[orce] is not there too */
- if (!opt) {
+#ifdef WHY_BOTHER
+ /* Neither -c[hange] nor -d[etach] -> it's "enslave" then;
+ * and -f[orce] is not there too. Check that it's ethernet. */
+ if (!(opt & (OPT_d|OPT_c|OPT_f))) {
/* The family '1' is ARPHRD_ETHER for ethernet. */
if (master.hwaddr.ifr_hwaddr.sa_family != 1) {
bb_error_msg_and_die(
master_ifname);
}
}
+#endif
/* Accepts only one slave */
if (opt & OPT_c) {
- /* change active slave */
+ /* Change active slave */
if (get_slave_flags(slave_ifname)) {
bb_perror_msg_and_die(
"%s: can't get flags", slave_ifname);
return EXIT_SUCCESS;
}
- /* Accept multiple slaves */
+ /* Accepts multiple slaves */
res = 0;
do {
if (opt & OPT_d) {
- /* detach a slave interface from the master */
+ /* Detach a slave interface from the master */
rv = get_slave_flags(slave_ifname);
if (rv) {
/* Can't work with this slave, */
/* remember the error and skip it */
bb_perror_msg(
- "skipping %s: can't get flags",
- slave_ifname);
+ "skipping %s: can't get %s",
+ slave_ifname, "flags");
res = rv;
continue;
}
rv = release(master_ifname, slave_ifname);
if (rv) {
- bb_perror_msg(
- "master %s, slave %s: "
- "can't release",
- master_ifname, slave_ifname);
+ bb_perror_msg("can't release %s from %s",
+ slave_ifname, master_ifname);
res = rv;
}
} else {
- /* attach a slave interface to the master */
+ /* Attach a slave interface to the master */
rv = get_if_settings(slave_ifname, &slave);
if (rv) {
/* Can't work with this slave, */
/* remember the error and skip it */
bb_perror_msg(
- "skipping %s: can't get settings",
- slave_ifname);
+ "skipping %s: can't get %s",
+ slave_ifname, "settings");
res = rv;
continue;
}
rv = enslave(master_ifname, slave_ifname);
if (rv) {
- bb_perror_msg(
- "master %s, slave %s: "
- "can't enslave",
- master_ifname, slave_ifname);
+ bb_perror_msg("can't enslave %s to %s",
+ slave_ifname, master_ifname);
res = rv;
}
}