diff --git a/data/85-nm-unmanaged.rules b/data/85-nm-unmanaged.rules index aefab5c461..f8d95097ff 100644 --- a/data/85-nm-unmanaged.rules +++ b/data/85-nm-unmanaged.rules @@ -6,7 +6,7 @@ SUBSYSTEM!="net", GOTO="nm_unmanaged_end" # Determine ID_NET_DRIVER if there's no ID_NET_DRIVER or DRIVERS (old udev?) ENV{ID_NET_DRIVER}=="?*", GOTO="nm_unmanaged_driver" DRIVERS=="?*", GOTO="nm_unmanaged_driver" -PROGRAM="/bin/sh -c '/usr/sbin/ethtool -i $env{INTERFACE} |/bin/sed -n s/^driver:\ //p'", RESULT=="?*", ENV{ID_NET_DRIVER}="%c" +PROGRAM="/bin/sh -c 'test -e "/sys/class/net/$env{INTERFACE}" && /usr/sbin/ethtool -i "$env{INTERFACE}" | /bin/sed -n s/^driver:\ //p'", RESULT=="?*", ENV{ID_NET_DRIVER}="%c" LABEL="nm_unmanaged_driver" # VirtualBox host networking. Out-of-tree driver that looks like an ordinary diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 80db6817a9..1e11f063c0 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -2681,28 +2681,35 @@ nm_utils_ip4_property_path (const char *ifname, const char *property) return _get_property_path (ifname, property, FALSE); } -const char * -ASSERT_VALID_PATH_COMPONENT (const char *name) +gboolean +nm_utils_is_valid_path_component (const char *name) { const char *n; if (name == NULL || name[0] == '\0') - goto fail; + return FALSE; if (name[0] == '.') { if (name[1] == '\0') - goto fail; + return FALSE; if (name[1] == '.' && name[2] == '\0') - goto fail; + return FALSE; } n = name; do { if (*n == '/') - goto fail; + return FALSE; } while (*(++n) != '\0'); - return name; -fail: + return TRUE; +} + +const char * +ASSERT_VALID_PATH_COMPONENT (const char *name) +{ + if (G_LIKELY (nm_utils_is_valid_path_component (name))) + return name; + nm_log_err (LOGD_CORE, "Failed asserting path component: %s%s%s", NM_PRINT_FMT_QUOTED (name, "\"", name, "\"", "(null)")); g_error ("FATAL: Failed asserting path component: %s%s%s", diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index c0ddba221d..70f62d47e2 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -163,6 +163,7 @@ gint64 nm_utils_get_monotonic_timestamp_ms (void); gint32 nm_utils_get_monotonic_timestamp_s (void); gint64 nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ticks_per_ns); +gboolean nm_utils_is_valid_path_component (const char *name); const char *ASSERT_VALID_PATH_COMPONENT (const char *name); const char *nm_utils_ip6_property_path (const char *ifname, const char *property); const char *nm_utils_ip4_property_path (const char *ifname, const char *property); diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 3f5edd06ee..294456de1b 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -75,6 +75,7 @@ _LOG_DECLARE_SELF (NMDevice); static void impl_device_disconnect (NMDevice *self, DBusGMethodInvocation *context); static void impl_device_delete (NMDevice *self, DBusGMethodInvocation *context); static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data); +static gboolean ip_config_valid (NMDeviceState state); static void nm_device_update_metered (NMDevice *self); #include "nm-device-glue.h" @@ -5940,26 +5941,18 @@ static void _update_ip4_address (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - struct ifreq req; - guint32 new_address; - int fd; + guint32 addr; - g_return_if_fail (self != NULL); + g_return_if_fail (NM_IS_DEVICE (self)); - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - _LOGE (LOGD_IP4, "couldn't open control socket."); - return; + if ( ip_config_valid (priv->state) + && nm_ip4_config_get_num_addresses (priv->ip4_config)) { + addr = nm_ip4_config_get_address (priv->ip4_config, 0)->address; + if (addr != priv->ip4_address) { + priv->ip4_address = addr; + g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_ADDRESS); + } } - - memset (&req, 0, sizeof (struct ifreq)); - strncpy (req.ifr_name, nm_device_get_ip_iface (self), IFNAMSIZ); - if (ioctl (fd, SIOCGIFADDR, &req) == 0) { - new_address = ((struct sockaddr_in *)(&req.ifr_addr))->sin_addr.s_addr; - if (new_address != priv->ip4_address) - priv->ip4_address = new_address; - } - close (fd); } gboolean diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 80757f4ef9..785ac6e274 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -2306,11 +2306,25 @@ event_notification (struct nl_msg *msg, gpointer user_data) if (_support_user_ipv6ll_still_undecided() && msghdr->nlmsg_type == RTM_NEWLINK) _support_user_ipv6ll_detect ((struct rtnl_link *) nlo); - obj = nmp_object_from_nl (platform, nlo, FALSE, TRUE); + switch (msghdr->nlmsg_type) { + case RTM_DELADDR: + case RTM_DELLINK: + case RTM_DELROUTE: + /* The event notifies about a deleted object. We don't need to initialize all the + * fields of the nmp-object. Shortcut nmp_object_from_nl(). */ + obj = nmp_object_from_nl (platform, nlo, TRUE, TRUE); + _LOGD ("event-notification: %s, seq %u: %s", + _nl_nlmsg_type_to_str (msghdr->nlmsg_type, buf_nlmsg_type, sizeof (buf_nlmsg_type)), + msghdr->nlmsg_seq, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0)); + break; + default: + obj = nmp_object_from_nl (platform, nlo, FALSE, TRUE); + _LOGD ("event-notification: %s, seq %u: %s", + _nl_nlmsg_type_to_str (msghdr->nlmsg_type, buf_nlmsg_type, sizeof (buf_nlmsg_type)), + msghdr->nlmsg_seq, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + break; + } - _LOGD ("event-notification: %s, seq %u: %s", - _nl_nlmsg_type_to_str (msghdr->nlmsg_type, buf_nlmsg_type, sizeof (buf_nlmsg_type)), - msghdr->nlmsg_seq, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); if (obj) { auto_nmp_obj NMPObject *obj_cache = NULL; diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index 2d064e1dd3..c6ea6c99b9 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -48,8 +48,11 @@ ethtool_get (const char *name, gpointer edata) if (!name || !*name) return FALSE; - if (strlen (name) >= IFNAMSIZ) - g_return_val_if_reached (FALSE); + if (!nmp_utils_device_exists (name)) + return FALSE; + + /* nmp_utils_device_exists() already errors out if @name is invalid. */ + nm_assert (strlen (name) < IFNAMSIZ); memset (&ifr, 0, sizeof (ifr)); strcpy (ifr.ifr_name, name); @@ -273,6 +276,9 @@ nmp_utils_mii_supports_carrier_detect (const char *ifname) if (!ifname) return FALSE; + if (!nmp_utils_device_exists (ifname)) + return FALSE; + fd = socket (PF_INET, SOCK_DGRAM, 0); if (fd < 0) { nm_log_err (LOGD_PLATFORM, "mii: couldn't open control socket (%s)", ifname); @@ -436,4 +442,17 @@ nmp_utils_lifetime_get (guint32 timestamp, return TRUE; } +gboolean +nmp_utils_device_exists (const char *name) +{ +#define SYS_CLASS_NET "/sys/class/net/" + char sysdir[STRLEN (SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET; + if ( !name + || strlen (name) >= IFNAMSIZ + || !nm_utils_is_valid_path_component (name)) + g_return_val_if_reached (FALSE); + + strcpy (&sysdir[STRLEN (SYS_CLASS_NET)], name); + return g_file_test (sysdir, G_FILE_TEST_EXISTS); +} diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index 557de8440b..ebebb905b8 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -63,4 +63,6 @@ gboolean nmp_utils_lifetime_get (guint32 timestamp, guint32 *out_lifetime, guint32 *out_preferred); +gboolean nmp_utils_device_exists (const char *name); + #endif /* __NM_PLATFORM_UTILS_H__ */ diff --git a/src/platform/wifi/wifi-utils-wext.c b/src/platform/wifi/wifi-utils-wext.c index 8428010ace..470b73d1c2 100644 --- a/src/platform/wifi/wifi-utils-wext.c +++ b/src/platform/wifi/wifi-utils-wext.c @@ -34,6 +34,7 @@ #include "wifi-utils-wext.h" #include "nm-logging.h" #include "nm-utils.h" +#include "nm-platform-utils.h" /* Hacks necessary to #include wireless.h; yay for WEXT */ #ifndef __user @@ -670,6 +671,9 @@ wifi_wext_is_wifi (const char *iface) struct iwreq iwr; gboolean is_wifi = FALSE; + if (!nmp_utils_device_exists (iface)) + return FALSE; + fd = socket (PF_INET, SOCK_DGRAM, 0); if (fd >= 0) { strncpy (iwr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);