diff options
-rw-r--r-- | isys/iface.c | 96 | ||||
-rw-r--r-- | isys/iface.h | 4 | ||||
-rw-r--r-- | loader/net.c | 19 |
3 files changed, 106 insertions, 13 deletions
diff --git a/isys/iface.c b/isys/iface.c index 7a995c42c..9bc55821e 100644 --- a/isys/iface.c +++ b/isys/iface.c @@ -444,13 +444,101 @@ int iface_have_in6_addr(struct in6_addr *addr6) { return _iface_have_valid_addr(addr6, AF_INET6, INET6_ADDRSTRLEN); } +/* Check if NM is already running */ +int is_nm_running(DBusConnection *connection, int *running, char **error_str) +{ + DBusError error; + DBusMessage *message, *reply; + const char *nm_service = NM_DBUS_SERVICE; + dbus_bool_t alive = FALSE; + + message = dbus_message_new_method_call("org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "NameHasOwner"); + if (!message) + return 33; + + if (!dbus_message_append_args(message, + DBUS_TYPE_STRING, &nm_service, + DBUS_TYPE_INVALID)) { + dbus_message_unref(message); + return 34; + } + + dbus_error_init(&error); + reply = dbus_connection_send_with_reply_and_block(connection, + message, 2000, + &error); + if (!reply) { + if (dbus_error_is_set(&error)) { + *error_str = strdup(error.message); + dbus_error_free(&error); + } + + dbus_message_unref(message); + return 35; + } + + dbus_error_init(&error); + if (!dbus_message_get_args(reply, &error, + DBUS_TYPE_BOOLEAN, &alive, + DBUS_TYPE_INVALID)) { + if (dbus_error_is_set(&error)) { + *error_str = strdup(error.message); + dbus_error_free(&error); + } + + dbus_message_unref(message); + dbus_message_unref(reply); + return 36; + } + + *running = alive; + + dbus_message_unref(message); + dbus_message_unref(reply); + return 0; +} + +/* + * Wait for NetworkManager to appear on the system bus + */ +int wait_for_nm(DBusConnection *connection, char **error_str) { + int count = 0; + + /* send message and block until a reply or error comes back */ + while (count < 45) { + int running = 0, ret; + + ret = is_nm_running(connection, &running, error_str); + if (ret != 0) + return ret; /* error */ + if (running) + return 0; /* nm is alive */ + + sleep(1); + count++; + } + + return 37; +} + /* * Start NetworkManager -- requires that you have already written out the * control files in /etc/sysconfig for the interface. */ -int iface_start_NetworkManager(void) { - int status; +int iface_start_NetworkManager(DBusConnection *connection, char **error) { pid_t pid; + int ret, running = 0; + char *ignore = NULL; + + ret = is_nm_running(connection, &running, &ignore); + if (ignore) + free(ignore); + + if (ret == 0 && running) + return 0; /* already running */ /* Start NetworkManager */ pid = fork(); @@ -473,9 +561,7 @@ int iface_start_NetworkManager(void) { } else if (pid == -1) { return 1; } else { - if (waitpid(pid, &status, 0) == -1) { - return 2; - } + return wait_for_nm(connection, error); } return 0; diff --git a/isys/iface.h b/isys/iface.h index 8dcb1900a..8785db2b3 100644 --- a/isys/iface.h +++ b/isys/iface.h @@ -27,6 +27,8 @@ #include <netlink/cache.h> #include <netlink/socket.h> +#include <dbus/dbus.h> + /* Enumerated types used in iface.c as well as loader's network code */ enum { IPUNUSED, IPV4, IPV6 }; @@ -154,7 +156,7 @@ int iface_have_in6_addr(struct in6_addr *addr6); /* * Start NetworkManager */ -int iface_start_NetworkManager(void); +int iface_start_NetworkManager(DBusConnection *connection, char **error); /* * Set Maximum Transfer Unit (MTU) on specified interface diff --git a/loader/net.c b/loader/net.c index 0eb0fe2f7..3dd7fe9c9 100644 --- a/loader/net.c +++ b/loader/net.c @@ -1730,6 +1730,8 @@ int get_connection(iface_t *iface) { dbus_uint32_t state = 0; char *nm_iface = "org.freedesktop.NetworkManager"; char *property = "State"; + int ret; + char *error_str = NULL; if (iface == NULL) { return 1; @@ -1745,13 +1747,6 @@ int get_connection(iface_t *iface) { iface->device, 0); } - /* start NetworkManager for configured interface */ - logMessage(INFO, "starting NetworkManager (%d) for %s", __LINE__, - iface->device); - if (iface_start_NetworkManager() > 0) { - return 2; - } - dbus_error_init(&error); connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); if (connection == NULL) { @@ -1761,6 +1756,16 @@ int get_connection(iface_t *iface) { dbus_error_free(&error); } + return 2; + } + + /* start NetworkManager for configured interface */ + logMessage(INFO, "starting NetworkManager (%d) for %s", __LINE__, + iface->device); + ret = iface_start_NetworkManager(connection, &error_str); + if (ret != 0) { + logMessage(INFO, "failed to start NetworkManager (%d) for %s: error %d (%s)", + __LINE__, iface->device, ret, error_str ? error_str : "unknown"); return 3; } |