X-Git-Url: https://roy.marples.name/git diff --git a/src/libdhcpcd/dispatch.c b/src/libdhcpcd/dispatch.c index c36f297..dbe4b7f 100644 --- a/src/libdhcpcd/dispatch.c +++ b/src/libdhcpcd/dispatch.c @@ -1,6 +1,6 @@ /* * libdhcpcd - * Copyright 2009 Roy Marples + * Copyright 2009-2014 Roy Marples * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,6 +30,9 @@ #define IN_LIBDHCPCD #include "libdhcpcd.h" +static const char * const dhcpcd_types[] = + { "link", "ipv4", "ra", "dhcp6", NULL }; + static const char * dhcpcd_message_get_string(DHCPCD_MESSAGE *msg) { @@ -51,6 +54,7 @@ dhcpcd_handle_event(DHCPCD_CONNECTION *con, 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; @@ -60,38 +64,93 @@ dhcpcd_handle_event(DHCPCD_CONNECTION *con, DHCPCD_MESSAGE *msg) 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); } @@ -101,6 +160,7 @@ dhcpcd_dispatch_message(DHCPCD_CONNECTION *con, DHCPCD_MESSAGE *msg) { bool handled; const char *str; + DHCPCD_IF *ifp; if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) return false; @@ -122,8 +182,9 @@ dhcpcd_dispatch_message(DHCPCD_CONNECTION *con, DHCPCD_MESSAGE *msg) { 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);