Support the new link type.
[dhcpcd-ui] / src / libdhcpcd / dispatch.c
index c36f29712fc03945b82f866f6b23dffbf111b315..79208334f587e3d92921a2f2775b2083a184d80a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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
@@ -30,6 +30,8 @@
 #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)
 {
@@ -51,6 +53,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 +63,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 +159,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 +181,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);