/* vi: set sw=4 ts=4: */
/*
- * ifplugd for busybox
+ * ifplugd for busybox, based on ifplugd 0.28 (written by Lennart Poettering).
*
* Copyright (C) 2009 Maksym Kryzhanovskyy <xmaks@email.cz>
*
#include <linux/wireless.h>
/*
-TODO: describe compat status here.
+From initial port to busybox, removed most of the redundancy by
+converting implementation of a polymorphic interface to the strict
+functional style. The main role is run a script when link state
+changed, other activities like audio signal or detailed reports
+are on the script itself.
One questionable point of the design is netlink usage:
{
int r = ioctl(ioctl_fd, request, data);
if (r < 0 && errmsg)
- bb_perror_msg(errmsg);
+ bb_perror_msg("%s failed", errmsg);
return r;
}
return;
set_ifreq_to_ifname(&ifrequest);
- if (network_ioctl(SIOCGIFFLAGS, &ifrequest, "can't get interface flags") < 0) {
+ if (network_ioctl(SIOCGIFFLAGS, &ifrequest, "getting interface flags") < 0) {
G.iface_exists = 0;
return;
}
ifrequest.ifr_flags |= IFF_UP;
/* Let user know we mess up with interface */
bb_error_msg("upping interface");
- if (network_ioctl(SIOCSIFFLAGS, &ifrequest, "can't set interface flags") < 0)
+ if (network_ioctl(SIOCSIFFLAGS, &ifrequest, "setting interface flags") < 0)
xfunc_die();
}
set_ifreq_to_ifname(&ifreq);
- if (network_ioctl(SIOCGMIIPHY, &ifreq, "SIOCGMIIPHY failed") < 0) {
+ if (network_ioctl(SIOCGMIIPHY, &ifreq, "SIOCGMIIPHY") < 0) {
return IFSTATUS_ERR;
}
mii->reg_num = 1;
- if (network_ioctl(SIOCGMIIREG, &ifreq, "SIOCGMIIREG failed") < 0) {
+ if (network_ioctl(SIOCGMIIREG, &ifreq, "SIOCGMIIREG") < 0) {
return IFSTATUS_ERR;
}
set_ifreq_to_ifname(&ifreq);
- if (network_ioctl(SIOCDEVPRIVATE, &ifreq, "SIOCDEVPRIVATE failed") < 0) {
+ if (network_ioctl(SIOCDEVPRIVATE, &ifreq, "SIOCDEVPRIVATE") < 0) {
return IFSTATUS_ERR;
}
mii->reg_num = 1;
- if (network_ioctl(SIOCDEVPRIVATE+1, &ifreq, "SIOCDEVPRIVATE+1 failed") < 0) {
+ if (network_ioctl(SIOCDEVPRIVATE+1, &ifreq, "SIOCDEVPRIVATE+1") < 0) {
return IFSTATUS_ERR;
}
edata.cmd = ETHTOOL_GLINK;
ifreq.ifr_data = (void*) &edata;
- if (network_ioctl(SIOCETHTOOL, &ifreq, "ETHTOOL_GLINK failed") < 0) {
+ if (network_ioctl(SIOCETHTOOL, &ifreq, "ETHTOOL_GLINK") < 0) {
return IFSTATUS_ERR;
}
set_ifreq_to_ifname(&ifreq);
- if (network_ioctl(SIOCGIFFLAGS, &ifreq, "SIOCGIFFLAGS failed") < 0) {
+ if (network_ioctl(SIOCGIFFLAGS, &ifreq, "SIOCGIFFLAGS") < 0) {
return IFSTATUS_ERR;
}
static smallint detect_link_wlan(void)
{
+ int i;
struct iwreq iwrequest;
uint8_t mac[ETH_ALEN];
- memset(&iwrequest, 0, sizeof(struct iwreq));
+ memset(&iwrequest, 0, sizeof(iwrequest));
strncpy_IFNAMSIZ(iwrequest.ifr_ifrn.ifrn_name, G.iface);
- if (network_ioctl(SIOCGIWAP, &iwrequest, "SIOCGIWAP failed") < 0) {
+ if (network_ioctl(SIOCGIWAP, &iwrequest, "SIOCGIWAP") < 0) {
return IFSTATUS_ERR;
}
- memcpy(mac, &(iwrequest.u.ap_addr.sa_data), ETH_ALEN);
+ memcpy(mac, &iwrequest.u.ap_addr.sa_data, ETH_ALEN);
if (mac[0] == 0xFF || mac[0] == 0x44 || mac[0] == 0x00) {
- for (int i = 1; i < ETH_ALEN; ++i) {
+ for (i = 1; i < ETH_ALEN; ++i) {
if (mac[i] != mac[0])
return IFSTATUS_UP;
}
static smallint detect_link_auto(void)
{
- const char *method;
+ static const struct {
+ const char *name;
+ smallint (*func)(void);
+ } method[] = {
+ { "SIOCETHTOOL" , &detect_link_ethtool },
+ { "SIOCGMIIPHY" , &detect_link_mii },
+ { "SIOCDEVPRIVATE" , &detect_link_priv },
+ { "wireless extension", &detect_link_wlan },
+ { "IFF_RUNNING" , &detect_link_iff },
+ };
+ int i;
smallint iface_status;
smallint sv_logmode;
}
sv_logmode = logmode;
- logmode = LOGMODE_NONE;
-
- iface_status = detect_link_ethtool();
- if (iface_status != IFSTATUS_ERR) {
- G.cached_detect_link_func = detect_link_ethtool;
- method = "SIOCETHTOOL";
- found_method:
+ for (i = 0; i < ARRAY_SIZE(method); i++) {
+ logmode = LOGMODE_NONE;
+ iface_status = method[i].func();
logmode = sv_logmode;
- bb_error_msg("using %s detection mode", method);
- return iface_status;
- }
-
- iface_status = detect_link_mii();
- if (iface_status != IFSTATUS_ERR) {
- G.cached_detect_link_func = detect_link_mii;
- method = "SIOCGMIIPHY";
- goto found_method;
- }
-
- iface_status = detect_link_priv();
- if (iface_status != IFSTATUS_ERR) {
- G.cached_detect_link_func = detect_link_priv;
- method = "SIOCDEVPRIVATE";
- goto found_method;
- }
-
- iface_status = detect_link_wlan();
- if (iface_status != IFSTATUS_ERR) {
- G.cached_detect_link_func = detect_link_wlan;
- method = "wireless extension";
- goto found_method;
- }
-
- iface_status = detect_link_iff();
- if (iface_status != IFSTATUS_ERR) {
- G.cached_detect_link_func = detect_link_iff;
- method = "IFF_RUNNING";
- goto found_method;
+ if (iface_status != IFSTATUS_ERR) {
+ G.cached_detect_link_func = method[i].func;
+ bb_error_msg("using %s detection mode", method[i].name);
+ break;
+ }
}
-
- logmode = sv_logmode;
- return iface_status; /* IFSTATUS_ERR */
+ return iface_status;
}
static smallint detect_link(void)
static NOINLINE int check_existence_through_netlink(void)
{
+ int iface_len;
char replybuf[1024];
+ iface_len = strlen(G.iface);
while (1) {
struct nlmsghdr *mhdr;
ssize_t bytes;
mhdr = (struct nlmsghdr*)replybuf;
while (bytes > 0) {
- if (!NLMSG_OK(mhdr, bytes)
- || bytes < sizeof(struct nlmsghdr)
- || bytes < mhdr->nlmsg_len
- ) {
+ if (!NLMSG_OK(mhdr, bytes)) {
bb_error_msg("netlink packet too small or truncated");
return -1;
}
if (mhdr->nlmsg_type == RTM_NEWLINK || mhdr->nlmsg_type == RTM_DELLINK) {
struct rtattr *attr;
- struct ifinfomsg *imsg;
int attr_len;
- imsg = NLMSG_DATA(mhdr);
-
if (mhdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) {
bb_error_msg("netlink packet too small or truncated");
return -1;
}
- attr = (struct rtattr*)((char*)imsg + NLMSG_ALIGN(sizeof(struct ifinfomsg)));
- attr_len = NLMSG_PAYLOAD(mhdr, sizeof(struct ifinfomsg));
+ attr = IFLA_RTA(NLMSG_DATA(mhdr));
+ attr_len = IFLA_PAYLOAD(mhdr);
while (RTA_OK(attr, attr_len)) {
if (attr->rta_type == IFLA_IFNAME) {
- char ifname[IFNAMSIZ + 1];
int len = RTA_PAYLOAD(attr);
-
if (len > IFNAMSIZ)
len = IFNAMSIZ;
- memcpy(ifname, RTA_DATA(attr), len);
- if (strcmp(G.iface, ifname) == 0) {
+ if (iface_len <= len
+ && strncmp(G.iface, RTA_DATA(attr), len) == 0
+ ) {
G.iface_exists = (mhdr->nlmsg_type == RTM_NEWLINK);
}
}