diff --git a/man/NetworkManager.conf.xml.in b/man/NetworkManager.conf.xml.in index 7807b1bf9..054f84202 100644 --- a/man/NetworkManager.conf.xml.in +++ b/man/NetworkManager.conf.xml.in @@ -401,7 +401,7 @@ unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4;interface-name:eth WIFI_SCAN : Wi-Fi scanning operations IP4 : IPv4-related operations IP6 : IPv6-related operations - AUTOIP4 : AutoIP (avahi) operations + AUTOIP4 : AutoIP operations DNS : Domain Name System related operations VPN : Virtual Private Network connections and operations SHARING : Connection sharing diff --git a/src/Makefile.am b/src/Makefile.am index 0008351de..caf688083 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -81,6 +81,10 @@ libsystemd_nm_la_SOURCES = \ systemd/src/libsystemd-network/dhcp6-protocol.h \ systemd/src/libsystemd-network/dhcp-lease-internal.h \ systemd/src/libsystemd-network/sd-dhcp6-client.c \ + systemd/src/libsystemd-network/ipv4ll-internal.h \ + systemd/src/libsystemd-network/sd-ipv4ll.c \ + systemd/src/libsystemd-network/ipv4ll-packet.c \ + systemd/src/libsystemd-network/ipv4ll-network.c \ systemd/src/shared/async.h \ systemd/src/shared/time-util.h \ systemd/src/shared/siphash24.h \ @@ -112,6 +116,7 @@ libsystemd_nm_la_SOURCES = \ systemd/src/systemd/sd-dhcp6-client.h \ systemd/src/systemd/sd-event.h \ systemd/src/systemd/_sd-common.h \ + systemd/src/systemd/sd-ipv4ll.h \ systemd/nm-sd-adapt.h \ systemd/nm-sd-adapt.c diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 714504459..f764f013d 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -68,6 +68,7 @@ #include "nm-core-internal.h" #include "nm-default-route-manager.h" #include "nm-route-manager.h" +#include "sd-ipv4ll.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF (NMDevice); @@ -280,9 +281,8 @@ typedef struct { NMFirewallPendingCall fw_call; /* IPv4LL stuff */ - GPid ipv4ll_pid; - guint ipv4ll_watch; - guint ipv4ll_timeout; + sd_ipv4ll * ipv4ll; + guint ipv4ll_timeout; /* IP6 configuration info */ NMIP6Config * ip6_config; @@ -2750,14 +2750,10 @@ ipv4ll_cleanup (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->ipv4ll_watch) { - g_source_remove (priv->ipv4ll_watch); - priv->ipv4ll_watch = 0; - } - - if (priv->ipv4ll_pid > 0) { - nm_utils_kill_child_sync (priv->ipv4ll_pid, SIGKILL, LOGD_AUTOIP4, "avahi-autoipd", NULL, 0, 0); - priv->ipv4ll_pid = -1; + if (priv->ipv4ll) { + sd_ipv4ll_set_callback (priv->ipv4ll, NULL, NULL); + sd_ipv4ll_stop (priv->ipv4ll); + priv->ipv4ll = sd_ipv4ll_unref (priv->ipv4ll); } ipv4ll_timeout_remove (self); @@ -2793,16 +2789,16 @@ ipv4ll_get_ip4_config (NMDevice *self, guint32 lla) #define IPV4LL_NETWORK (htonl (0xA9FE0000L)) #define IPV4LL_NETMASK (htonl (0xFFFF0000L)) -void -nm_device_handle_ipv4ll_event (NMDevice *self, - const char *event, - const char *address) +static void +nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) { + NMDevice *self = data; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection = NULL; const char *method; - - g_return_if_fail (event != NULL); + struct in_addr address; + NMIP4Config *config; + int r; if (priv->act_request == NULL) return; @@ -2815,25 +2811,24 @@ nm_device_handle_ipv4ll_event (NMDevice *self, if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) != 0) return; - if (strcmp (event, "BIND") == 0) { - guint32 lla; - NMIP4Config *config; - - if (inet_pton (AF_INET, address, &lla) <= 0) { - _LOGE (LOGD_AUTOIP4, "invalid address %s received from avahi-autoipd.", address); + switch (event) { + case IPV4LL_EVENT_BIND: + r = sd_ipv4ll_get_address (ll, &address); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "invalid IPv4 link-local address received, error %d.", r); priv->ip4_state = IP_FAIL; nm_device_check_ip_failed (self, FALSE); return; } - if ((lla & IPV4LL_NETMASK) != IPV4LL_NETWORK) { - _LOGE (LOGD_AUTOIP4, "invalid address %s received from avahi-autoipd (not link-local).", address); + if ((address.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) { + _LOGE (LOGD_AUTOIP4, "invalid address %08x received (not link-local).", address.s_addr); priv->ip4_state = IP_FAIL; nm_device_check_ip_failed (self, FALSE); return; } - config = ipv4ll_get_ip4_config (self, lla); + config = ipv4ll_get_ip4_config (self, address.s_addr); if (config == NULL) { _LOGE (LOGD_AUTOIP4, "failed to get IPv4LL config"); priv->ip4_state = IP_FAIL; @@ -2854,40 +2849,14 @@ nm_device_handle_ipv4ll_event (NMDevice *self, g_assert_not_reached (); g_object_unref (config); - } else { - _LOGW (LOGD_AUTOIP4, "IPv4LL address %s no longer valid because '%s'.", address, event); + break; + default: + _LOGW (LOGD_AUTOIP4, "IPv4LL address no longer valid after event %d.", event); priv->ip4_state = IP_FAIL; nm_device_check_ip_failed (self, FALSE); } } -static void -ipv4ll_watch_cb (GPid pid, gint status, gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMDeviceState state; - - if (!priv->ipv4ll_watch) - return; - priv->ipv4ll_watch = 0; - - if (WIFEXITED (status)) - _LOGD (LOGD_AUTOIP4, "avahi-autoipd exited with error code %d", WEXITSTATUS (status)); - else if (WIFSTOPPED (status)) - _LOGW (LOGD_AUTOIP4, "avahi-autoipd stopped unexpectedly with signal %d", WSTOPSIG (status)); - else if (WIFSIGNALED (status)) - _LOGW (LOGD_AUTOIP4, "avahi-autoipd died with signal %d", WTERMSIG (status)); - else - _LOGW (LOGD_AUTOIP4, "avahi-autoipd died from an unknown cause"); - - ipv4ll_cleanup (self); - - state = nm_device_get_state (self); - if (nm_device_is_activating (self) || (state == NM_DEVICE_STATE_ACTIVATED)) - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); -} - static gboolean ipv4ll_timeout_cb (gpointer user_data) { @@ -2895,7 +2864,7 @@ ipv4ll_timeout_cb (gpointer user_data) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); if (priv->ipv4ll_timeout) { - _LOGI (LOGD_AUTOIP4, "avahi-autoipd timed out."); + _LOGI (LOGD_AUTOIP4, "IPv4LL configuration timed out."); priv->ipv4ll_timeout = 0; ipv4ll_cleanup (self); @@ -2906,66 +2875,69 @@ ipv4ll_timeout_cb (gpointer user_data) return FALSE; } -/* default to installed helper, but can be modified for testing */ -const char *nm_device_autoipd_helper_path = LIBEXECDIR "/nm-avahi-autoipd.action"; - static NMActStageReturn ipv4ll_start (NMDevice *self, NMDeviceStateReason *reason) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const char *argv[6]; - char *cmdline; - const char *aipd_binary; - int i = 0; - GError *error = NULL; + const struct ether_addr *addr; + int ifindex, r; + size_t addr_len; ipv4ll_cleanup (self); - /* Find avahi-autoipd */ - aipd_binary = nm_utils_find_helper ("avahi-autoipd", NULL, NULL); - if (!aipd_binary) { - _LOGW (LOGD_DEVICE | LOGD_AUTOIP4, - "Activation: Stage 3 of 5 (IP Configure Start) failed" - " to start avahi-autoipd: not found"); - *reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; + r = sd_ipv4ll_new (&priv->ipv4ll); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: new() failed with error %d", r); + goto fail; } - argv[i++] = aipd_binary; - argv[i++] = "--script"; - argv[i++] = nm_device_autoipd_helper_path; - - if (nm_logging_enabled (LOGL_DEBUG, LOGD_AUTOIP4)) - argv[i++] = "--debug"; - argv[i++] = nm_device_get_ip_iface (self); - argv[i++] = NULL; - - cmdline = g_strjoinv (" ", (char **) argv); - _LOGD (LOGD_AUTOIP4, "running: %s", cmdline); - g_free (cmdline); - - if (!g_spawn_async ("/", (char **) argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, - nm_utils_setpgid, NULL, &(priv->ipv4ll_pid), &error)) { - _LOGW (LOGD_DEVICE | LOGD_AUTOIP4, - "Activation: Stage 3 of 5 (IP Configure Start) failed" - " to start avahi-autoipd: %s", - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - ipv4ll_cleanup (self); - return NM_ACT_STAGE_RETURN_FAILURE; + r = sd_ipv4ll_attach_event (priv->ipv4ll, NULL, 0); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: attach_event() failed with error %d", r); + goto fail; } - _LOGD (LOGD_DEVICE | LOGD_AUTOIP4, - "Activation: Stage 3 of 5 (IP Configure Start) started" - " avahi-autoipd..."); + ifindex = nm_device_get_ip_ifindex (self); + addr = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &addr_len); + if (!addr || addr_len != ETH_ALEN) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: can't retrieve hardware address"); + goto fail; + } - /* Monitor the child process so we know when it dies */ - priv->ipv4ll_watch = g_child_watch_add (priv->ipv4ll_pid, ipv4ll_watch_cb, self); + r = sd_ipv4ll_set_mac (priv->ipv4ll, addr); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: set_mac() failed with error %d", r); + goto fail; + } + + r = sd_ipv4ll_set_index (priv->ipv4ll, ifindex); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: set_index() failed with error %d", r); + goto fail; + } + + r = sd_ipv4ll_set_callback (priv->ipv4ll, nm_device_handle_ipv4ll_event, self); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: set_callback() failed with error %d", r); + goto fail; + } + + r = sd_ipv4ll_start (priv->ipv4ll); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: start() failed with error %d", r); + goto fail; + } + + _LOGI (LOGD_DEVICE | LOGD_AUTOIP4, + "Activation: Stage 3 of 5 (IP Configure Start) IPv4LL started"); /* Start a timeout to bound the address attempt */ priv->ipv4ll_timeout = g_timeout_add_seconds (20, ipv4ll_timeout_cb, self); return NM_ACT_STAGE_RETURN_POSTPONE; +fail: + *reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; } /*********************************************/ diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 1485b8196..ad79376f4 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -394,10 +394,6 @@ gboolean nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps); gboolean nm_device_get_autoconnect (NMDevice *device); -void nm_device_handle_ipv4ll_event (NMDevice *self, - const char *event, - const char *address); - void nm_device_state_changed (NMDevice *device, NMDeviceState state, NMDeviceStateReason reason); @@ -442,7 +438,4 @@ void nm_device_spawn_iface_helper (NMDevice *self); G_END_DECLS -/* For testing only */ -extern const char* nm_device_autoipd_helper_path; - #endif /* NM_DEVICE_H */ diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c index 86aba4dac..bea89dc98 100644 --- a/src/dhcp-manager/nm-dhcp-dhcpcd.c +++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c @@ -95,7 +95,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last g_ptr_array_add (argv, (gpointer) "-K"); /* Disable built-in carrier detection */ - g_ptr_array_add (argv, (gpointer) "-L"); /* Disable built-in IPv4LL since we use avahi-autoipd */ + g_ptr_array_add (argv, (gpointer) "-L"); /* Disable built-in IPv4LL */ /* --noarp. Don't request or claim the address by ARP; this also disables IPv4LL. */ g_ptr_array_add (argv, (gpointer) "-A"); diff --git a/src/main.c b/src/main.c index a5851dc55..49f0cd1d3 100644 --- a/src/main.c +++ b/src/main.c @@ -323,7 +323,6 @@ main (int argc, char *argv[]) /* don't free these strings, we need them for the entire * process lifetime */ nm_dhcp_helper_path = g_strdup_printf ("%s/src/dhcp-manager/nm-dhcp-helper", path); - nm_device_autoipd_helper_path = g_strdup_printf ("%s/callouts/nm-avahi-autoipd.action", path); g_free (path); } diff --git a/src/nm-manager.c b/src/nm-manager.c index f9ccdb633..4a7c1f9aa 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -59,9 +59,6 @@ #include "nm-core-internal.h" #include "nm-config.h" -#define NM_AUTOIP_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd" -#define NM_AUTOIP_DBUS_IFACE "org.freedesktop.nm_avahi_autoipd" - static gboolean impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err); @@ -183,7 +180,6 @@ typedef struct { NMVpnManager *vpn_manager; - GDBusProxy *aipd_proxy; NMSleepMonitor *sleep_monitor; GSList *auth_chains; @@ -826,40 +822,6 @@ device_removed_cb (NMDevice *device, gpointer user_data) remove_device (NM_MANAGER (user_data), device, FALSE, TRUE); } -static void -aipd_handle_event (GDBusProxy *proxy, - const char *event, - const char *iface, - const char *address, - gpointer user_data) -{ - NMManager *manager = NM_MANAGER (user_data); - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - GSList *iter; - gboolean handled = FALSE; - - if ( (strcmp (event, "BIND") != 0) - && (strcmp (event, "CONFLICT") != 0) - && (strcmp (event, "UNBIND") != 0) - && (strcmp (event, "STOP") != 0)) { - nm_log_warn (LOGD_AUTOIP4, "unknown event '%s' received from avahi-autoipd", event); - return; - } - - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - NMDevice *candidate = NM_DEVICE (iter->data); - - if (!strcmp (nm_device_get_iface (candidate), iface)) { - nm_device_handle_ipv4ll_event (candidate, event, address); - handled = TRUE; - break; - } - } - - if (!handled) - nm_log_warn (LOGD_AUTOIP4, "(%s): unhandled avahi-autoipd event", iface); -} - NMState nm_manager_get_state (NMManager *manager) { @@ -4594,7 +4556,6 @@ nm_manager_init (NMManager *manager) NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); guint i; GFile *file; - GError *error = NULL; /* Initialize rfkill structures and states */ memset (priv->radio_states, 0, sizeof (priv->radio_states)); @@ -4635,23 +4596,6 @@ nm_manager_init (NMManager *manager) priv->vpn_manager = g_object_ref (nm_vpn_manager_get ()); - /* avahi-autoipd stuff */ - priv->aipd_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - NULL, - NM_AUTOIP_DBUS_SERVICE, - "/", - NM_AUTOIP_DBUS_IFACE, - NULL, &error); - if (priv->aipd_proxy) { - _nm_dbus_signal_connect (priv->aipd_proxy, "Event", G_VARIANT_TYPE ("(sss)"), - G_CALLBACK (aipd_handle_event), manager); - } else { - nm_log_warn (LOGD_AUTOIP4, "could not initialize avahi-autoipd D-Bus proxy: %s", - error->message); - g_clear_error (&error); - } - /* sleep/wake handling */ priv->sleep_monitor = g_object_ref (nm_sleep_monitor_get ()); g_signal_connect (priv->sleep_monitor, NM_SLEEP_MONITOR_SLEEPING, @@ -4878,7 +4822,6 @@ dispose (GObject *object) priv->dbus_mgr = NULL; } - g_clear_object (&priv->aipd_proxy); if (priv->sleep_monitor) { g_signal_handlers_disconnect_by_func (priv->sleep_monitor, sleeping_cb, manager); g_signal_handlers_disconnect_by_func (priv->sleep_monitor, resuming_cb, manager);