summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--isys/iface.c96
-rw-r--r--isys/iface.h4
-rw-r--r--loader/net.c19
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;
}