No need to log extra messages here.
[dhcpcd-ui] / src / libdhcpcd / main.c
index 6e4059e2dbb714e5e2a428062b585f0228a8e299..d63844fe4e5d30fcfd93edd5d06ea3edf5ad5897 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
@@ -24,6 +24,7 @@
  * SUCH DAMAGE.
  */
 
+#include <arpa/inet.h>
 #include <errno.h>
 #include <poll.h>
 #include <stdbool.h>
@@ -35,6 +36,7 @@
 
 #define IN_LIBDHCPCD
 #include "libdhcpcd.h"
+#include "config.h"
 
 #define DHCPCD_TIMEOUT_MS 500
 
@@ -53,11 +55,12 @@ static dbus_bool_t
 dhcpcd_add_watch(DBusWatch *watch, void *data)
 {
        DHCPCD_WATCH *w;
-       int flags;
+       int fd;
+       unsigned int flags;
 
-       flags = dbus_watch_get_unix_fd(watch);
+       fd = dbus_watch_get_unix_fd(watch);
        for (w = dhcpcd_watching; w; w = w->next) {
-               if (w->pollfd.fd == flags)
+               if (w->pollfd.fd == fd)
                        break;
        }
        if (w == NULL) {
@@ -70,7 +73,7 @@ dhcpcd_add_watch(DBusWatch *watch, void *data)
 
        w->connection = (DHCPCD_CONNECTION *)data;
        w->watch = watch;
-       w->pollfd.fd = flags;
+       w->pollfd.fd = fd;
        flags = dbus_watch_get_flags(watch);
        w->pollfd.events = POLLHUP | POLLERR;
        if (flags & DBUS_WATCH_READABLE)
@@ -109,6 +112,7 @@ dhcpcd_delete_watch(DBusWatch *watch, void *data)
 static DBusHandlerResult
 dhcpcd_message(_unused DBusConnection *bus, DBusMessage *msg, void *data)
 {
+
        if (dhcpcd_dispatch_message((DHCPCD_CONNECTION *)data, msg))
                return DBUS_HANDLER_RESULT_HANDLED;
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -144,10 +148,9 @@ dhcpcd_open(char **error)
        }
        if (bus == NULL)
                return NULL;
-       con = malloc(sizeof(*con));
+       con = calloc(1, sizeof(*con));
        if (con == NULL)
                goto bad;
-       memset(con, 0, sizeof(*con));
        con->bus = bus;
        if (!dbus_connection_set_watch_functions(bus,
                dhcpcd_add_watch, dhcpcd_delete_watch, NULL, con, NULL))
@@ -227,6 +230,7 @@ dhcpcd_if_connection(DHCPCD_IF *interface)
 void
 dhcpcd_error_clear(DHCPCD_CONNECTION *con)
 {
+
        free(con->error);
        con->error = NULL;
        con->err = 0;
@@ -235,6 +239,7 @@ dhcpcd_error_clear(DHCPCD_CONNECTION *con)
 void
 dhcpcd_error_set(DHCPCD_CONNECTION *con, const char *error, int err)
 {
+
        dhcpcd_error_clear(con);
        if (error != NULL) {
                con->error = strdup(error);
@@ -249,6 +254,7 @@ dhcpcd_error_set(DHCPCD_CONNECTION *con, const char *error, int err)
 const char *
 dhcpcd_error(DHCPCD_CONNECTION *con)
 {
+
        return con->error;
 }
 
@@ -256,6 +262,7 @@ bool
 dhcpcd_iter_get(DHCPCD_CONNECTION *con, DBusMessageIter *iter,
     int type, void *arg)
 {
+
        if (dbus_message_iter_get_arg_type(iter) == type) {
                dbus_message_iter_get_basic(iter, arg);
                dbus_message_iter_next(iter);
@@ -270,7 +277,7 @@ dhcpcd_message_error(DHCPCD_CONNECTION *con, DHCPCD_MESSAGE *msg)
 {
        DBusMessageIter args;
        char *s;
-       
+
        if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_ERROR)
                return false;
        if (dbus_message_iter_init(msg, &args) &&
@@ -311,7 +318,7 @@ dhcpcd_message_reply(DHCPCD_CONNECTION *con, const char *cmd, const char *arg)
 {
        DBusMessage *msg, *reply;
        DBusMessageIter args;
-       
+
        msg = dbus_message_new_method_call(DHCPCD_SERVICE, DHCPCD_PATH,
            DHCPCD_SERVICE, cmd);
        if (msg == NULL) {
@@ -362,13 +369,12 @@ dhcpcd_dispatch(int fd)
 {
        DHCPCD_WATCH *w;
        struct pollfd fds;
-       int n, flags;
+       unsigned int flags;
 
+       flags = 0;
        fds.fd = fd;
        fds.events = (POLLIN | POLLHUP | POLLOUT | POLLERR);
-       n = poll(&fds, 1, 0);
-       flags = 0;
-       if (n == 1) {
+       if (poll(&fds, 1, 0) == 1) {
                if (fds.revents & POLLIN)
                        flags |= DBUS_WATCH_READABLE;
                if (fds.revents & POLLOUT)
@@ -394,24 +400,23 @@ dhcpcd_dispatch(int fd)
 DHCPCD_IF *
 dhcpcd_if_new(DHCPCD_CONNECTION *con, DBusMessageIter *array, char **order)
 {
-       DBusMessageIter dict, entry, var;
+       DBusMessageIter dict, entry, var, a;
        DHCPCD_IF *i;
-       char *s;
+       char *s, *p;
        uint32_t u32;
-       bool b;
-       int errors;
+       int b, errors;
+       size_t l;
 
        if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) {
                errno = EINVAL;
                return NULL;
        }
        dbus_message_iter_recurse(array, &dict);
-       i = malloc(sizeof(*i));
+       i = calloc(1, sizeof(*i));
        if (i == NULL) {
                dhcpcd_error_set(con, 0, errno);
                return NULL;
        }
-       memset(i, 0, sizeof(*i));
        errors = con->errors;
        for (;
             dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY;
@@ -427,14 +432,28 @@ dhcpcd_if_new(DHCPCD_CONNECTION *con, DBusMessageIter *array, char **order)
                        if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_STRING, &s))
                                break;
                        strlcpy(i->ifname, s, sizeof(i->ifname));
+               } else if (strcmp(s, "Type") == 0) {
+                       if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_STRING, &s))
+                               break;
+                       strlcpy(i->type, s, sizeof(i->type));
                } else if (strcmp(s, "Flags") == 0) {
                        if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_UINT32, &u32))
                                break;
                        i->flags = u32;
+               } else if (strcmp(s, "Up") == 0) {
+                       /* b is an int as DBus booleans want more space than
+                        * a C99 boolean */
+                       if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_BOOLEAN, &b))
+                               break;
+                       i->up = b;
                } else if (strcmp(s, "Reason") == 0) {
                        if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_STRING, &s))
                                break;
+
                        strlcpy(i->reason, s, sizeof(i->reason));
+                       l = strlen(i->reason);
+                       if (l != 0 && i->reason[l - 1] == '6')
+                               i->reason[l - 1] = '\0';
                } else if (strcmp(s, "Wireless") == 0) {
                        if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_BOOLEAN, &b))
                                break;
@@ -446,10 +465,47 @@ dhcpcd_if_new(DHCPCD_CONNECTION *con, DBusMessageIter *array, char **order)
                } else if (strcmp(s, "IPAddress") == 0) {
                        if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_UINT32, &u32))
                                break;
-                               i->ip.s_addr = u32;
+                       i->ip.s_addr = u32;
                } else if (strcmp(s, "SubnetCIDR") == 0)
                        dbus_message_iter_get_basic(&var, &i->cidr);
-               else if (order != NULL && strcmp(s, "InterfaceOrder") == 0)
+               else if (strcmp(s, "RA_Prefix") == 0) {
+                       /* Don't crash with older dhcpcd versions */
+                       if (dbus_message_iter_get_arg_type(&dict) ==
+                           DBUS_TYPE_STRING)
+                       {
+                               if (!dhcpcd_iter_get(con, &a,
+                                   DBUS_TYPE_STRING, &s))
+                                       break;
+                               inet_pton(AF_INET6, s, &i->prefix.s6_addr);
+                               continue;
+                       }
+
+                       if (dbus_message_iter_get_arg_type(&dict) !=
+                           DBUS_TYPE_DICT_ENTRY)
+                               break;
+                       dbus_message_iter_recurse(&var, &a);
+                       if (!dhcpcd_iter_get(con, &a, DBUS_TYPE_STRING, &s))
+                               break;
+                       /* Future versions may include pltime and vltime */
+                       p = strchr(s, ',');
+                       if (p)
+                               *p = '\0';
+                       p = strchr(s, '/');
+                       if (p) {
+                               *p++ = '\0';
+                               i->prefix_len = atoi(p);
+                       } else
+                               i->prefix_len = 0;
+                       inet_pton(AF_INET6, s, &i->prefix.s6_addr);
+               } else if (strcmp(s, "RA_PrefixLen") == 0) {
+                       if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_BYTE, &b))
+                               break;
+                       i->prefix_len = b;
+               } else if (strcmp(s, "D6_IPAddress") == 0) {
+                       if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_STRING, &s))
+                               break;
+                       inet_pton(AF_INET6, s, &i->ip6.s6_addr);
+               } else if (order != NULL && strcmp(s, "InterfaceOrder") == 0)
                        if (!dhcpcd_iter_get(con, &var, DBUS_TYPE_STRING, order))
                                break;
        }
@@ -470,7 +526,8 @@ dhcpcd_interfaces(DHCPCD_CONNECTION *con)
        DBusMessageIter args, dict, entry;
        DHCPCD_IF *i, *l;
        int errors;
-       
+       char *stopif;
+
        if (con->interfaces != NULL)
                return con->interfaces;
        l = NULL;
@@ -488,15 +545,24 @@ dhcpcd_interfaces(DHCPCD_CONNECTION *con)
        l = NULL;
        errors = con->errors;
        dbus_message_iter_recurse(&args, &dict);
+       stopif = NULL;
        for (;
             dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY;
-            dbus_message_iter_next(&dict))    
+            dbus_message_iter_next(&dict))
        {
                dbus_message_iter_recurse(&dict, &entry);
                dbus_message_iter_next(&entry);
                i = dhcpcd_if_new(con, &entry, NULL);
                if (i == NULL)
                        break;
+               if (stopif && strcmp(stopif, i->ifname) == 0) {
+                       free(i);
+                       continue;
+               }
+               if (strcmp(i->reason, "NOCARRIER") == 0 ||
+                   strcmp(i->reason, "DEPARTED") == 0 ||
+                   strcmp(i->reason, "STOPPED") == 0)
+                       stopif = i->ifname;
                if (l == NULL)
                        con->interfaces = i;
                else
@@ -514,14 +580,15 @@ dhcpcd_interfaces(DHCPCD_CONNECTION *con)
 }
 
 DHCPCD_IF *
-dhcpcd_if_find(DHCPCD_CONNECTION *con, const char *ifname)
+dhcpcd_if_find(DHCPCD_CONNECTION *con, const char *ifname, const char *type)
 {
        DHCPCD_IF *i;
 
        if (con->interfaces == NULL)
                dhcpcd_interfaces(con);
        for (i = con->interfaces; i; i = i ->next)
-               if (strcmp(i->ifname, ifname) == 0)
+               if (strcmp(i->ifname, ifname) == 0 &&
+                   strcmp(i->type, type) == 0)
                        return i;
        return NULL;
 }
@@ -541,7 +608,7 @@ dhcpcd_set_watch_functions(DHCPCD_CONNECTION *con,
     void *data)
 {
        DHCPCD_WATCH *w;
-       
+
        con->add_watch = add_watch;
        con->delete_watch = delete_watch;
        con->watch_data = data;
@@ -560,7 +627,7 @@ dhcpcd_set_signal_functions(DHCPCD_CONNECTION *con,
     void *data)
 {
        DHCPCD_IF *i;
-       
+
        con->event = event;
        con->status_changed = status_changed;
        con->wi_scanresults = wi_scanresults;
@@ -572,7 +639,7 @@ dhcpcd_set_signal_functions(DHCPCD_CONNECTION *con,
        }
        if (con->wi_scanresults) {
                for (i = dhcpcd_interfaces(con); i; i = i->next)
-                       if (i->wireless)
+                       if (i->wireless && strcmp(i->type, "link") == 0)
                                con->wi_scanresults(con, i, data);
        }
 }