/*
* libdhcpcd
- * Copyright 2009 Roy Marples <roy@marples.name>
+ * Copyright 2009-2014 Roy Marples <roy@marples.name>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#define IN_LIBDHCPCD
#include "libdhcpcd.h"
+static const char *dhcpcd_types[] = { "link", "ipv4", "ra", "dhcp6", NULL };
+
static const char *
dhcpcd_message_get_string(DHCPCD_MESSAGE *msg)
{
DBusMessageIter args;
DHCPCD_IF *i, *e, *l, *n, *nl;
char *order, *o, *p;
+ int ti;
if (!dbus_message_iter_init(msg, &args))
return;
return;
p = order;
n = nl = NULL;
- while ((o = strsep(&p, " ")) != NULL) {
+
+ /* Remove all instances on carrier drop */
+ if (strcmp(i->reason, "NOCARRIER") == 0 ||
+ strcmp(i->reason, "DEPARTED") == 0 ||
+ strcmp(i->reason, "STOPPED") == 0)
+ {
+ l = NULL;
+ for (e = con->interfaces; e; e = n) {
+ n = e->next;
+ if (strcmp(e->ifname, i->ifname) == 0) {
+ if (strcmp(e->type, i->type) == 0)
+ l = nl = e;
+ else {
+ if (l)
+ l->next = e->next;
+ else
+ con->interfaces = e->next;
+ free(e);
+ }
+ } else
+ l = e;
+ }
+ }
+
+ /* Find our pointer */
+ if (nl == NULL) {
l = NULL;
for (e = con->interfaces; e; e = e->next) {
- if (strcmp(e->ifname, o) == 0)
+ if (strcmp(e->ifname, i->ifname) == 0 &&
+ strcmp(e->type, i->type) == 0)
+ {
+ nl = e;
break;
+ }
l = e;
}
- if (e == NULL) {
- e = i;
- } else {
- if (l != NULL)
+ }
+ if (nl) {
+ /* Preserve the pointer for wireless history */
+ n = nl->next;
+ memcpy(nl, i, sizeof(*i));
+ nl->next = n;
+ free(i);
+ i = nl;
+ } else {
+ /* Append it then */
+ if (l)
+ l->next = i;
+ else
+ con->interfaces = i;
+ i->next = NULL;
+ }
+
+ /* Sort! */
+ n = nl = NULL;
+ while ((o = strsep(&p, " ")) != NULL) {
+ for (ti = 0; dhcpcd_types[ti]; ti++) {
+ l = NULL;
+ for (e = con->interfaces; e; e = e->next) {
+ if (strcmp(e->ifname, o) == 0 &&
+ strcmp(e->type, dhcpcd_types[ti]) == 0)
+ break;
+ l = e;
+ }
+ if (e == NULL)
+ continue;
+ if (l)
l->next = e->next;
else
con->interfaces = e->next;
e->next = NULL;
+ if (nl == NULL)
+ n = nl = e;
+ else {
+ nl->next = e;
+ nl = e;
+ }
}
- if (e != i && strcmp(e->ifname, i->ifname) == 0) {
- /* Preserve the pointer */
- memcpy(e, i, sizeof(*e));
- free(i);
- i = e;
- }
- if (nl == NULL)
- n = nl = e;
- else {
- nl->next = e;
- nl = nl->next;
- }
}
- if (nl != NULL)
- nl->next = con->interfaces;
+ /* Free any stragglers */
+ while (con->interfaces) {
+ e = con->interfaces->next;
+ free(con->interfaces);
+ con->interfaces = e;
+ }
con->interfaces = n;
+
if (con->event)
con->event(con, i, con->signal_data);
}
{
bool handled;
const char *str;
+ DHCPCD_IF *ifp;
if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
return false;
{
if (con->wi_scanresults) {
str = dhcpcd_message_get_string(msg);
- con->wi_scanresults(con, dhcpcd_if_find(con, str),
- con->signal_data);
+ ifp = dhcpcd_if_find(con, str, "link");
+ if (ifp)
+ con->wi_scanresults(con, ifp, con->signal_data);
}
} else if (dbus_message_is_signal(msg, DHCPCD_SERVICE, "Event"))
dhcpcd_handle_event(con, msg);