{
struct interface *ifp, *ifl = NULL;
- logger(LOG_ERR, "%s: removing interface", iface->name);
+ logger(LOG_INFO, "%s: removing interface", iface->name);
drop_config(iface, "STOP");
close_sockets(iface);
delete_timeout(NULL, iface);
}
static void
-handle_carrier(struct interface *iface)
+handle_carrier(const char *ifname)
{
- if (!(iface->state->options->options & DHCPCD_LINK))
+ struct interface *iface;
+
+ for (iface = ifaces; iface; iface = iface->next)
+ if (strcmp(iface->name, ifname) == 0)
+ break;
+ if (!iface || !(iface->state->options->options & DHCPCD_LINK))
return;
switch (carrier_status(iface->name)) {
case -1:
}
static void
-handle_new_interface(const char *name)
+handle_new_interface(const char *ifname)
{
- struct interface *ifs, *ifp;
- const char * const argv[] = { "dhcpcd", name };
+ struct interface *ifs, *ifp, *ifn, *ifl = NULL;
+ const char * const argv[] = { "dhcpcd", ifname };
int i;
/* If running off an interface list, check it's in it. */
if (ifc) {
for (i = 0; i < ifc; i++)
- if (strcmp(ifv[i], name) == 0)
+ if (strcmp(ifv[i], ifname) == 0)
break;
if (i >= ifc)
return;
}
if ((ifs = discover_interfaces(2, UNCONST(argv)))) {
- for (ifp = ifs; ifp; ifp = ifp->next)
+ for (ifp = ifs; ifp; ifp = ifp->next) {
+ /* Check if we already have the interface */
+ for (ifn = ifaces; ifn; ifn = ifn->next) {
+ if (strcmp(ifn->name, ifp->name) == 0)
+ break;
+ ifl = ifn;
+ }
+ if (ifn)
+ continue;
init_state(ifp, 2, UNCONST(argv));
- if (ifaces) {
- ifp = ifaces;
- while (ifp->next)
- ifp = ifp->next;
- ifp->next = ifs;
- } else
- ifaces = ifs;
+ if (ifl)
+ ifl->next = ifp;
+ else
+ ifaces = ifp;
+ }
}
}
+static void
+handle_remove_interface(const char *ifname)
+{
+ struct interface *iface;
+
+ for (iface = ifaces; iface; iface = iface->next)
+ if (strcmp(iface->name, ifname) == 0)
+ break;
+ if (iface && iface->state->options->options & DHCPCD_LINK)
+ stop_interface(iface);
+}
+
static void
handle_link(_unused void *arg)
{
- if (manage_link(linkfd, ifaces, handle_carrier,
- handle_new_interface, stop_interface) == -1)
+ if (manage_link(linkfd,
+ handle_carrier,
+ handle_new_interface,
+ handle_remove_interface) == -1)
logger(LOG_ERR, "manage_link: %s", strerror(errno));
}
int
handle_args(int argc, char **argv)
{
- struct interface *ifs, *ifp, *ifl = NULL;
+ struct interface *ifs, *ifp, *ifl = NULL, *ifn;
int do_exit = 0, do_release = 0, do_reboot = 0, opt, oi = 0;
optind = 0;
if (do_release)
send_release(ifp);
if (do_exit || do_release) {
+ logger(LOG_INFO, "%s: removing interface", ifp->name);
drop_config(ifp, do_release ? "RELEASE" : "STOP");
close_sockets(ifp);
delete_timeout(NULL, ifp);
if ((ifs = discover_interfaces(argc, argv))) {
argc += optind;
argv -= optind;
- for (ifp = ifs; ifp; ifp = ifp->next)
- init_state(ifp, argc, argv);
- if (ifaces) {
- ifp = ifaces;
- while (ifp->next)
- ifp = ifp->next;
- ifp->next = ifs;
- } else
- ifaces = ifs;
+ for (ifp = ifs; ifp; ifp = ifp->next) {
+ for (ifn = ifaces; ifn; ifn = ifn->next) {
+ if (strcmp(ifn->name, ifp->name) == 0)
+ break;
+ ifl = ifn;
+ }
+ if (!ifn) {
+ init_state(ifp, argc, argv);
+ if (ifl)
+ ifl->next = ifp;
+ else
+ ifaces = ifp;
+ }
+ }
}
return 0;
}
#define BUFFER_LEN 2048
int
-manage_link(int fd, struct interface *ifaces,
- void (*if_carrier)(struct interface *),
+manage_link(int fd,
+ void (*if_carrier)(const char *),
void (*if_add)(const char *),
- void (*if_remove)(struct interface *))
+ void (*if_remove)(const char *))
{
char buffer[2048], *p;
+ char ifname[IFNAMSIZ + 1];
ssize_t bytes;
struct rt_msghdr *rtm;
struct if_announcemsghdr *ifa;
if_add(ifa->ifan_name);
break;
case IFAN_DEPARTURE:
- for (iface = ifaces; iface; iface = iface->next)
- if (strcmp(ifa->ifan_name, iface->name) == 0) {
- if_remove(iface);
- break;
- }
+ if_remove(ifa->ifan_name);
break;
- }
break;
case RTM_IFINFO:
ifm = (struct if_msghdr *)p;
- for (iface = ifaces; iface; iface = iface->next)
- if (ifm->ifm_index == if_nametoindex(iface->name)) {
- if_carrier(iface);
- break;
- }
+ memset(ifname, 0, sizeof(ifname));
+ if (if_indextoname(ifm->ifm_index, ifname))
+ if_carrier(ifname);
break;
}
}
#define BUFFERLEN 256
+static void (*nl_carrier)(const char *) = NULL;
+static void (*nl_add)(const char *) = NULL;
+static void (*nl_remove)(const char *) = NULL;
+
int
open_link_socket(void)
{
static int
get_netlink(int fd, int flags,
- int (*callback)(struct nlmsghdr *, const struct interface *),
- const struct interface *iface)
+ int (*callback)(struct nlmsghdr *))
{
char *buffer = NULL;
ssize_t bytes;
NLMSG_OK(nlm, (size_t)bytes);
nlm = NLMSG_NEXT(nlm, bytes))
{
- r = callback(nlm, iface);
+ r = callback(nlm);
if (r != 0)
goto eexit;
}
}
static int
-err_netlink(struct nlmsghdr *nlm, _unused const struct interface *iface)
+err_netlink(struct nlmsghdr *nlm)
{
struct nlmsgerr *err;
int l;
}
static int
-link_netlink(struct nlmsghdr *nlm, const struct interface *ifaces)
+link_netlink(struct nlmsghdr *nlm)
{
int len;
struct rtattr *rta;
struct ifinfomsg *ifi;
char ifn[IF_NAMESIZE + 1];
- const struct interface *iface;
if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK)
return 0;
}
ifi = NLMSG_DATA(nlm);
if (ifi->ifi_flags & IFF_LOOPBACK)
- return 0;
+ return 1;
rta = (struct rtattr *) ((char *)ifi + NLMSG_ALIGN(sizeof(*ifi)));
len = NLMSG_PAYLOAD(nlm, sizeof(*ifi));
*ifn = '\0';
case IFLA_WIRELESS:
/* Ignore wireless messages */
if (nlm->nlmsg_type == RTM_NEWLINK &&
- ifi->ifi_change == 0)
- return 0;
+ ifi->ifi_change == 0)
+ return 1;
break;
case IFLA_IFNAME:
strlcpy(ifn, RTA_DATA(rta), sizeof(ifn));
}
rta = RTA_NEXT(rta, len);
}
-
- for (iface = ifaces; iface; iface = iface->next)
- if (strcmp(iface->name, ifn) == 0)
- return 1;
- return 0;
+ if (nlm->nlmsg_type == RTM_NEWLINK) {
+ if (ifi->ifi_change == ~0U) {
+ if (nl_add)
+ nl_add(ifn);
+ } else {
+ if (nl_carrier)
+ nl_carrier(ifn);
+ }
+ } else {
+ if (nl_remove)
+ nl_remove(ifn);
+ }
+ return 1;
}
-manage_link(int fd, struct interface *ifaces,
- void (*if_carrier)(struct interface *),
+int
+manage_link(int fd,
+ void (*if_carrier)(const char *),
void (*if_add)(const char *),
- void (*if_remove)(struct interface *))
+ void (*if_remove)(const char *))
{
- return get_netlink(fd, MSG_DONTWAIT, &link_netlink, ifaces);
+ nl_carrier = if_carrier;
+ nl_add = if_add;
+ nl_remove = if_remove;
+ return get_netlink(fd, MSG_DONTWAIT, &link_netlink);
}
static int
hdr->nlmsg_seq = ++seq;
if (sendmsg(fd, &msg, 0) != -1)
- r = get_netlink(fd, 0, &err_netlink, NULL);
+ r = get_netlink(fd, 0, &err_netlink);
else
r = -1;
close(fd);
ssize_t get_raw_packet(struct interface *, int, void *, ssize_t);
int open_link_socket(void);
-int manage_link(int, struct interface *,
- void (*)(struct interface *),
+int manage_link(int,
void (*)(const char *),
- void (*)(struct interface *));
+ void (*)(const char *),
+ void (*)(const char *));
int carrier_status(const char *);
#endif