diff options
Diffstat (limited to 'src/platform')
24 files changed, 1017 insertions, 525 deletions
diff --git a/src/platform/Makefile.in b/src/platform/Makefile.in index 9358879f3..d4c8ade7f 100644 --- a/src/platform/Makefile.in +++ b/src/platform/Makefile.in @@ -189,6 +189,8 @@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@ +BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ @@ -312,6 +314,7 @@ NEWT_CFLAGS = @NEWT_CFLAGS@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ +NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -331,6 +334,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ @@ -357,7 +361,7 @@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ -UDEV_BASE_DIR = @UDEV_BASE_DIR@ +UDEV_DIR = @UDEV_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 46272217d..a5eb7d4ed 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -18,11 +18,14 @@ * Copyright (C) 2012–2013 Red Hat, Inc. */ +#include "config.h" + #include <errno.h> #include <unistd.h> #include <netinet/icmp6.h> #include <netinet/in.h> +#include "gsystem-local-alloc.h" #include "NetworkManagerUtils.h" #include "nm-fake-platform.h" #include "nm-logging.h" @@ -162,12 +165,12 @@ link_get_all (NMPlatform *platform) } static gboolean -_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *link) +_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *l) { NMFakePlatformLink *device = link_get (platform, ifindex); if (device) - *link = device->link; + *l = device->link; return !!device; } @@ -543,7 +546,7 @@ link_get_master (NMPlatform *platform, int slave) static gboolean master_set_option (NMPlatform *platform, int master, const char *option, const char *value) { - auto_g_free char *path = g_strdup_printf ("master:%d:%s", master, option); + gs_free char *path = g_strdup_printf ("master:%d:%s", master, option); return sysctl_set (platform, path, value); } @@ -551,7 +554,7 @@ master_set_option (NMPlatform *platform, int master, const char *option, const c static char * master_get_option (NMPlatform *platform, int master, const char *option) { - auto_g_free char *path = g_strdup_printf ("master:%d:%s", master, option); + gs_free char *path = g_strdup_printf ("master:%d:%s", master, option); return sysctl_get (platform, path); } @@ -559,7 +562,7 @@ master_get_option (NMPlatform *platform, int master, const char *option) static gboolean slave_set_option (NMPlatform *platform, int slave, const char *option, const char *value) { - auto_g_free char *path = g_strdup_printf ("slave:%d:%s", slave, option); + gs_free char *path = g_strdup_printf ("slave:%d:%s", slave, option); return sysctl_set (platform, path, value); } @@ -567,7 +570,7 @@ slave_set_option (NMPlatform *platform, int slave, const char *option, const cha static char * slave_get_option (NMPlatform *platform, int slave, const char *option) { - auto_g_free char *path = g_strdup_printf ("slave:%d:%s", slave, option); + gs_free char *path = g_strdup_printf ("slave:%d:%s", slave, option); return sysctl_get (platform, path); } @@ -688,7 +691,7 @@ wifi_get_capabilities (NMPlatform *platform, int ifindex, NMDeviceWifiCapabiliti } static gboolean -wifi_get_bssid (NMPlatform *platform, int ifindex, struct ether_addr *bssid) +wifi_get_bssid (NMPlatform *platform, int ifindex, guint8 *bssid) { return FALSE; } @@ -754,7 +757,7 @@ mesh_set_channel (NMPlatform *platform, int ifindex, guint32 channel) } static gboolean -mesh_set_ssid (NMPlatform *platform, int ifindex, const GByteArray *ssid) +mesh_set_ssid (NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len) { return FALSE; } @@ -827,7 +830,7 @@ ip4_address_add (NMPlatform *platform, int ifindex, int i; memset (&address, 0, sizeof (address)); - address.source = NM_PLATFORM_SOURCE_KERNEL; + address.source = NM_IP_CONFIG_SOURCE_KERNEL; address.ifindex = ifindex; address.address = addr; address.peer_address = peer_addr; @@ -869,7 +872,7 @@ ip6_address_add (NMPlatform *platform, int ifindex, int i; memset (&address, 0, sizeof (address)); - address.source = NM_PLATFORM_SOURCE_KERNEL; + address.source = NM_IP_CONFIG_SOURCE_KERNEL; address.ifindex = ifindex; address.address = addr; address.peer_address = peer_addr; @@ -901,7 +904,7 @@ ip6_address_add (NMPlatform *platform, int ifindex, } static gboolean -ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) +ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); int i; @@ -909,7 +912,8 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) for (i = 0; i < priv->ip4_addresses->len; i++) { NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i); - if (address->ifindex == ifindex && address->plen == plen && address->address == addr) { + if (address->ifindex == ifindex && address->plen == plen && address->address == addr && + (!peer_address || address->peer_address == peer_address)) { NMPlatformIP4Address deleted_address; memcpy (&deleted_address, address, sizeof (deleted_address)); @@ -978,31 +982,37 @@ ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int return FALSE; } +static gboolean +ip4_check_reinstall_device_route (NMPlatform *platform, int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric) +{ + return FALSE; +} + /******************************************************************/ static GArray * -ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default) +ip4_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mode) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); GArray *routes; NMPlatformIP4Route *route; - int count = 0, i; + guint i; - /* Count routes */ - for (i = 0; i < priv->ip4_routes->len; i++) { - route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i); - if (route && route->ifindex == ifindex) - count++; - } + g_return_val_if_fail (NM_IN_SET (mode, NM_PLATFORM_GET_ROUTE_MODE_ALL, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT), NULL); - routes = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP4Route), count); + routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP4Route)); /* Fill routes */ for (i = 0; i < priv->ip4_routes->len; i++) { route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i); - if (route && route->ifindex == ifindex) { - if (route->plen != 0 || include_default) - g_array_append_val (routes, *route); + if (route && (!ifindex || route->ifindex == ifindex)) { + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) { + if (mode != NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT) + g_array_append_val (routes, *route); + } else { + if (mode != NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT) + g_array_append_val (routes, *route); + } } } @@ -1010,28 +1020,28 @@ ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default) } static GArray * -ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default) +ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mode) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); GArray *routes; NMPlatformIP6Route *route; - int count = 0, i; + guint i; - /* Count routes */ - for (i = 0; i < priv->ip6_routes->len; i++) { - route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i); - if (route && route->ifindex == ifindex) - count++; - } + g_return_val_if_fail (NM_IN_SET (mode, NM_PLATFORM_GET_ROUTE_MODE_ALL, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT), NULL); - routes = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP6Route), count); + routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP6Route)); /* Fill routes */ for (i = 0; i < priv->ip6_routes->len; i++) { route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i); - if (route && route->ifindex == ifindex) { - if (route->plen != 0 || include_default) - g_array_append_val (routes, *route); + if (route && (!ifindex || route->ifindex == ifindex)) { + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) { + if (mode != NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT) + g_array_append_val (routes, *route); + } else { + if (mode != NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT) + g_array_append_val (routes, *route); + } } } @@ -1039,16 +1049,16 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default) } static gboolean -ip4_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source, +ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source, in_addr_t network, int plen, in_addr_t gateway, - int metric, int mss) + guint32 pref_src, guint32 metric, guint32 mss) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); NMPlatformIP4Route route; guint i; memset (&route, 0, sizeof (route)); - route.source = NM_PLATFORM_SOURCE_KERNEL; + route.source = NM_IP_CONFIG_SOURCE_KERNEL; route.ifindex = ifindex; route.source = source; route.network = network; @@ -1079,16 +1089,16 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source, } static gboolean -ip6_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source, +ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source, struct in6_addr network, int plen, struct in6_addr gateway, - int metric, int mss) + guint32 metric, guint32 mss) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); NMPlatformIP6Route route; guint i; memset (&route, 0, sizeof (route)); - route.source = NM_PLATFORM_SOURCE_KERNEL; + route.source = NM_IP_CONFIG_SOURCE_KERNEL; route.ifindex = ifindex; route.source = source; route.network = network; @@ -1119,7 +1129,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source, } static NMPlatformIP4Route * -ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric) +ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); int i; @@ -1138,7 +1148,7 @@ ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, i } static NMPlatformIP6Route * -ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric) +ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); int i; @@ -1157,7 +1167,7 @@ ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int p } static gboolean -ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric) +ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) { NMPlatformIP4Route *route = ip4_route_get (platform, ifindex, network, plen, metric); NMPlatformIP4Route deleted_route; @@ -1172,7 +1182,7 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen } static gboolean -ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric) +ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) { NMPlatformIP6Route *route = ip6_route_get (platform, ifindex, network, plen, metric); NMPlatformIP6Route deleted_route; @@ -1187,13 +1197,13 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in } static gboolean -ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric) +ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) { return !!ip4_route_get (platform, ifindex, network, plen, metric); } static gboolean -ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric) +ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) { return !!ip6_route_get (platform, ifindex, network, plen, metric); } @@ -1341,6 +1351,8 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass) platform_class->ip4_address_exists = ip4_address_exists; platform_class->ip6_address_exists = ip6_address_exists; + platform_class->ip4_check_reinstall_device_route = ip4_check_reinstall_device_route; + platform_class->ip4_route_get_all = ip4_route_get_all; platform_class->ip6_route_get_all = ip6_route_get_all; platform_class->ip4_route_add = ip4_route_add; diff --git a/src/platform/nm-fake-platform.h b/src/platform/nm-fake-platform.h index c9fa42eb6..53a2ff1a6 100644 --- a/src/platform/nm-fake-platform.h +++ b/src/platform/nm-fake-platform.h @@ -18,8 +18,8 @@ * Copyright (C) 2012 Red Hat, Inc. */ -#ifndef NM_FAKE_PLATFORM_H -#define NM_FAKE_PLATFORM_H +#ifndef __NETWORKMANAGER_FAKE_PLATFORM_H__ +#define __NETWORKMANAGER_FAKE_PLATFORM_H__ #include "nm-platform.h" @@ -46,4 +46,4 @@ GType nm_fake_platform_get_type (void); void nm_fake_platform_setup (void); -#endif /* NM_FAKE_PLATFORM_H */ +#endif /* __NETWORKMANAGER_FAKE_PLATFORM_H__ */ diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index f73ff3207..5d1522ce9 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -17,7 +17,7 @@ * * Copyright (C) 2012-2013 Red Hat, Inc. */ -#include <config.h> +#include "config.h" #include <errno.h> #include <unistd.h> @@ -44,6 +44,17 @@ #include <netlink/route/route.h> #include <gudev/gudev.h> +#if HAVE_LIBNL_INET6_ADDR_GEN_MODE +#include <netlink/route/link/inet6.h> +#if HAVE_KERNEL_INET6_ADDR_GEN_MODE +#include <linux/if_link.h> +#else +#define IN6_ADDR_GEN_MODE_EUI64 0 +#define IN6_ADDR_GEN_MODE_NONE 1 +#endif +#endif + +#include "gsystem-local-alloc.h" #include "NetworkManagerUtils.h" #include "nm-linux-platform.h" #include "NetworkManagerUtils.h" @@ -83,6 +94,7 @@ typedef struct { GHashTable *wifi_data; int support_kernel_extended_ifa_flags; + int support_user_ipv6ll; } NMLinuxPlatformPrivate; #define NM_LINUX_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformPrivate)) @@ -90,6 +102,8 @@ typedef struct { G_DEFINE_TYPE (NMLinuxPlatform, nm_linux_platform, NM_TYPE_PLATFORM) static const char *to_string_object (NMPlatform *platform, struct nl_object *obj); +static gboolean _address_match (struct rtnl_addr *addr, int family, int ifindex); +static gboolean _route_match (struct rtnl_route *rtnlroute, int family, int ifindex, gboolean include_proto_kernel); void nm_linux_platform_setup (void) @@ -106,7 +120,7 @@ _nl_f_nl_has_capability (int capability) } static struct libnl_vtable * -_nl_get_vtable () +_nl_get_vtable (void) { static struct libnl_vtable vtable; @@ -268,7 +282,7 @@ _nm_rtnl_addr_alloc (int ifindex) } static struct rtnl_route * -_nm_rtnl_route_alloc () +_nm_rtnl_route_alloc (void) { struct rtnl_route *rtnlroute = rtnl_route_alloc (); @@ -278,7 +292,7 @@ _nm_rtnl_route_alloc () } static struct rtnl_nexthop * -_nm_rtnl_route_nh_alloc () +_nm_rtnl_route_nh_alloc (void) { struct rtnl_nexthop *nexthop; @@ -596,8 +610,8 @@ ethtool_get (const char *name, gpointer edata) static int ethtool_get_stringset_index (const char *ifname, int stringset_id, const char *string) { - auto_g_free struct ethtool_sset_info *info = NULL; - auto_g_free struct ethtool_gstrings *strings = NULL; + gs_free struct ethtool_sset_info *info = NULL; + gs_free struct ethtool_gstrings *strings = NULL; guint32 len, i; info = g_malloc0 (sizeof (*info) + sizeof (guint32)); @@ -667,6 +681,23 @@ check_support_kernel_extended_ifa_flags (NMPlatform *platform) return priv->support_kernel_extended_ifa_flags > 0; } +static gboolean +check_support_user_ipv6ll (NMPlatform *platform) +{ + NMLinuxPlatformPrivate *priv; + + g_return_val_if_fail (NM_IS_LINUX_PLATFORM (platform), FALSE); + + priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + + if (priv->support_user_ipv6ll == 0) { + nm_log_warn (LOGD_PLATFORM, "Unable to detect kernel support for IFLA_INET6_ADDR_GEN_MODE. Assume no kernel support."); + priv->support_user_ipv6ll = -1; + } + + return priv->support_user_ipv6ll > 0; +} + /* Object type specific utilities */ @@ -735,7 +766,7 @@ link_type_from_udev (NMPlatform *platform, int ifindex, const char *ifname, int prop = g_udev_device_get_property (udev_device, "DEVTYPE"); sysfs_path = g_udev_device_get_sysfs_path (udev_device); - if (g_strcmp0 (prop, "wlan") == 0 || wifi_utils_is_wifi (ifname, sysfs_path)) + if (wifi_utils_is_wifi (ifname, sysfs_path, prop)) return_type (NM_LINK_TYPE_WIFI, "wifi"); else if (g_strcmp0 (prop, "wwan") == 0) return_type (NM_LINK_TYPE_WWAN_ETHERNET, "wwan"); @@ -1176,7 +1207,7 @@ init_ip4_address (NMPlatformIP4Address *address, struct rtnl_addr *rtnladdr) memset (address, 0, sizeof (*address)); - address->source = NM_PLATFORM_SOURCE_KERNEL; + address->source = NM_IP_CONFIG_SOURCE_KERNEL; address->ifindex = rtnl_addr_get_ifindex (rtnladdr); address->plen = rtnl_addr_get_prefixlen (rtnladdr); _init_ip_address_lifetime ((NMPlatformIPAddress *) address, rtnladdr); @@ -1208,7 +1239,7 @@ init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr) memset (address, 0, sizeof (*address)); - address->source = NM_PLATFORM_SOURCE_KERNEL; + address->source = NM_IP_CONFIG_SOURCE_KERNEL; address->ifindex = rtnl_addr_get_ifindex (rtnladdr); address->plen = rtnl_addr_get_prefixlen (rtnladdr); _init_ip_address_lifetime ((NMPlatformIPAddress *) address, rtnladdr); @@ -1230,16 +1261,16 @@ init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr) } static guint -source_to_rtprot (NMPlatformSource source) +source_to_rtprot (NMIPConfigSource source) { switch (source) { - case NM_PLATFORM_SOURCE_UNKNOWN: + case NM_IP_CONFIG_SOURCE_UNKNOWN: return RTPROT_UNSPEC; - case NM_PLATFORM_SOURCE_KERNEL: + case NM_IP_CONFIG_SOURCE_KERNEL: return RTPROT_KERNEL; - case NM_PLATFORM_SOURCE_DHCP: + case NM_IP_CONFIG_SOURCE_DHCP: return RTPROT_DHCP; - case NM_PLATFORM_SOURCE_RDISC: + case NM_IP_CONFIG_SOURCE_RDISC: return RTPROT_RA; default: @@ -1247,26 +1278,36 @@ source_to_rtprot (NMPlatformSource source) } } -static NMPlatformSource +static NMIPConfigSource rtprot_to_source (guint rtprot) { switch (rtprot) { case RTPROT_UNSPEC: - return NM_PLATFORM_SOURCE_UNKNOWN; + return NM_IP_CONFIG_SOURCE_UNKNOWN; case RTPROT_REDIRECT: case RTPROT_KERNEL: - return NM_PLATFORM_SOURCE_KERNEL; + return NM_IP_CONFIG_SOURCE_KERNEL; case RTPROT_RA: - return NM_PLATFORM_SOURCE_RDISC; + return NM_IP_CONFIG_SOURCE_RDISC; case RTPROT_DHCP: - return NM_PLATFORM_SOURCE_DHCP; + return NM_IP_CONFIG_SOURCE_DHCP; default: - return NM_PLATFORM_SOURCE_USER; + return NM_IP_CONFIG_SOURCE_USER; } } static gboolean +_rtnl_route_is_default (const struct rtnl_route *rtnlroute) +{ + struct nl_addr *dst; + + return rtnlroute + && (dst = rtnl_route_get_dst ((struct rtnl_route *) rtnlroute)) + && nl_addr_get_prefixlen (dst) == 0; +} + +static gboolean init_ip4_route (NMPlatformIP4Route *route, struct rtnl_route *rtnlroute) { struct nl_addr *dst, *gw; @@ -1527,8 +1568,20 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor switch (object_type) { case OBJECT_TYPE_LINK: { - NMPlatformLink device; struct rtnl_link *rtnl_link = (struct rtnl_link *) object; + NMPlatformLink device; + +#if HAVE_LIBNL_INET6_ADDR_GEN_MODE + /* If we ever see a link with valid IPv6 link-local address + * generation modes, the kernel supports it. + */ + if (priv->support_user_ipv6ll == 0) { + uint8_t mode; + + if (rtnl_link_inet6_get_addr_gen_mode (rtnl_link, &mode) == 0) + priv->support_user_ipv6ll = 1; + } +#endif if (!init_link (platform, &device, rtnl_link)) return; @@ -1576,20 +1629,25 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor { NMPlatformIP4Address address; - if (!init_ip4_address (&address, (struct rtnl_addr *) object)) - return; - /* Address deletion is sometimes accompanied by route deletion. We need to * check all routes belonging to the same interface. */ switch (change_type) { case NM_PLATFORM_SIGNAL_REMOVED: - check_cache_items (platform, priv->route_cache, address.ifindex); + check_cache_items (platform, + priv->route_cache, + rtnl_addr_get_ifindex ((struct rtnl_addr *) object)); break; default: break; } + if (!_address_match ((struct rtnl_addr *) object, AF_INET, 0)) { + nm_log_dbg (LOGD_PLATFORM, "skip announce unmatching IP4 address %s", to_string_ip4_address ((struct rtnl_addr *) object)); + return; + } + if (!init_ip4_address (&address, (struct rtnl_addr *) object)) + return; g_signal_emit_by_name (platform, sig, address.ifindex, &address, change_type, reason); } return; @@ -1597,6 +1655,10 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor { NMPlatformIP6Address address; + if (!_address_match ((struct rtnl_addr *) object, AF_INET6, 0)) { + nm_log_dbg (LOGD_PLATFORM, "skip announce unmatching IP6 address %s", to_string_ip6_address ((struct rtnl_addr *) object)); + return; + } if (!init_ip6_address (&address, (struct rtnl_addr *) object)) return; g_signal_emit_by_name (platform, sig, address.ifindex, &address, change_type, reason); @@ -1606,6 +1668,10 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor { NMPlatformIP4Route route; + if (!_route_match ((struct rtnl_route *) object, AF_INET, 0, FALSE)) { + nm_log_dbg (LOGD_PLATFORM, "skip announce unmatching IP4 route %s", to_string_ip4_route ((struct rtnl_route *) object)); + return; + } if (init_ip4_route (&route, (struct rtnl_route *) object)) g_signal_emit_by_name (platform, sig, route.ifindex, &route, change_type, reason); } @@ -1614,6 +1680,10 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor { NMPlatformIP6Route route; + if (!_route_match ((struct rtnl_route *) object, AF_INET6, 0, FALSE)) { + nm_log_dbg (LOGD_PLATFORM, "skip announce unmatching IP6 route %s", to_string_ip6_route ((struct rtnl_route *) object)); + return; + } if (init_ip6_route (&route, (struct rtnl_route *) object)) g_signal_emit_by_name (platform, sig, route.ifindex, &route, change_type, reason); } @@ -1721,15 +1791,14 @@ add_object (NMPlatform *platform, struct nl_object *obj) /* Decreases the reference count if @obj for convenience */ static gboolean -delete_object (NMPlatform *platform, struct nl_object *obj, gboolean do_refresh_object) +delete_object (NMPlatform *platform, struct nl_object *object, gboolean do_refresh_object) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); - auto_nl_object struct nl_object *obj_cleanup = obj; - struct nl_object *object = obj; int object_type; int nle; + gboolean result = FALSE; - object_type = object_type_from_nl_object (obj); + object_type = object_type_from_nl_object (object); g_return_val_if_fail (object_type != OBJECT_TYPE_UNKNOWN, FALSE); switch (object_type) { @@ -1772,14 +1841,18 @@ delete_object (NMPlatform *platform, struct nl_object *obj, gboolean do_refresh_ goto DEFAULT; DEFAULT: default: - error ("Netlink error deleting %s: %s (%d)", to_string_object (platform, obj), nl_geterror (nle), nle); - return FALSE; + error ("Netlink error deleting %s: %s (%d)", to_string_object (platform, object), nl_geterror (nle), nle); + goto out; } if (do_refresh_object) refresh_object (platform, object, TRUE, NM_PLATFORM_REASON_INTERNAL); - return TRUE; + result = TRUE; + +out: + nl_object_put (object); + return result; } static void @@ -1807,6 +1880,33 @@ _rtnl_addr_timestamps_equal_fuzzy (guint32 ts1, guint32 ts2) return diff <= 2; } +static gboolean +nm_nl_object_diff (ObjectType type, struct nl_object *_a, struct nl_object *_b) +{ + if (nl_object_diff (_a, _b)) { + /* libnl thinks objects are different*/ + return TRUE; + } + + if (type == OBJECT_TYPE_IP4_ADDRESS || type == OBJECT_TYPE_IP6_ADDRESS) { + struct rtnl_addr *a = (struct rtnl_addr *) _a; + struct rtnl_addr *b = (struct rtnl_addr *) _b; + + /* libnl nl_object_diff() ignores differences in timestamp. Let's care about + * them (if they are large enough). + * + * Note that these valid and preferred timestamps are absolute, after + * _rtnl_addr_hack_lifetimes_rel_to_abs(). */ + if ( !_rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_preferred_lifetime (a), + rtnl_addr_get_preferred_lifetime (b)) + || !_rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_valid_lifetime (a), + rtnl_addr_get_valid_lifetime (b))) + return TRUE; + } + + return FALSE; +} + /* This function does all the magic to avoid race conditions caused * by concurrent usage of synchronous commands and an asynchronous cache. This * might be a nice future addition to libnl but it requires to do all operations @@ -1912,24 +2012,9 @@ event_notification (struct nl_msg *msg, gpointer user_data) * This also catches notifications for internal addition or change, unless * another action occured very soon after it. */ - if (!nl_object_diff (kernel_object, cached_object)) { - if (type == OBJECT_TYPE_IP4_ADDRESS || type == OBJECT_TYPE_IP6_ADDRESS) { - struct rtnl_addr *c = (struct rtnl_addr *) cached_object; - struct rtnl_addr *k = (struct rtnl_addr *) kernel_object; - - /* libnl nl_object_diff() ignores differences in timestamp. Let's care about - * them (if they are large enough). - * - * Note that these valid and preferred timestamps are absolute, after - * _rtnl_addr_hack_lifetimes_rel_to_abs(). */ - if ( _rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_preferred_lifetime (c), - rtnl_addr_get_preferred_lifetime (k)) - && _rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_valid_lifetime (c), - rtnl_addr_get_valid_lifetime (k))) - return NL_OK; - } else - return NL_OK; - } + if (!nm_nl_object_diff (type, kernel_object, cached_object)) + return NL_OK; + /* Handle external change */ nl_cache_remove (cached_object); nle = nl_cache_add (cache, kernel_object); @@ -2133,7 +2218,7 @@ link_get_all (NMPlatform *platform) } static gboolean -_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *link) +_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *l) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); auto_nl_object struct rtnl_link *rtnllink = NULL; @@ -2141,7 +2226,7 @@ _nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *link) rtnllink = rtnl_link_get (priv->link_cache, ifindex); if (rtnllink) { if (link_is_announceable (platform, rtnllink)) { - if (init_link (platform, link, rtnllink)) + if (init_link (platform, l, rtnllink)) return TRUE; } } @@ -2166,7 +2251,7 @@ static gboolean link_add (NMPlatform *platform, const char *name, NMLinkType type, const void *address, size_t address_len) { int r; - struct nl_object *link; + struct nl_object *l; if (type == NM_LINK_TYPE_BOND) { /* When the kernel loads the bond module, either via explicit modprobe @@ -2184,15 +2269,15 @@ link_add (NMPlatform *platform, const char *name, NMLinkType type, const void *a debug ("link: add link '%s' of type '%s' (%d)", name, type_to_string (type), (int) type); - link = build_rtnl_link (0, name, type); + l = build_rtnl_link (0, name, type); g_assert ( (address != NULL) ^ (address_len == 0) ); if (address) { auto_nl_addr struct nl_addr *nladdr = _nm_nl_addr_build (AF_LLC, address, address_len); - rtnl_link_set_addr ((struct rtnl_link *) link, nladdr); + rtnl_link_set_addr ((struct rtnl_link *) l, nladdr); } - return add_object (platform, link); + return add_object (platform, l); } static struct rtnl_link * @@ -2384,6 +2469,46 @@ link_set_noarp (NMPlatform *platform, int ifindex) } static gboolean +link_get_user_ipv6ll_enabled (NMPlatform *platform, int ifindex) +{ +#if HAVE_LIBNL_INET6_ADDR_GEN_MODE + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + + if (priv->support_user_ipv6ll > 0) { + auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); + uint8_t mode = 0; + + if (rtnllink) { + if (rtnl_link_inet6_get_addr_gen_mode (rtnllink, &mode) != 0) { + /* Default to "disabled" on error */ + return FALSE; + } + return mode == IN6_ADDR_GEN_MODE_NONE; + } + } +#endif + return FALSE; +} + +static gboolean +link_set_user_ipv6ll_enabled (NMPlatform *platform, int ifindex, gboolean enabled) +{ +#if HAVE_LIBNL_INET6_ADDR_GEN_MODE + if (check_support_user_ipv6ll (platform)) { + auto_nl_object struct rtnl_link *change = _nm_rtnl_link_alloc (ifindex, NULL); + guint8 mode = enabled ? IN6_ADDR_GEN_MODE_NONE : IN6_ADDR_GEN_MODE_EUI64; + char buf[32]; + + rtnl_link_inet6_set_addr_gen_mode (change, mode); + debug ("link: change %d: set IPv6 address generation mode to %s", + ifindex, rtnl_link_inet6_addrgenmode2str (mode, buf, sizeof (buf))); + return link_change (platform, ifindex, change); + } +#endif + return FALSE; +} + +static gboolean supports_ethtool_carrier_detect (const char *ifname) { struct ethtool_cmd edata = { .cmd = ETHTOOL_GLINK }; @@ -2455,7 +2580,7 @@ link_supports_vlans (NMPlatform *platform, int ifindex) { auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); const char *name = nm_platform_link_get_name (ifindex); - auto_g_free struct ethtool_gfeatures *features = NULL; + gs_free struct ethtool_gfeatures *features = NULL; int idx, block, bit, size; /* Only ARPHRD_ETHER links can possibly support VLANs. */ @@ -2494,7 +2619,7 @@ link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size rtnl_link_set_addr (change, nladdr); if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { - char *mac = nm_utils_hwaddr_ntoa_len (address, length); + char *mac = nm_utils_hwaddr_ntoa (address, length); debug ("link: change %d: address %s (%lu bytes)", ifindex, mac, (unsigned long) length); g_free (mac); @@ -2508,13 +2633,23 @@ link_get_address (NMPlatform *platform, int ifindex, size_t *length) { auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex); struct nl_addr *nladdr; - - nladdr = rtnllink ? rtnl_link_get_addr (rtnllink) : NULL; + size_t l = 0; + gconstpointer a = NULL; + + if (rtnllink && + (nladdr = rtnl_link_get_addr (rtnllink))) { + l = nl_addr_get_len (nladdr); + if (l > NM_UTILS_HWADDR_LEN_MAX) { + if (length) + *length = 0; + g_return_val_if_reached (NULL); + } else if (l > 0) + a = nl_addr_get_binary_addr (nladdr); + } if (length) - *length = nladdr ? nl_addr_get_len (nladdr) : 0; - - return nladdr ? nl_addr_get_binary_addr (nladdr) : NULL; + *length = l; + return a; } static gboolean @@ -2667,7 +2802,7 @@ link_option_path (int master, const char *category, const char *option) static gboolean link_set_option (int master, const char *category, const char *option, const char *value) { - auto_g_free char *path = link_option_path (master, category, option); + gs_free char *path = link_option_path (master, category, option); return path && nm_platform_sysctl_set (path, value); } @@ -2675,7 +2810,7 @@ link_set_option (int master, const char *category, const char *option, const cha static char * link_get_option (int master, const char *category, const char *option) { - auto_g_free char *path = link_option_path (master, category, option); + gs_free char *path = link_option_path (master, category, option); return path ? nm_platform_sysctl_get (path) : NULL; } @@ -2754,7 +2889,7 @@ infiniband_partition_add (NMPlatform *platform, int parent, int p_key) g_free (path); if (success) { - auto_g_free char *ifname = g_strdup_printf ("%s.%04x", parent_name, p_key); + gs_free char *ifname = g_strdup_printf ("%s.%04x", parent_name, p_key); auto_nl_object struct rtnl_link *rtnllink = _nm_rtnl_link_alloc (0, ifname); success = refresh_object (platform, (struct nl_object *) rtnllink, FALSE, NM_PLATFORM_REASON_INTERNAL); @@ -2767,7 +2902,7 @@ static gboolean veth_get_properties (NMPlatform *platform, int ifindex, NMPlatformVethProperties *props) { const char *ifname; - auto_g_free struct ethtool_stats *stats = NULL; + gs_free struct ethtool_stats *stats = NULL; int peer_ifindex_stat; ifname = nm_platform_link_get_name (ifindex); @@ -2841,7 +2976,7 @@ tun_get_properties (NMPlatform *platform, int ifindex, NMPlatformTunProperties * #ifndef IFF_MULTI_QUEUE const int IFF_MULTI_QUEUE = 0x0100; #endif - props->mode = ((flags & TUN_TYPE_MASK) == TUN_TUN_DEV) ? "tun" : "tap"; + props->mode = ((flags & (IFF_TUN | IFF_TAP)) == IFF_TUN) ? "tun" : "tap"; props->no_pi = !!(flags & IFF_NO_PI); props->vnet_hdr = !!(flags & IFF_VNET_HDR); props->multi_queue = !!(flags & IFF_MULTI_QUEUE); @@ -2947,6 +3082,13 @@ macvlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformMacvlanProp #undef IFLA_VXLAN_MAX #define IFLA_VXLAN_MAX IFLA_VXLAN_LOCAL6 +/* older kernel header might not contain 'struct ifla_vxlan_port_range'. + * Redefine it. */ +struct nm_ifla_vxlan_port_range { + guint16 low; + guint16 high; +}; + static const struct nla_policy vxlan_info_policy[IFLA_VXLAN_MAX + 1] = { [IFLA_VXLAN_ID] = { .type = NLA_U32 }, [IFLA_VXLAN_GROUP] = { .type = NLA_U32 }, @@ -2962,7 +3104,7 @@ static const struct nla_policy vxlan_info_policy[IFLA_VXLAN_MAX + 1] = { [IFLA_VXLAN_AGEING] = { .type = NLA_U32 }, [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 }, [IFLA_VXLAN_PORT_RANGE] = { .type = NLA_UNSPEC, - .minlen = sizeof (struct ifla_vxlan_port_range) }, + .minlen = sizeof (struct nm_ifla_vxlan_port_range) }, [IFLA_VXLAN_PROXY] = { .type = NLA_U8 }, [IFLA_VXLAN_RSC] = { .type = NLA_U8 }, [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 }, @@ -2975,7 +3117,7 @@ vxlan_info_data_parser (struct nlattr *info_data, gpointer parser_data) { NMPlatformVxlanProperties *props = parser_data; struct nlattr *tb[IFLA_VXLAN_MAX + 1]; - struct ifla_vxlan_port_range *range; + struct nm_ifla_vxlan_port_range *range; int err; err = nla_parse_nested (tb, IFLA_VXLAN_MAX, info_data, @@ -2985,8 +3127,10 @@ vxlan_info_data_parser (struct nlattr *info_data, gpointer parser_data) memset (props, 0, sizeof (*props)); - props->parent_ifindex = tb[IFLA_VXLAN_LINK] ? nla_get_u32 (tb[IFLA_VXLAN_LINK]) : 0; - props->id = nla_get_u32 (tb[IFLA_VXLAN_ID]); + if (tb[IFLA_VXLAN_LINK]) + props->parent_ifindex = nla_get_u32 (tb[IFLA_VXLAN_LINK]); + if (tb[IFLA_VXLAN_ID]) + props->id = nla_get_u32 (tb[IFLA_VXLAN_ID]); if (tb[IFLA_VXLAN_GROUP]) props->group = nla_get_u32 (tb[IFLA_VXLAN_GROUP]); if (tb[IFLA_VXLAN_LOCAL]) @@ -2996,21 +3140,34 @@ vxlan_info_data_parser (struct nlattr *info_data, gpointer parser_data) if (tb[IFLA_VXLAN_LOCAL6]) memcpy (&props->local6, nla_data (tb[IFLA_VXLAN_LOCAL6]), sizeof (props->local6)); - props->ageing = nla_get_u32 (tb[IFLA_VXLAN_AGEING]); - props->limit = nla_get_u32 (tb[IFLA_VXLAN_LIMIT]); - props->tos = nla_get_u8 (tb[IFLA_VXLAN_TOS]); - props->ttl = nla_get_u8 (tb[IFLA_VXLAN_TTL]); - - props->dst_port = nla_get_u16 (tb[IFLA_VXLAN_PORT]); - range = nla_data (tb[IFLA_VXLAN_PORT_RANGE]); - props->src_port_min = range->low; - props->src_port_max = range->high; + if (tb[IFLA_VXLAN_AGEING]) + props->ageing = nla_get_u32 (tb[IFLA_VXLAN_AGEING]); + if (tb[IFLA_VXLAN_LIMIT]) + props->limit = nla_get_u32 (tb[IFLA_VXLAN_LIMIT]); + if (tb[IFLA_VXLAN_TOS]) + props->tos = nla_get_u8 (tb[IFLA_VXLAN_TOS]); + if (tb[IFLA_VXLAN_TTL]) + props->ttl = nla_get_u8 (tb[IFLA_VXLAN_TTL]); + + if (tb[IFLA_VXLAN_PORT]) + props->dst_port = nla_get_u16 (tb[IFLA_VXLAN_PORT]); + + if (tb[IFLA_VXLAN_PORT_RANGE]) { + range = nla_data (tb[IFLA_VXLAN_PORT_RANGE]); + props->src_port_min = range->low; + props->src_port_max = range->high; + } - props->learning = !!nla_get_u8 (tb[IFLA_VXLAN_LEARNING]); - props->proxy = !!nla_get_u8 (tb[IFLA_VXLAN_PROXY]); - props->rsc = !!nla_get_u8 (tb[IFLA_VXLAN_RSC]); - props->l2miss = !!nla_get_u8 (tb[IFLA_VXLAN_L2MISS]); - props->l3miss = !!nla_get_u8 (tb[IFLA_VXLAN_L3MISS]); + if (tb[IFLA_VXLAN_LEARNING]) + props->learning = !!nla_get_u8 (tb[IFLA_VXLAN_LEARNING]); + if (tb[IFLA_VXLAN_PROXY]) + props->proxy = !!nla_get_u8 (tb[IFLA_VXLAN_PROXY]); + if (tb[IFLA_VXLAN_RSC]) + props->rsc = !!nla_get_u8 (tb[IFLA_VXLAN_RSC]); + if (tb[IFLA_VXLAN_L2MISS]) + props->l2miss = !!nla_get_u8 (tb[IFLA_VXLAN_L2MISS]); + if (tb[IFLA_VXLAN_L3MISS]) + props->l3miss = !!nla_get_u8 (tb[IFLA_VXLAN_L3MISS]); return 0; } @@ -3131,7 +3288,7 @@ wifi_get_capabilities (NMPlatform *platform, int ifindex, NMDeviceWifiCapabiliti } static gboolean -wifi_get_bssid (NMPlatform *platform, int ifindex, struct ether_addr *bssid) +wifi_get_bssid (NMPlatform *platform, int ifindex, guint8 *bssid) { WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); @@ -3244,14 +3401,14 @@ mesh_set_channel (NMPlatform *platform, int ifindex, guint32 channel) } static gboolean -mesh_set_ssid (NMPlatform *platform, int ifindex, const GByteArray *ssid) +mesh_set_ssid (NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len) { WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex); if (!wifi_data) return FALSE; - return wifi_utils_set_mesh_ssid (wifi_data, ssid); + return wifi_utils_set_mesh_ssid (wifi_data, ssid, len); } static gboolean @@ -3287,7 +3444,7 @@ _address_match (struct rtnl_addr *addr, int family, int ifindex) g_return_val_if_fail (addr, FALSE); return rtnl_addr_get_family (addr) == family && - rtnl_addr_get_ifindex (addr) == ifindex; + (ifindex == 0 || rtnl_addr_get_ifindex (addr) == ifindex); } static GArray * @@ -3455,9 +3612,9 @@ ip6_address_add (NMPlatform *platform, } static gboolean -ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) +ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address) { - return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, NULL, plen, 0, 0, 0, NULL), TRUE); + return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, peer_address ? &peer_address : NULL, plen, 0, 0, 0, NULL), TRUE); } static gboolean @@ -3487,10 +3644,53 @@ ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int return ip_address_exists (platform, AF_INET6, ifindex, &addr, plen); } +static gboolean +ip4_check_reinstall_device_route (NMPlatform *platform, int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + NMPlatformIP4Address addr_candidate; + NMPlatformIP4Route route_candidate; + struct nl_object *object; + guint32 device_network; + + for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) { + if (_address_match ((struct rtnl_addr *) object, AF_INET, 0)) { + if (init_ip4_address (&addr_candidate, (struct rtnl_addr *) object)) + if ( addr_candidate.plen == address->plen + && addr_candidate.address == address->address) { + /* If we already have the same address installed on any interface, + * we back off. + * Perform this check first, as we expect to have significantly less + * addresses to search. */ + return FALSE; + } + } + } + + device_network = nm_utils_ip4_address_clear_host_address (address->address, address->plen); + + for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) { + if (_route_match ((struct rtnl_route *) object, AF_INET, 0, TRUE)) { + if (init_ip4_route (&route_candidate, (struct rtnl_route *) object)) { + if ( route_candidate.network == device_network + && route_candidate.plen == address->plen + && ( route_candidate.metric == 0 + || route_candidate.metric == device_route_metric)) { + /* There is already any route with metric 0 or the metric we want to install + * for the same subnet. */ + return FALSE; + } + } + } + } + + return TRUE; +} + /******************************************************************/ static gboolean -_route_match (struct rtnl_route *rtnlroute, int family, int ifindex) +_route_match (struct rtnl_route *rtnlroute, int family, int ifindex, gboolean include_proto_kernel) { struct rtnl_nexthop *nexthop; @@ -3498,31 +3698,42 @@ _route_match (struct rtnl_route *rtnlroute, int family, int ifindex) if (rtnl_route_get_type (rtnlroute) != RTN_UNICAST || rtnl_route_get_table (rtnlroute) != RT_TABLE_MAIN || - rtnl_route_get_protocol (rtnlroute) == RTPROT_KERNEL || + (!include_proto_kernel && rtnl_route_get_protocol (rtnlroute) == RTPROT_KERNEL) || rtnl_route_get_family (rtnlroute) != family || - rtnl_route_get_nnexthops (rtnlroute) != 1) + rtnl_route_get_nnexthops (rtnlroute) != 1 || + rtnl_route_get_flags (rtnlroute) & RTM_F_CLONED) return FALSE; + if (ifindex == 0) + return TRUE; + nexthop = rtnl_route_nexthop_n (rtnlroute, 0); return rtnl_route_nh_get_ifindex (nexthop) == ifindex; } static GArray * -ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default) +ip4_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mode) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); GArray *routes; NMPlatformIP4Route route; struct nl_object *object; + g_return_val_if_fail (NM_IN_SET (mode, NM_PLATFORM_GET_ROUTE_MODE_ALL, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT), NULL); + routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route)); for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) { - if (_route_match ((struct rtnl_route *) object, AF_INET, ifindex)) { - if (init_ip4_route (&route, (struct rtnl_route *) object)) { - if (route.plen != 0 || include_default) - g_array_append_val (routes, route); + if (_route_match ((struct rtnl_route *) object, AF_INET, ifindex, FALSE)) { + if (_rtnl_route_is_default ((struct rtnl_route *) object)) { + if (mode == NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT) + continue; + } else { + if (mode == NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT) + continue; } + if (init_ip4_route (&route, (struct rtnl_route *) object)) + g_array_append_val (routes, route); } } @@ -3530,21 +3741,28 @@ ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default) } static GArray * -ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default) +ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mode) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); GArray *routes; NMPlatformIP6Route route; struct nl_object *object; + g_return_val_if_fail (NM_IN_SET (mode, NM_PLATFORM_GET_ROUTE_MODE_ALL, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT), NULL); + routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP6Route)); for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) { - if (_route_match ((struct rtnl_route *) object, AF_INET6, ifindex)) { - if (init_ip6_route (&route, (struct rtnl_route *) object)) { - if (route.plen != 0 || include_default) - g_array_append_val (routes, route); + if (_route_match ((struct rtnl_route *) object, AF_INET6, ifindex, FALSE)) { + if (_rtnl_route_is_default ((struct rtnl_route *) object)) { + if (mode == NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT) + continue; + } else { + if (mode == NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT) + continue; } + if (init_ip6_route (&route, (struct rtnl_route *) object)) + g_array_append_val (routes, route); } } @@ -3570,9 +3788,10 @@ clear_host_address (int family, const void *network, int plen, void *dst) } static struct nl_object * -build_rtnl_route (int family, int ifindex, NMPlatformSource source, +build_rtnl_route (int family, int ifindex, NMIPConfigSource source, gconstpointer network, int plen, gconstpointer gateway, - int metric, int mss) + gconstpointer pref_src, + guint32 metric, guint32 mss) { guint32 network_clean[4]; struct rtnl_route *rtnlroute; @@ -3581,6 +3800,7 @@ build_rtnl_route (int family, int ifindex, NMPlatformSource source, /* Workaround a libnl bug by using zero destination address length for default routes */ auto_nl_addr struct nl_addr *dst = NULL; auto_nl_addr struct nl_addr *gw = gateway ? _nm_nl_addr_build (family, gateway, addrlen) : NULL; + auto_nl_addr struct nl_addr *pref_src_nl = pref_src ? _nm_nl_addr_build (family, pref_src, addrlen) : NULL; /* There seem to be problems adding a route with non-zero host identifier. * Adding IPv6 routes is simply ignored, without error message. @@ -3602,6 +3822,8 @@ build_rtnl_route (int family, int ifindex, NMPlatformSource source, rtnl_route_nh_set_ifindex (nexthop, ifindex); if (gw && !nl_addr_iszero (gw)) rtnl_route_nh_set_gateway (nexthop, gw); + if (pref_src_nl) + rtnl_route_set_pref_src (rtnlroute, pref_src_nl); rtnl_route_add_nexthop (rtnlroute, nexthop); if (mss > 0) @@ -3611,23 +3833,23 @@ build_rtnl_route (int family, int ifindex, NMPlatformSource source, } static gboolean -ip4_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source, +ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source, in_addr_t network, int plen, in_addr_t gateway, - int metric, int mss) + guint32 pref_src, guint32 metric, guint32 mss) { - return add_object (platform, build_rtnl_route (AF_INET, ifindex, source, &network, plen, &gateway, metric, mss)); + return add_object (platform, build_rtnl_route (AF_INET, ifindex, source, &network, plen, &gateway, pref_src ? &pref_src : NULL, metric, mss)); } static gboolean -ip6_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source, +ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source, struct in6_addr network, int plen, struct in6_addr gateway, - int metric, int mss) + guint32 metric, guint32 mss) { - return add_object (platform, build_rtnl_route (AF_INET6, ifindex, source, &network, plen, &gateway, metric, mss)); + return add_object (platform, build_rtnl_route (AF_INET6, ifindex, source, &network, plen, &gateway, NULL, metric, mss)); } static struct rtnl_route * -route_search_cache (struct nl_cache *cache, int family, int ifindex, const void *network, int plen, int metric) +route_search_cache (struct nl_cache *cache, int family, int ifindex, const void *network, int plen, guint32 metric) { guint32 network_clean[4], dst_clean[4]; struct nl_object *object; @@ -3638,7 +3860,7 @@ route_search_cache (struct nl_cache *cache, int family, int ifindex, const void struct nl_addr *dst; struct rtnl_route *rtnlroute = (struct rtnl_route *) object; - if (!_route_match (rtnlroute, family, ifindex)) + if (!_route_match (rtnlroute, family, ifindex, FALSE)) continue; if (metric && metric != rtnl_route_get_priority (rtnlroute)) @@ -3676,11 +3898,11 @@ refresh_route (NMPlatform *platform, int family, int ifindex, const void *networ } static gboolean -ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric) +ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) { in_addr_t gateway = 0; struct rtnl_route *cached_object; - struct nl_object *route = build_rtnl_route (AF_INET, ifindex, NM_PLATFORM_SOURCE_UNKNOWN, &network, plen, &gateway, metric, 0); + struct nl_object *route = build_rtnl_route (AF_INET, ifindex, NM_IP_CONFIG_SOURCE_UNKNOWN, &network, plen, &gateway, NULL, metric, 0); uint8_t scope = RT_SCOPE_NOWHERE; struct nl_cache *cache; @@ -3736,20 +3958,20 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen } static gboolean -ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric) +ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) { struct in6_addr gateway = IN6ADDR_ANY_INIT; - return delete_object (platform, build_rtnl_route (AF_INET6, ifindex, NM_PLATFORM_SOURCE_UNKNOWN ,&network, plen, &gateway, metric, 0), FALSE) && + return delete_object (platform, build_rtnl_route (AF_INET6, ifindex, NM_IP_CONFIG_SOURCE_UNKNOWN ,&network, plen, &gateway, NULL, metric, 0), FALSE) && refresh_route (platform, AF_INET6, ifindex, &network, plen, metric); } static gboolean -ip_route_exists (NMPlatform *platform, int family, int ifindex, gpointer network, int plen, int metric) +ip_route_exists (NMPlatform *platform, int family, int ifindex, gpointer network, int plen, guint32 metric) { auto_nl_object struct nl_object *object = build_rtnl_route (family, ifindex, - NM_PLATFORM_SOURCE_UNKNOWN, - network, plen, NULL, metric, 0); + NM_IP_CONFIG_SOURCE_UNKNOWN, + network, plen, NULL, NULL, metric, 0); struct nl_cache *cache = choose_cache (platform, object); auto_nl_object struct nl_object *cached_object = nl_cache_search (cache, object); @@ -3759,19 +3981,119 @@ ip_route_exists (NMPlatform *platform, int family, int ifindex, gpointer network } static gboolean -ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric) +ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric) { return ip_route_exists (platform, AF_INET, ifindex, &network, plen, metric); } static gboolean -ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric) +ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric) { return ip_route_exists (platform, AF_INET6, ifindex, &network, plen, metric); } /******************************************************************/ +/* Initialize the link cache while ensuring all links are of AF_UNSPEC, + * family (even though the kernel might set AF_BRIDGE for bridges). + * See also: _nl_link_family_unset() */ +static void +init_link_cache (NMPlatform *platform) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + struct nl_object *object = NULL; + + rtnl_link_alloc_cache (priv->nlh, AF_UNSPEC, &priv->link_cache); + + do { + for (object = nl_cache_get_first (priv->link_cache); object; object = nl_cache_get_next (object)) { + if (rtnl_link_get_family ((struct rtnl_link *)object) != AF_UNSPEC) + break; + } + + if (object) { + /* A non-AF_UNSPEC object encoutnered */ + struct nl_object *existing; + + nl_object_get (object); + nl_cache_remove (object); + rtnl_link_set_family ((struct rtnl_link *)object, AF_UNSPEC); + existing = nl_cache_search (priv->link_cache, object); + if (existing) + nl_object_put (existing); + else + nl_cache_add (priv->link_cache, object); + nl_object_put (object); + } + } while (object); +} + +/* Calls announce_object with appropriate arguments for all objects + * which are not coherent between old and new caches and deallocates + * the old cache. */ +static void +cache_announce_changes (NMPlatform *platform, struct nl_cache *new, struct nl_cache *old) +{ + struct nl_object *object; + + if (!old) + return; + + for (object = nl_cache_get_first (new); object; object = nl_cache_get_next (object)) { + struct nl_object *cached_object = nm_nl_cache_search (old, object); + + if (cached_object) { + ObjectType type = object_type_from_nl_object (object); + if (nm_nl_object_diff (type, object, cached_object)) + announce_object (platform, object, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_EXTERNAL); + nl_object_put (cached_object); + } else + announce_object (platform, object, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_EXTERNAL); + } + for (object = nl_cache_get_first (old); object; object = nl_cache_get_next (object)) { + struct nl_object *cached_object = nm_nl_cache_search (new, object); + if (cached_object) + nl_object_put (cached_object); + else + announce_object (platform, object, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_EXTERNAL); + } + + nl_cache_free (old); +} + +/* Creates and populates the netlink object caches. Called upon platform init and + * when we run out of sync (out of buffer space, netlink congestion control). In case + * the caches already exist, it finds changed, added and removed objects, announces + * them and destroys the old caches. */ +static void +cache_repopulate_all (NMPlatform *platform) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + struct nl_cache *old_link_cache = priv->link_cache; + struct nl_cache *old_address_cache = priv->address_cache; + struct nl_cache *old_route_cache = priv->route_cache; + struct nl_object *object; + + debug ("platform: %spopulate platform cache", old_link_cache ? "re" : ""); + + /* Allocate new netlink caches */ + init_link_cache (platform); + rtnl_addr_alloc_cache (priv->nlh, &priv->address_cache); + rtnl_route_alloc_cache (priv->nlh, AF_UNSPEC, 0, &priv->route_cache); + g_assert (priv->link_cache && priv->address_cache && priv->route_cache); + + for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) { + _rtnl_addr_hack_lifetimes_rel_to_abs ((struct rtnl_addr *) object); + } + + /* Make sure all changes we've missed are announced. */ + cache_announce_changes (platform, priv->link_cache, old_link_cache); + cache_announce_changes (platform, priv->address_cache, old_address_cache); + cache_announce_changes (platform, priv->route_cache, old_route_cache); +} + +/******************************************************************/ + #define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI)) #define ERROR_CONDITIONS ((GIOCondition) (G_IO_ERR | G_IO_NVAL)) #define DISCONNECT_CONDITIONS ((GIOCondition) (G_IO_HUP)) @@ -3798,7 +4120,8 @@ event_handler (GIOChannel *channel, GIOCondition io_condition, gpointer user_data) { - NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (user_data); + NMPlatform *platform = NM_PLATFORM (user_data); + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); int nle; nle = nl_recvmsgs_default (priv->nlh_event); @@ -3810,6 +4133,17 @@ event_handler (GIOChannel *channel, * and can happen easily. */ debug ("Uncritical failure to retrieve incoming events: %s (%d)", nl_geterror (nle), nle); break; + case -NLE_NOMEM: + warning ("Too many netlink events. Need to resynchronize platform cache"); + /* Drain the event queue, we've lost events and are out of sync anyway and we'd + * like to free up some space. We'll read in the status synchronously. */ + nl_socket_modify_cb (priv->nlh_event, NL_CB_VALID, NL_CB_DEFAULT, NULL, NULL); + do { + nle = nl_recvmsgs_default (priv->nlh_event); + } while (nle != -NLE_AGAIN); + nl_socket_modify_cb (priv->nlh_event, NL_CB_VALID, NL_CB_CUSTOM, event_notification, user_data); + cache_repopulate_all (platform); + break; default: error ("Failed to retrieve incoming events: %s (%d)", nl_geterror (nle), nle); break; @@ -3841,6 +4175,12 @@ setup_socket (gboolean event, gpointer user_data) nle = nl_socket_set_passcred (sock, 1); g_assert (!nle); + /* No blocking for event socket, so that we can drain it safely. */ + if (event) { + nle = nl_socket_set_nonblocking (sock); + g_assert (!nle); + } + return sock; } @@ -3979,7 +4319,9 @@ setup (NMPlatform *platform) int channel_flags; gboolean status; int nle; +#if HAVE_LIBNL_INET6_ADDR_GEN_MODE struct nl_object *object; +#endif /* Initialize netlink socket for requests */ priv->nlh = setup_socket (FALSE, platform); @@ -4015,14 +4357,25 @@ setup (NMPlatform *platform) (EVENT_CONDITIONS | ERROR_CONDITIONS | DISCONNECT_CONDITIONS), event_handler, platform); - /* Allocate netlink caches */ - rtnl_link_alloc_cache (priv->nlh, AF_UNSPEC, &priv->link_cache); - rtnl_addr_alloc_cache (priv->nlh, &priv->address_cache); - rtnl_route_alloc_cache (priv->nlh, AF_UNSPEC, 0, &priv->route_cache); - g_assert (priv->link_cache && priv->address_cache && priv->route_cache); + cache_repopulate_all (platform); - for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) - _rtnl_addr_hack_lifetimes_rel_to_abs ((struct rtnl_addr *) object); +#if HAVE_LIBNL_INET6_ADDR_GEN_MODE + /* Initial check for user IPv6LL support once the link cache is allocated + * and filled. If there are no links in the cache yet then we'll check + * when a new link shows up in announce_object(). + */ + object = nl_cache_get_first (priv->link_cache); + if (object) { + uint8_t mode; + + if (rtnl_link_inet6_get_addr_gen_mode ((struct rtnl_link *) object, &mode) == 0) + priv->support_user_ipv6ll = 1; + else + priv->support_user_ipv6ll = -1; + } +#else + priv->support_user_ipv6ll = -1; +#endif /* Set up udev monitoring */ priv->udev_client = g_udev_client_new (udev_subsys); @@ -4111,6 +4464,9 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->link_is_connected = link_is_connected; platform_class->link_uses_arp = link_uses_arp; + platform_class->link_get_user_ipv6ll_enabled = link_get_user_ipv6ll_enabled; + platform_class->link_set_user_ipv6ll_enabled = link_set_user_ipv6ll_enabled; + platform_class->link_get_address = link_get_address; platform_class->link_set_address = link_set_address; platform_class->link_get_mtu = link_get_mtu; @@ -4167,6 +4523,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->ip4_address_exists = ip4_address_exists; platform_class->ip6_address_exists = ip6_address_exists; + platform_class->ip4_check_reinstall_device_route = ip4_check_reinstall_device_route; + platform_class->ip4_route_get_all = ip4_route_get_all; platform_class->ip6_route_get_all = ip6_route_get_all; platform_class->ip4_route_add = ip4_route_add; @@ -4177,4 +4535,5 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->ip6_route_exists = ip6_route_exists; platform_class->check_support_kernel_extended_ifa_flags = check_support_kernel_extended_ifa_flags; + platform_class->check_support_user_ipv6ll = check_support_user_ipv6ll; } diff --git a/src/platform/nm-linux-platform.h b/src/platform/nm-linux-platform.h index 53ea75e69..6f2c19939 100644 --- a/src/platform/nm-linux-platform.h +++ b/src/platform/nm-linux-platform.h @@ -18,8 +18,8 @@ * Copyright (C) 2012 Red Hat, Inc. */ -#ifndef NM_LINUX_PLATFORM_H -#define NM_LINUX_PLATFORM_H +#ifndef __NETWORKMANAGER_LINUX_PLATFORM_H__ +#define __NETWORKMANAGER_LINUX_PLATFORM_H__ #include "nm-platform.h" @@ -46,4 +46,4 @@ GType nm_linux_platform_get_type (void); void nm_linux_platform_setup (void); -#endif /* NM_LINUX_PLATFORM_H */ +#endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 542b0faab..14fc44c5f 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -18,6 +18,8 @@ * Copyright (C) 2012 Red Hat, Inc. */ +#include "config.h" + #include <stdlib.h> #include <errno.h> #include <unistd.h> @@ -26,6 +28,7 @@ #include <string.h> #include <netlink/route/addr.h> +#include "gsystem-local-alloc.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-platform.h" @@ -215,6 +218,21 @@ nm_platform_check_support_kernel_extended_ifa_flags () return klass->check_support_kernel_extended_ifa_flags (platform); } +gboolean +nm_platform_check_support_user_ipv6ll (void) +{ + static int supported = -1; + + g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE); + + if (!klass->check_support_user_ipv6ll) + return FALSE; + + if (supported < 0) + supported = klass->check_support_user_ipv6ll (platform) ? 1 : 0; + return !!supported; +} + /******************************************************************/ /** @@ -730,6 +748,52 @@ nm_platform_link_uses_arp (int ifindex) } /** + * nm_platform_link_get_user_ip6vll_enabled: + * @ifindex: Interface index + * + * Check whether NM handles IPv6LL address creation for the link. If the + * platform or OS doesn't support changing the IPv6LL address mode, this call + * will fail and return %FALSE. + * + * Returns: %TRUE if NM handles the IPv6LL address for @ifindex + */ +gboolean +nm_platform_link_get_user_ipv6ll_enabled (int ifindex) +{ + reset_error (); + + g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail (klass->check_support_user_ipv6ll, FALSE); + + if (klass->link_get_user_ipv6ll_enabled) + return klass->link_get_user_ipv6ll_enabled (platform, ifindex); + return FALSE; +} + +/** + * nm_platform_link_set_user_ip6vll_enabled: + * @ifindex: Interface index + * + * Set whether NM handles IPv6LL address creation for the link. If the + * platform or OS doesn't support changing the IPv6LL address mode, this call + * will fail and return %FALSE. + * + * Returns: %TRUE if the operation was successful, %FALSE if it failed. + */ +gboolean +nm_platform_link_set_user_ipv6ll_enabled (int ifindex, gboolean enabled) +{ + reset_error (); + + g_return_val_if_fail (ifindex >= 0, FALSE); + g_return_val_if_fail (klass->check_support_user_ipv6ll, FALSE); + + if (klass->link_set_user_ipv6ll_enabled) + return klass->link_set_user_ipv6ll_enabled (platform, ifindex, enabled); + return FALSE; +} + +/** * nm_platform_link_set_address: * @ifindex: Interface index * @address: The new MAC address @@ -877,7 +941,7 @@ nm_platform_link_set_mtu (int ifindex, guint32 mtu) g_return_val_if_fail (mtu > 0, FALSE); g_return_val_if_fail (klass->link_set_mtu, FALSE); - debug ("link: setting '%s' (%d) mtu %d", nm_platform_link_get_name (ifindex), ifindex, mtu); + debug ("link: setting '%s' (%d) mtu %"G_GUINT32_FORMAT, nm_platform_link_get_name (ifindex), ifindex, mtu); return klass->link_set_mtu (platform, ifindex, mtu); } @@ -1051,7 +1115,7 @@ nm_platform_team_add (const char *name) * nm_platform_vlan_add: * @name: New interface name * @vlanid: VLAN identifier - * @vlanflags: VLAN flags from libnm-util + * @vlanflags: VLAN flags from libnm * * Create a software VLAN device. */ @@ -1266,7 +1330,7 @@ nm_platform_wifi_get_capabilities (int ifindex, NMDeviceWifiCapabilities *caps) } gboolean -nm_platform_wifi_get_bssid (int ifindex, struct ether_addr *bssid) +nm_platform_wifi_get_bssid (int ifindex, guint8 *bssid) { reset_error (); @@ -1377,14 +1441,38 @@ nm_platform_mesh_set_channel (int ifindex, guint32 channel) } gboolean -nm_platform_mesh_set_ssid (int ifindex, const GByteArray *ssid) +nm_platform_mesh_set_ssid (int ifindex, const guint8 *ssid, gsize len) { reset_error (); g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (ssid != NULL, FALSE); - return klass->mesh_set_ssid (platform, ifindex, ssid); + return klass->mesh_set_ssid (platform, ifindex, ssid, len); +} + +#define TO_STRING_DEV_BUF_SIZE (5+15+1) +static const char * +_to_string_dev (int ifindex, char *buf, size_t size) +{ + g_assert (buf && size >= TO_STRING_DEV_BUF_SIZE); + + if (ifindex) { + const char *name = ifindex > 0 ? nm_platform_link_get_name (ifindex) : NULL; + char *buf2; + + strcpy (buf, " dev "); + buf2 = buf + 5; + size -= 5; + + if (name) + g_strlcpy (buf2, name, size); + else + g_snprintf (buf2, size, "%d", ifindex); + } else + buf[0] = 0; + + return buf; } /******************************************************************/ @@ -1482,28 +1570,41 @@ nm_platform_ip6_address_add (int ifindex, } gboolean -nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen) +nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen, in_addr_t peer_address) { + char str_dev[TO_STRING_DEV_BUF_SIZE]; + char str_peer[NM_UTILS_INET_ADDRSTRLEN]; + reset_error (); g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (plen > 0, FALSE); g_return_val_if_fail (klass->ip4_address_delete, FALSE); - debug ("address: deleting IPv4 address %s/%d", nm_utils_inet4_ntop (address, NULL), plen); - return klass->ip4_address_delete (platform, ifindex, address, plen); + debug ("address: deleting IPv4 address %s/%d, %s%s%sifindex %d%s", + nm_utils_inet4_ntop (address, NULL), plen, + peer_address ? "peer " : "", + peer_address ? nm_utils_inet4_ntop (peer_address, str_peer) : "", + peer_address ? ", " : "", + ifindex, + _to_string_dev (ifindex, str_dev, sizeof (str_dev))); + return klass->ip4_address_delete (platform, ifindex, address, plen, peer_address); } gboolean nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen) { + char str_dev[TO_STRING_DEV_BUF_SIZE]; + reset_error (); g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (plen > 0, FALSE); g_return_val_if_fail (klass->ip6_address_delete, FALSE); - debug ("address: deleting IPv6 address %s/%d", nm_utils_inet6_ntop (&address, NULL), plen); + debug ("address: deleting IPv6 address %s/%d, ifindex %d%s", + nm_utils_inet6_ntop (&address, NULL), plen, ifindex, + _to_string_dev (ifindex, str_dev, sizeof (str_dev))); return klass->ip6_address_delete (platform, ifindex, address, plen); } @@ -1600,11 +1701,16 @@ _rebase_relative_time_on_now (guint32 timestamp, guint32 duration, guint32 now, static gboolean _address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32 padding, guint32 *out_lifetime, guint32 *out_preferred) { - gint32 lifetime, preferred; + guint32 lifetime, preferred; if (address->lifetime == 0) { *out_lifetime = NM_PLATFORM_LIFETIME_PERMANENT; *out_preferred = NM_PLATFORM_LIFETIME_PERMANENT; + + /* We treat lifetime==0 as permanent addresses to allow easy creation of such addresses + * (without requiring to set the lifetime fields to NM_PLATFORM_LIFETIME_PERMANENT). + * In that case we also expect that the other fields (timestamp and preferred) are left unset. */ + g_return_val_if_fail (address->timestamp == 0 && address->preferred == 0, TRUE); } else { lifetime = _rebase_relative_time_on_now (address->timestamp, address->lifetime, now, padding); if (!lifetime) @@ -1626,10 +1732,31 @@ _address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32 return TRUE; } +gboolean +nm_platform_ip4_check_reinstall_device_route (int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric) +{ + g_return_val_if_fail (address, FALSE); + + if ( ifindex <= 0 + || address->plen <= 0 + || address->plen >= 32) + return FALSE; + + if (device_route_metric == NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE) { + /* The automatically added route would be already our desired priority. + * Nothing to do. */ + return FALSE; + } + + return klass->ip4_check_reinstall_device_route (platform, ifindex, address, device_route_metric); +} + /** * nm_platform_ip4_address_sync: * @ifindex: Interface index * @known_addresses: List of addresses + * @device_route_metric: the route metric for adding subnet routes (replaces + * the kernel added routes). * * A convenience function to synchronize addresses for a specific interface * with the least possible disturbance. It simply removes addresses that are @@ -1638,7 +1765,7 @@ _address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32 * Returns: %TRUE on success. */ gboolean -nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses) +nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses, guint32 device_route_metric) { GArray *addresses; NMPlatformIP4Address *address; @@ -1651,7 +1778,7 @@ nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses) address = &g_array_index (addresses, NMPlatformIP4Address, i); if (!array_contains_ip4_address (known_addresses, address)) - nm_platform_ip4_address_delete (ifindex, address->address, address->plen); + nm_platform_ip4_address_delete (ifindex, address->address, address->plen, address->peer_address); } g_array_free (addresses, TRUE); @@ -1662,13 +1789,34 @@ nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses) for (i = 0; i < known_addresses->len; i++) { const NMPlatformIP4Address *known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i); guint32 lifetime, preferred; + guint32 network; + gboolean reinstall_device_route = FALSE; /* add a padding of 5 seconds to avoid potential races. */ if (!_address_get_lifetime ((NMPlatformIPAddress *) known_address, now, 5, &lifetime, &preferred)) continue; + if (nm_platform_ip4_check_reinstall_device_route (ifindex, known_address, device_route_metric)) + reinstall_device_route = TRUE; + if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->peer_address, known_address->plen, lifetime, preferred, known_address->label)) return FALSE; + + if (reinstall_device_route) { + /* Kernel automatically adds a device route for us with metric 0. That is not what we want. + * Remove it, and re-add it. + * + * In face of having the same subnets on two different interfaces with the same metric, + * this is a problem. Surprisingly, kernel is able to add two routes for the same subnet/prefix,metric + * to different interfaces. We cannot. Adding one, would replace the other. This is avoided + * by the above nm_platform_ip4_check_reinstall_device_route() check. + */ + network = nm_utils_ip4_address_clear_host_address (known_address->address, known_address->plen); + (void) nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_KERNEL, network, known_address->plen, + 0, known_address->address, device_route_metric, 0); + (void) nm_platform_ip4_route_delete (ifindex, network, known_address->plen, + NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE); + } } return TRUE; @@ -1731,49 +1879,49 @@ nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses) gboolean nm_platform_address_flush (int ifindex) { - return nm_platform_ip4_address_sync (ifindex, NULL) + return nm_platform_ip4_address_sync (ifindex, NULL, 0) && nm_platform_ip6_address_sync (ifindex, NULL); } /******************************************************************/ GArray * -nm_platform_ip4_route_get_all (int ifindex, gboolean include_default) +nm_platform_ip4_route_get_all (int ifindex, NMPlatformGetRouteMode mode) { reset_error (); - g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail (ifindex >= 0, NULL); g_return_val_if_fail (klass->ip4_route_get_all, NULL); - return klass->ip4_route_get_all (platform, ifindex, include_default); + return klass->ip4_route_get_all (platform, ifindex, mode); } GArray * -nm_platform_ip6_route_get_all (int ifindex, gboolean include_default) +nm_platform_ip6_route_get_all (int ifindex, NMPlatformGetRouteMode mode) { reset_error (); - g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail (ifindex >= 0, NULL); g_return_val_if_fail (klass->ip6_route_get_all, NULL); - return klass->ip6_route_get_all (platform, ifindex, include_default); + return klass->ip6_route_get_all (platform, ifindex, mode); } gboolean -nm_platform_ip4_route_add (int ifindex, NMPlatformSource source, +nm_platform_ip4_route_add (int ifindex, NMIPConfigSource source, in_addr_t network, int plen, - in_addr_t gateway, int metric, int mss) + in_addr_t gateway, guint32 pref_src, + guint32 metric, guint32 mss) { reset_error (); g_return_val_if_fail (platform, FALSE); g_return_val_if_fail (0 <= plen && plen <= 32, FALSE); - g_return_val_if_fail (metric >= 0, FALSE); - g_return_val_if_fail (mss >= 0, FALSE); g_return_val_if_fail (klass->ip4_route_add, FALSE); if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { NMPlatformIP4Route route = { 0 }; + char pref_src_buf[NM_UTILS_INET_ADDRSTRLEN]; route.ifindex = ifindex; route.source = source; @@ -1783,20 +1931,21 @@ nm_platform_ip4_route_add (int ifindex, NMPlatformSource source, route.metric = metric; route.mss = mss; - debug ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (&route)); + debug ("route: adding or updating IPv4 route: %s%s%s%s", nm_platform_ip4_route_to_string (&route), + pref_src ? " (src: " : "", + pref_src ? nm_utils_inet4_ntop (pref_src, pref_src_buf) : "", + pref_src ? ")" : ""); } - return klass->ip4_route_add (platform, ifindex, source, network, plen, gateway, metric, mss); + return klass->ip4_route_add (platform, ifindex, source, network, plen, gateway, pref_src, metric, mss); } gboolean -nm_platform_ip6_route_add (int ifindex, NMPlatformSource source, +nm_platform_ip6_route_add (int ifindex, NMIPConfigSource source, struct in6_addr network, int plen, struct in6_addr gateway, - int metric, int mss) + guint32 metric, guint32 mss) { g_return_val_if_fail (platform, FALSE); g_return_val_if_fail (0 <= plen && plen <= 128, FALSE); - g_return_val_if_fail (metric >= 0, FALSE); - g_return_val_if_fail (mss >= 0, FALSE); g_return_val_if_fail (klass->ip6_route_add, FALSE); if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { @@ -1816,31 +1965,39 @@ nm_platform_ip6_route_add (int ifindex, NMPlatformSource source, } gboolean -nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, int metric) +nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, guint32 metric) { + char str_dev[TO_STRING_DEV_BUF_SIZE]; + reset_error (); g_return_val_if_fail (platform, FALSE); g_return_val_if_fail (klass->ip4_route_delete, FALSE); - debug ("route: deleting IPv4 route %s/%d, metric=%d", nm_utils_inet4_ntop (network, NULL), plen, metric); + debug ("route: deleting IPv4 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s", + nm_utils_inet4_ntop (network, NULL), plen, metric, ifindex, + _to_string_dev (ifindex, str_dev, sizeof (str_dev))); return klass->ip4_route_delete (platform, ifindex, network, plen, metric); } gboolean -nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, int metric) +nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, guint32 metric) { + char str_dev[TO_STRING_DEV_BUF_SIZE]; + reset_error (); g_return_val_if_fail (platform, FALSE); g_return_val_if_fail (klass->ip6_route_delete, FALSE); - debug ("route: deleting IPv6 route %s/%d, metric=%d", nm_utils_inet6_ntop (&network, NULL), plen, metric); + debug ("route: deleting IPv6 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s", + nm_utils_inet6_ntop (&network, NULL), plen, metric, ifindex, + _to_string_dev (ifindex, str_dev, sizeof (str_dev))); return klass->ip6_route_delete (platform, ifindex, network, plen, metric); } gboolean -nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, int metric) +nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, guint32 metric) { reset_error (); @@ -1851,7 +2008,7 @@ nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, int metr } gboolean -nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, int metric) +nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, guint32 metric) { reset_error (); @@ -1907,6 +2064,8 @@ array_contains_ip6_route (const GArray *routes, const NMPlatformIP6Route *route) * A convenience function to synchronize routes for a specific interface * with the least possible disturbance. It simply removes routes that are * not listed and adds routes that are. + * Default routes are ignored (both in @known_routes and those already + * configured on the device). * * Returns: %TRUE on success. */ @@ -1920,12 +2079,12 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes) int i, i_type; /* Delete unknown routes */ - routes = nm_platform_ip4_route_get_all (ifindex, FALSE); + routes = nm_platform_ip4_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT); for (i = 0; i < routes->len; i++) { route = &g_array_index (routes, NMPlatformIP4Route, i); if (!array_contains_ip4_route (known_routes, route)) - nm_platform_ip4_route_delete (ifindex, route->network, route->plen, route->metric); + (void) nm_platform_ip4_route_delete (ifindex, route->network, route->plen, route->metric); } if (!known_routes) { @@ -1938,6 +2097,9 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes) for (i = 0; i < known_routes->len && success; i++) { known_route = &g_array_index (known_routes, NMPlatformIP4Route, i); + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (known_route)) + continue; + if ((known_route->gateway == 0) ^ (i_type != 0)) { /* Make two runs over the list of routes. On the first, only add * device routes, on the second the others (gateway routes). */ @@ -1951,9 +2113,10 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes) known_route->network, known_route->plen, known_route->gateway, + 0, known_route->metric, known_route->mss); - if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { + if (!success && known_route->source < NM_IP_CONFIG_SOURCE_USER) { nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv4 route to kernel: %s", nm_platform_ip4_route_to_string (known_route)); success = TRUE; @@ -1974,6 +2137,8 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes) * A convenience function to synchronize routes for a specific interface * with the least possible disturbance. It simply removes routes that are * not listed and adds routes that are. + * Default routes are ignored (both in @known_routes and those already + * configured on the device). * * Returns: %TRUE on success. */ @@ -1987,7 +2152,7 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes) int i, i_type; /* Delete unknown routes */ - routes = nm_platform_ip6_route_get_all (ifindex, FALSE); + routes = nm_platform_ip6_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT); for (i = 0; i < routes->len; i++) { route = &g_array_index (routes, NMPlatformIP6Route, i); route->ifindex = 0; @@ -2006,6 +2171,9 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes) for (i = 0; i < known_routes->len && success; i++) { known_route = &g_array_index (known_routes, NMPlatformIP6Route, i); + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (known_route)) + continue; + if (IN6_IS_ADDR_UNSPECIFIED (&known_route->gateway) ^ (i_type != 0)) { /* Make two runs over the list of routes. On the first, only add * device routes, on the second the others (gateway routes). */ @@ -2021,7 +2189,7 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes) known_route->gateway, known_route->metric, known_route->mss); - if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { + if (!success && known_route->source < NM_IP_CONFIG_SOURCE_USER) { nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv6 route to kernel: %s", nm_platform_ip6_route_to_string (known_route)); success = TRUE; @@ -2044,26 +2212,26 @@ nm_platform_route_flush (int ifindex) /******************************************************************/ static const char * -source_to_string (NMPlatformSource source) +source_to_string (NMIPConfigSource source) { switch (source) { - case NM_PLATFORM_SOURCE_KERNEL: + case NM_IP_CONFIG_SOURCE_KERNEL: return "kernel"; - case NM_PLATFORM_SOURCE_SHARED: + case NM_IP_CONFIG_SOURCE_SHARED: return "shared"; - case NM_PLATFORM_SOURCE_IP4LL: + case NM_IP_CONFIG_SOURCE_IP4LL: return "ipv4ll"; - case NM_PLATFORM_SOURCE_PPP: + case NM_IP_CONFIG_SOURCE_PPP: return "ppp"; - case NM_PLATFORM_SOURCE_WWAN: + case NM_IP_CONFIG_SOURCE_WWAN: return "wwan"; - case NM_PLATFORM_SOURCE_VPN: + case NM_IP_CONFIG_SOURCE_VPN: return "vpn"; - case NM_PLATFORM_SOURCE_DHCP: + case NM_IP_CONFIG_SOURCE_DHCP: return "dhcp"; - case NM_PLATFORM_SOURCE_RDISC: + case NM_IP_CONFIG_SOURCE_RDISC: return "rdisc"; - case NM_PLATFORM_SOURCE_USER: + case NM_IP_CONFIG_SOURCE_USER: return "user"; default: break; @@ -2071,27 +2239,6 @@ source_to_string (NMPlatformSource source) return "unknown"; } -#define TO_STRING_DEV_BUF_SIZE (5+15+1) -static void -_to_string_dev (int ifindex, char *buf, size_t size) -{ - g_assert (buf && size >= TO_STRING_DEV_BUF_SIZE); - - if (ifindex){ - const char *name = ifindex > 0 ? nm_platform_link_get_name (ifindex) : NULL; - - strcpy (buf, " dev "); - buf += 5; - size -= 5; - - if (name) - g_strlcpy (buf, name, size); - else - g_snprintf (buf, size, "%d", ifindex); - } else - buf[0] = 0; -} - static const char * _lifetime_to_string (guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size) { @@ -2330,7 +2477,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route) _to_string_dev (route->ifindex, str_dev, sizeof (str_dev)); - g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %u mss %u src %s", + g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %"G_GUINT32_FORMAT" mss %"G_GUINT32_FORMAT" src %s", s_network, route->plen, s_gateway, str_dev, route->metric, route->mss, @@ -2363,7 +2510,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route) _to_string_dev (route->ifindex, str_dev, sizeof (str_dev)); - g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %u mss %u src %s", + g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %"G_GUINT32_FORMAT" mss %"G_GUINT32_FORMAT" src %s", s_network, route->plen, s_gateway, str_dev, route->metric, route->mss, diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 96b6cfabb..848f78e42 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -18,17 +18,17 @@ * Copyright (C) 2009 - 2010 Red Hat, Inc. */ -#ifndef NM_PLATFORM_H -#define NM_PLATFORM_H +#ifndef __NETWORKMANAGER_PLATFORM_H__ +#define __NETWORKMANAGER_PLATFORM_H__ #include <glib-object.h> #include "nm-glib-compat.h" #include <netinet/in.h> -#include <net/ethernet.h> #include <linux/if.h> #include <linux/if_addr.h> -#include <NetworkManager.h> +#include <nm-dbus-interface.h> +#include "nm-types.h" #define NM_TYPE_PLATFORM (nm_platform_get_type ()) #define NM_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform)) @@ -72,54 +72,11 @@ typedef enum { NM_PLATFORM_REASON_CACHE_CHECK } NMPlatformReason; -typedef enum { - /* Please don't interpret type numbers outside nm-platform and use functions - * like nm_platform_link_is_software() and nm_platform_supports_slaves(). - * - * type & 0x10000 -> Software device type - * type & 0x20000 -> Type supports slaves - */ - - /* No type, used as error value */ - NM_LINK_TYPE_NONE, - - /* Unknown type */ - NM_LINK_TYPE_UNKNOWN, - - /* Hardware types */ - NM_LINK_TYPE_ETHERNET, - NM_LINK_TYPE_INFINIBAND, - NM_LINK_TYPE_OLPC_MESH, - NM_LINK_TYPE_WIFI, - NM_LINK_TYPE_WWAN_ETHERNET, /* WWAN pseudo-ethernet */ - NM_LINK_TYPE_WIMAX, - - /* Software types */ - NM_LINK_TYPE_DUMMY = 0x10000, - NM_LINK_TYPE_GRE, - NM_LINK_TYPE_GRETAP, - NM_LINK_TYPE_IFB, - NM_LINK_TYPE_LOOPBACK, - NM_LINK_TYPE_MACVLAN, - NM_LINK_TYPE_MACVTAP, - NM_LINK_TYPE_OPENVSWITCH, - NM_LINK_TYPE_TAP, - NM_LINK_TYPE_TUN, - NM_LINK_TYPE_VETH, - NM_LINK_TYPE_VLAN, - NM_LINK_TYPE_VXLAN, - - /* Software types with slaves */ - NM_LINK_TYPE_BRIDGE = 0x10000 | 0x20000, - NM_LINK_TYPE_BOND, - NM_LINK_TYPE_TEAM, -} NMLinkType; - #define __NMPlatformObject_COMMON \ int ifindex; \ ; -typedef struct { +struct _NMPlatformLink { __NMPlatformObject_COMMON; char name[IFNAMSIZ]; NMLinkType type; @@ -132,7 +89,7 @@ typedef struct { gboolean connected; gboolean arp; guint mtu; -} NMPlatformLink; +}; typedef enum { NM_PLATFORM_SIGNAL_ADDED, @@ -143,19 +100,10 @@ typedef enum { #define NM_PLATFORM_LIFETIME_PERMANENT G_MAXUINT32 typedef enum { - /* In priority order; higher number == higher priority */ - NM_PLATFORM_SOURCE_UNKNOWN, - NM_PLATFORM_SOURCE_KERNEL, - NM_PLATFORM_SOURCE_SHARED, - NM_PLATFORM_SOURCE_IP4LL, - NM_PLATFORM_SOURCE_PPP, - NM_PLATFORM_SOURCE_WWAN, - NM_PLATFORM_SOURCE_VPN, - NM_PLATFORM_SOURCE_DHCP, - NM_PLATFORM_SOURCE_RDISC, - NM_PLATFORM_SOURCE_USER, -} NMPlatformSource; - + NM_PLATFORM_GET_ROUTE_MODE_ALL, + NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT, + NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT, +} NMPlatformGetRouteMode; typedef struct { __NMPlatformObject_COMMON; @@ -164,7 +112,7 @@ typedef struct { #define __NMPlatformIPAddress_COMMON \ __NMPlatformObject_COMMON; \ - NMPlatformSource source; \ + NMIPConfigSource source; \ \ /* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*(). * @@ -207,37 +155,55 @@ typedef struct { * NMPlatformIP4Address: * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_s() **/ -typedef struct { +struct _NMPlatformIP4Address { __NMPlatformIPAddress_COMMON; in_addr_t address; in_addr_t peer_address; /* PTP peer address */ char label[IFNAMSIZ]; -} NMPlatformIP4Address; +}; G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Address, address)); /** * NMPlatformIP6Address: * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_s() **/ -typedef struct { +struct _NMPlatformIP6Address { __NMPlatformIPAddress_COMMON; struct in6_addr address; struct in6_addr peer_address; guint flags; /* ifa_flags from <linux/if_addr.h>, field type "unsigned int" is as used in rtnl_addr_get_flags. */ -} NMPlatformIP6Address; +}; G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP6Address, address)); +typedef union { + NMPlatformIPAddress ax; + NMPlatformIP4Address a4; + NMPlatformIP6Address a6; +} NMPlatformIPXAddress; + #undef __NMPlatformIPAddress_COMMON -#define NM_PLATFORM_ROUTE_METRIC_DEFAULT 1024 +/* Default value for adding an IPv4 route. This is also what iproute2 does. + * Note that contrary to IPv6, you can add routes with metric 0 and it is even + * the default. + */ +#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 0 + +/* Default value for adding an IPv6 route. This is also what iproute2 does. + * Adding an IPv6 route with metric 0, kernel translates to IP6_RT_PRIO_USER (1024). */ +#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 1024 + +/* For IPv4, kernel adds a device route (subnet routes) with metric 0 when user + * configures addresses. */ +#define NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE 0 #define __NMPlatformIPRoute_COMMON \ __NMPlatformObject_COMMON; \ - NMPlatformSource source; \ + NMIPConfigSource source; \ int plen; \ - guint metric; \ - guint mss; \ + guint32 metric; \ + guint32 mss; \ ; typedef struct { @@ -248,20 +214,29 @@ typedef struct { }; } NMPlatformIPRoute; -typedef struct { +#define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) \ + ( ((const NMPlatformIPRoute *) (route))->plen <= 0 ) + +struct _NMPlatformIP4Route { __NMPlatformIPRoute_COMMON; in_addr_t network; in_addr_t gateway; -} NMPlatformIP4Route; +}; G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Route, network)); -typedef struct { +struct _NMPlatformIP6Route { __NMPlatformIPRoute_COMMON; struct in6_addr network; struct in6_addr gateway; -} NMPlatformIP6Route; +}; G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP6Route, network)); +typedef union { + NMPlatformIPRoute rx; + NMPlatformIP4Route r4; + NMPlatformIP6Route r6; +} NMPlatformIPXRoute; + #undef __NMPlatformIPRoute_COMMON @@ -384,6 +359,9 @@ typedef struct { gboolean (*link_is_connected) (NMPlatform *, int ifindex); gboolean (*link_uses_arp) (NMPlatform *, int ifindex); + gboolean (*link_get_user_ipv6ll_enabled) (NMPlatform *, int ifindex); + gboolean (*link_set_user_ipv6ll_enabled) (NMPlatform *, int ifindex, gboolean enabled); + gconstpointer (*link_get_address) (NMPlatform *, int ifindex, size_t *length); gboolean (*link_set_address) (NMPlatform *, int ifindex, gconstpointer address, size_t length); guint32 (*link_get_mtu) (NMPlatform *, int ifindex); @@ -417,7 +395,7 @@ typedef struct { gboolean (*gre_get_properties) (NMPlatform *, int ifindex, NMPlatformGreProperties *props); gboolean (*wifi_get_capabilities) (NMPlatform *, int ifindex, NMDeviceWifiCapabilities *caps); - gboolean (*wifi_get_bssid) (NMPlatform *, int ifindex, struct ether_addr *bssid); + gboolean (*wifi_get_bssid) (NMPlatform *, int ifindex, guint8 *bssid); GByteArray *(*wifi_get_ssid) (NMPlatform *, int ifindex); guint32 (*wifi_get_frequency) (NMPlatform *, int ifindex); int (*wifi_get_quality) (NMPlatform *, int ifindex); @@ -429,7 +407,7 @@ typedef struct { guint32 (*mesh_get_channel) (NMPlatform *, int ifindex); gboolean (*mesh_set_channel) (NMPlatform *, int ifindex, guint32 channel); - gboolean (*mesh_set_ssid) (NMPlatform *, int ifindex, const GByteArray *ssid); + gboolean (*mesh_set_ssid) (NMPlatform *, int ifindex, const guint8 *ssid, gsize len); GArray * (*ip4_address_get_all) (NMPlatform *, int ifindex); GArray * (*ip6_address_get_all) (NMPlatform *, int ifindex); @@ -440,25 +418,28 @@ typedef struct { gboolean (*ip6_address_add) (NMPlatform *, int ifindex, struct in6_addr address, struct in6_addr peer_address, int plen, guint32 lifetime, guint32 preferred_lft, guint flags); - gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen); + gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen, in_addr_t peer_address); gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen); gboolean (*ip4_address_exists) (NMPlatform *, int ifindex, in_addr_t address, int plen); gboolean (*ip6_address_exists) (NMPlatform *, int ifindex, struct in6_addr address, int plen); - GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, gboolean include_default); - GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, gboolean include_default); - gboolean (*ip4_route_add) (NMPlatform *, int ifindex, NMPlatformSource source, + gboolean (*ip4_check_reinstall_device_route) (NMPlatform *, int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric); + + GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteMode mode); + GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteMode mode); + gboolean (*ip4_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source, in_addr_t network, int plen, in_addr_t gateway, - int prio, int mss); - gboolean (*ip6_route_add) (NMPlatform *, int ifindex, NMPlatformSource source, + guint32 pref_src, guint32 metric, guint32 mss); + gboolean (*ip6_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source, struct in6_addr network, int plen, struct in6_addr gateway, - int prio, int mss); - gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, int plen, int metric); - gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, int metric); - gboolean (*ip4_route_exists) (NMPlatform *, int ifindex, in_addr_t network, int plen, int metric); - gboolean (*ip6_route_exists) (NMPlatform *, int ifindex, struct in6_addr network, int plen, int metric); + guint32 metric, guint32 mss); + gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric); + gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric); + gboolean (*ip4_route_exists) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric); + gboolean (*ip6_route_exists) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric); gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *); + gboolean (*check_support_user_ipv6ll) (NMPlatform *); } NMPlatformClass; /* NMPlatform signals @@ -524,6 +505,9 @@ gboolean nm_platform_link_is_up (int ifindex); gboolean nm_platform_link_is_connected (int ifindex); gboolean nm_platform_link_uses_arp (int ifindex); +gboolean nm_platform_link_get_user_ipv6ll_enabled (int ifindex); +gboolean nm_platform_link_set_user_ipv6ll_enabled (int ifindex, gboolean enabled); + gconstpointer nm_platform_link_get_address (int ifindex, size_t *length); gboolean nm_platform_link_set_address (int ifindex, const void *address, size_t length); guint32 nm_platform_link_get_mtu (int ifindex); @@ -557,7 +541,7 @@ gboolean nm_platform_vxlan_get_properties (int ifindex, NMPlatformVxlanPropertie gboolean nm_platform_gre_get_properties (int ifindex, NMPlatformGreProperties *props); gboolean nm_platform_wifi_get_capabilities (int ifindex, NMDeviceWifiCapabilities *caps); -gboolean nm_platform_wifi_get_bssid (int ifindex, struct ether_addr *bssid); +gboolean nm_platform_wifi_get_bssid (int ifindex, guint8 *bssid); GByteArray *nm_platform_wifi_get_ssid (int ifindex); guint32 nm_platform_wifi_get_frequency (int ifindex); int nm_platform_wifi_get_quality (int ifindex); @@ -569,7 +553,7 @@ void nm_platform_wifi_indicate_addressing_running (int ifindex, gboolean guint32 nm_platform_mesh_get_channel (int ifindex); gboolean nm_platform_mesh_set_channel (int ifindex, guint32 channel); -gboolean nm_platform_mesh_set_ssid (int ifindex, const GByteArray *ssid); +gboolean nm_platform_mesh_set_ssid (int ifindex, const guint8 *ssid, gsize len); GArray *nm_platform_ip4_address_get_all (int ifindex); GArray *nm_platform_ip6_address_get_all (int ifindex); @@ -580,27 +564,28 @@ gboolean nm_platform_ip4_address_add (int ifindex, gboolean nm_platform_ip6_address_add (int ifindex, struct in6_addr address, struct in6_addr peer_address, int plen, guint32 lifetime, guint32 preferred_lft, guint flags); -gboolean nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen); +gboolean nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen, in_addr_t peer_address); gboolean nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen); gboolean nm_platform_ip4_address_exists (int ifindex, in_addr_t address, int plen); gboolean nm_platform_ip6_address_exists (int ifindex, struct in6_addr address, int plen); -gboolean nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses); +gboolean nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses, guint32 device_route_metric); gboolean nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses); gboolean nm_platform_address_flush (int ifindex); -GArray *nm_platform_ip4_route_get_all (int ifindex, gboolean include_default); -GArray *nm_platform_ip6_route_get_all (int ifindex, gboolean include_default); -gboolean nm_platform_route_set_metric (int ifindex, int metric); -gboolean nm_platform_ip4_route_add (int ifindex, NMPlatformSource source, +gboolean nm_platform_ip4_check_reinstall_device_route (int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric); + +GArray *nm_platform_ip4_route_get_all (int ifindex, NMPlatformGetRouteMode mode); +GArray *nm_platform_ip6_route_get_all (int ifindex, NMPlatformGetRouteMode mode); +gboolean nm_platform_ip4_route_add (int ifindex, NMIPConfigSource source, in_addr_t network, int plen, in_addr_t gateway, - int metric, int mss); -gboolean nm_platform_ip6_route_add (int ifindex, NMPlatformSource source, + guint32 pref_src, guint32 metric, guint32 mss); +gboolean nm_platform_ip6_route_add (int ifindex, NMIPConfigSource source, struct in6_addr network, int plen, struct in6_addr gateway, - int metric, int mss); -gboolean nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, int metric); -gboolean nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, int metric); -gboolean nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, int metric); -gboolean nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, int metric); + guint32 metric, guint32 mss); +gboolean nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, guint32 metric); +gboolean nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, guint32 metric); +gboolean nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, guint32 metric); +gboolean nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, guint32 metric); gboolean nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes); gboolean nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes); gboolean nm_platform_route_flush (int ifindex); @@ -619,16 +604,10 @@ int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6R gboolean nm_platform_check_support_libnl_extended_ifa_flags (void); gboolean nm_platform_check_support_kernel_extended_ifa_flags (void); +gboolean nm_platform_check_support_user_ipv6ll (void); void nm_platform_addr_flags2str (int flags, char *buf, size_t size); int nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatformIPAddress *b); -#define auto_g_free __attribute__((cleanup(put_g_free))) -static void __attribute__((unused)) -put_g_free (void *ptr) -{ - g_clear_pointer ((gpointer *) ptr, g_free); -} - -#endif /* NM_PLATFORM_H */ +#endif /* __NETWORKMANAGER_PLATFORM_H__ */ diff --git a/src/platform/tests/Makefile.am b/src/platform/tests/Makefile.am index 9b10ea7b2..b06e25e0c 100644 --- a/src/platform/tests/Makefile.am +++ b/src/platform/tests/Makefile.am @@ -1,14 +1,13 @@ AM_CPPFLAGS = \ -I${top_srcdir} \ -I${top_srcdir}/include \ - -I${top_builddir}/include \ -I${top_srcdir}/src \ -I${top_builddir}/src \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/libnm-util \ - -I${top_builddir}/libnm-util \ + -I${top_srcdir}/libnm-core \ + -I${top_builddir}/libnm-core \ -I${srcdir}/.. \ -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNETWORKMANAGER_COMPILATION \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ $(GLIB_CFLAGS) \ $(GUDEV_CFLAGS) \ @@ -111,6 +110,6 @@ test_cleanup_linux_CPPFLAGS = \ test_cleanup_linux_LDADD = $(PLATFORM_LDADD) #@VALGRIND_RULES@ -TESTS = test-link-fake test-address-fake test-route-fake test-cleanup-fake test-link-linux test-address-linux test-route-linux test-cleanup-linux +TESTS = test-link-fake test-address-fake test-route-fake test-cleanup-fake test-address-linux test-route-linux test-cleanup-linux diff --git a/src/platform/tests/Makefile.in b/src/platform/tests/Makefile.in index 6b03e315a..052636abe 100644 --- a/src/platform/tests/Makefile.in +++ b/src/platform/tests/Makefile.in @@ -86,8 +86,8 @@ noinst_PROGRAMS = dump$(EXEEXT) monitor$(EXEEXT) platform$(EXEEXT) \ test-cleanup-fake$(EXEEXT) test-cleanup-linux$(EXEEXT) TESTS = test-link-fake$(EXEEXT) test-address-fake$(EXEEXT) \ test-route-fake$(EXEEXT) test-cleanup-fake$(EXEEXT) \ - test-link-linux$(EXEEXT) test-address-linux$(EXEEXT) \ - test-route-linux$(EXEEXT) test-cleanup-linux$(EXEEXT) + test-address-linux$(EXEEXT) test-route-linux$(EXEEXT) \ + test-cleanup-linux$(EXEEXT) subdir = src/platform/tests DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/build-aux/depcomp @@ -299,6 +299,8 @@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@ +BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ @@ -422,6 +424,7 @@ NEWT_CFLAGS = @NEWT_CFLAGS@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ +NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -441,6 +444,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ @@ -467,7 +471,7 @@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ -UDEV_BASE_DIR = @UDEV_BASE_DIR@ +UDEV_DIR = @UDEV_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ @@ -547,10 +551,10 @@ with_netconfig = @with_netconfig@ with_resolvconf = @with_resolvconf@ with_valgrind = @with_valgrind@ AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/include \ - -I${top_builddir}/include -I${top_srcdir}/src \ - -I${top_builddir}/src -I${top_srcdir}/src/logging \ - -I${top_srcdir}/libnm-util -I${top_builddir}/libnm-util \ + -I${top_srcdir}/src -I${top_builddir}/src \ + -I${top_srcdir}/libnm-core -I${top_builddir}/libnm-core \ -I${srcdir}/.. -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNETWORKMANAGER_COMPILATION \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(GLIB_CFLAGS) \ $(GUDEV_CFLAGS) $(LIBNL_CFLAGS) $(am__append_1) PLATFORM_SOURCES = \ diff --git a/src/platform/tests/dump.c b/src/platform/tests/dump.c index e97ef138c..3bb61da41 100644 --- a/src/platform/tests/dump.c +++ b/src/platform/tests/dump.c @@ -1,3 +1,5 @@ +#include "config.h" + #include <stdio.h> #include <stdlib.h> #include <arpa/inet.h> @@ -83,8 +85,8 @@ dump_interface (NMPlatformLink *link) g_array_unref (ip4_addresses); g_array_unref (ip6_addresses); - ip4_routes = nm_platform_ip4_route_get_all (link->ifindex, TRUE); - ip6_routes = nm_platform_ip6_route_get_all (link->ifindex, TRUE); + ip4_routes = nm_platform_ip4_route_get_all (link->ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL); + ip6_routes = nm_platform_ip6_route_get_all (link->ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL); g_assert (ip4_routes); g_assert (ip6_routes); diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c index d56cc2bf8..9aff10476 100644 --- a/src/platform/tests/monitor.c +++ b/src/platform/tests/monitor.c @@ -1,3 +1,5 @@ +#include "config.h" + #include <stdlib.h> #include <syslog.h> diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c index ea8bd0e3b..eea6610d3 100644 --- a/src/platform/tests/platform.c +++ b/src/platform/tests/platform.c @@ -18,12 +18,15 @@ * Copyright (C) 2013 Red Hat, Inc. */ +#include "config.h" + #include <stdlib.h> #include <stdio.h> #include <string.h> #include <arpa/inet.h> #include <netlink/route/addr.h> +#include "gsystem-local-alloc.h" #include "nm-platform.h" #include "nm-linux-platform.h" #include "nm-fake-platform.h" @@ -47,7 +50,7 @@ do_sysctl_set (char **argv) static gboolean do_sysctl_get (char **argv) { - auto_g_free char *value = nm_platform_sysctl_get (argv[0]); + gs_free char *value = nm_platform_sysctl_get (argv[0]); printf ("%s\n", value); @@ -281,7 +284,7 @@ do_master_get_option (char **argv) { int ifindex = parse_ifindex (*argv++); const char *option = *argv++; - auto_g_free char *value = nm_platform_master_get_option (ifindex, option); + gs_free char *value = nm_platform_master_get_option (ifindex, option); printf ("%s\n", value); @@ -303,7 +306,7 @@ do_slave_get_option (char **argv) { int ifindex = parse_ifindex (*argv++); const char *option = *argv++; - auto_g_free char *value = nm_platform_slave_get_option (ifindex, option); + gs_free char *value = nm_platform_slave_get_option (ifindex, option); printf ("%s\n", value); @@ -532,6 +535,9 @@ parse_ip_address (int family, char *str, gpointer address, int *plen) { char *endptr; + if (plen) + *plen = 0; + if (plen) { char *ptr = strchr (str, '/'); if (ptr) { @@ -594,7 +600,7 @@ do_ip6_address_add (char **argv) return FALSE; } -#define ADDR_CMD_FULL(v, cmdname, print) \ +#define ADDR_CMD_FULL(v, cmdname, print, ...) \ static gboolean \ do_##v##_address_##cmdname (char **argv) \ { \ @@ -602,7 +608,7 @@ do_ip6_address_add (char **argv) v##_t address; \ int plen; \ if (ifindex && parse_##v##_address (*argv++, &address, &plen)) { \ - gboolean value = nm_platform_##v##_address_##cmdname (ifindex, address, plen); \ + gboolean value = nm_platform_##v##_address_##cmdname (ifindex, address, plen, ##__VA_ARGS__); \ if (print) { \ print_boolean (value); \ return TRUE; \ @@ -611,7 +617,7 @@ do_ip6_address_add (char **argv) } else \ return FALSE; \ } -#define ADDR_CMD(cmdname) ADDR_CMD_FULL (ip4, cmdname, FALSE) ADDR_CMD_FULL (ip6, cmdname, FALSE) +#define ADDR_CMD(cmdname) ADDR_CMD_FULL (ip4, cmdname, FALSE, 0) ADDR_CMD_FULL (ip6, cmdname, FALSE) #define ADDR_CMD_PRINT(cmdname) ADDR_CMD_FULL (ip4, cmdname, TRUE) ADDR_CMD_FULL (ip6, cmdname, TRUE) ADDR_CMD (delete) @@ -627,7 +633,7 @@ do_ip4_route_get_all (char **argv) int i; if (ifindex) { - routes = nm_platform_ip4_route_get_all (ifindex, TRUE); + routes = nm_platform_ip4_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL); for (i = 0; i < routes->len; i++) { route = &g_array_index (routes, NMPlatformIP4Route, i); inet_ntop (AF_INET, &route->network, networkstr, sizeof (networkstr)); @@ -651,7 +657,7 @@ do_ip6_route_get_all (char **argv) int i; if (ifindex) { - routes = nm_platform_ip6_route_get_all (ifindex, TRUE); + routes = nm_platform_ip6_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL); for (i = 0; i < routes->len; i++) { route = &g_array_index (routes, NMPlatformIP6Route, i); inet_ntop (AF_INET6, &route->network, networkstr, sizeof (networkstr)); @@ -677,8 +683,8 @@ do_ip4_route_add (char **argv) metric = strtol (*argv++, NULL, 10); mss = strtol (*argv++, NULL, 10); - return nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, - network, plen, gateway, + return nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, + network, plen, gateway, 0, metric, mss); } @@ -693,7 +699,7 @@ do_ip6_route_add (char **argv) parse_ip6_address (*argv++, &gateway, NULL); metric = strtol (*argv++, NULL, 10); mss = strtol (*argv++, NULL, 10); - return nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, + return nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, metric, mss); } diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c index 3fef53752..3ef13b8ec 100644 --- a/src/platform/tests/test-address.c +++ b/src/platform/tests/test-address.c @@ -1,3 +1,5 @@ +#include "config.h" + #include "test-common.h" #define DEVICE_NAME "nm-test-device" @@ -91,13 +93,13 @@ test_ip4_address (void) g_array_unref (addresses); /* Remove address */ - g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN)); + g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN, 0)); no_error (); g_assert (!nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN)); accept_signal (address_removed); /* Remove address again */ - g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN)); + g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN, 0)); no_error (); free_signal (address_added); @@ -196,7 +198,7 @@ test_ip4_address_external (void) g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN)); accept_signal (address_added); /*run_command ("ip address delete %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME); - g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN)); + g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN, 0)); no_error (); g_assert (!nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN)); accept_signal (address_removed);*/ diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c index e60d82f0e..afbb438cc 100644 --- a/src/platform/tests/test-cleanup.c +++ b/src/platform/tests/test-cleanup.c @@ -1,9 +1,11 @@ +#include "config.h" + #include "test-common.h" #define DEVICE_NAME "nm-test-device" static void -test_cleanup_internal () +test_cleanup_internal (void) { SignalData *link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME); int ifindex; @@ -43,17 +45,17 @@ test_cleanup_internal () /* Add routes and addresses */ g_assert (nm_platform_ip4_address_add (ifindex, addr4, 0, plen4, lifetime, preferred, NULL)); g_assert (nm_platform_ip6_address_add (ifindex, addr6, in6addr_any, plen6, lifetime, preferred, flags)); - g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway4, 32, INADDR_ANY, metric, mss)); - g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network4, plen4, gateway4, metric, mss)); - g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, 0, 0, gateway4, metric, mss)); - g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway6, 128, in6addr_any, metric, mss)); - g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network6, plen6, gateway6, metric, mss)); - g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, in6addr_any, 0, gateway6, metric, mss)); + g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, gateway4, 32, INADDR_ANY, 0, metric, mss)); + g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network4, plen4, gateway4, 0, metric, mss)); + g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway4, 0, metric, mss)); + g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, gateway6, 128, in6addr_any, metric, mss)); + g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network6, plen6, gateway6, metric, mss)); + g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway6, metric, mss)); addresses4 = nm_platform_ip4_address_get_all (ifindex); addresses6 = nm_platform_ip6_address_get_all (ifindex); - routes4 = nm_platform_ip4_route_get_all (ifindex, TRUE); - routes6 = nm_platform_ip6_route_get_all (ifindex, TRUE); + routes4 = nm_platform_ip4_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL); + routes6 = nm_platform_ip6_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL); g_assert_cmpint (addresses4->len, ==, 1); g_assert_cmpint (addresses6->len, ==, 1); @@ -70,8 +72,8 @@ test_cleanup_internal () addresses4 = nm_platform_ip4_address_get_all (ifindex); addresses6 = nm_platform_ip6_address_get_all (ifindex); - routes4 = nm_platform_ip4_route_get_all (ifindex, TRUE); - routes6 = nm_platform_ip6_route_get_all (ifindex, TRUE); + routes4 = nm_platform_ip4_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL); + routes6 = nm_platform_ip6_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL); g_assert_cmpint (addresses4->len, ==, 0); g_assert_cmpint (addresses6->len, ==, 0); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 59a770c63..ab40f6524 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1,3 +1,5 @@ +#include "config.h" + #include "test-common.h" #include "nm-test-utils.h" diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index a3f757c2e..8bd2ef44d 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -1,3 +1,5 @@ +#include "config.h" + #include "test-common.h" #include "nm-test-utils.h" @@ -130,6 +132,7 @@ software_add (NMLinkType link_type, const char *name) default: g_error ("Link type %d unhandled.", link_type); } + g_assert_not_reached (); } static void @@ -188,12 +191,12 @@ test_slave (int master, int type, SignalData *master_changed) /* Older team versions (e.g. Fedora 17) have a bug that team master stays * IFF_LOWER_UP even if its slave is down. Double check it with iproute2 and if * `ip link` also claims master to be up, accept it. */ - char *stdout = NULL; + char *stdout_str = NULL; - nmtst_spawn_sync (NULL, &stdout, NULL, 0, "/sbin/ip", "link", "show", "dev", nm_platform_link_get_name (master)); + nmtst_spawn_sync (NULL, &stdout_str, NULL, 0, "/sbin/ip", "link", "show", "dev", nm_platform_link_get_name (master)); - g_assert (strstr (stdout, "LOWER_UP")); - g_free (stdout); + g_assert (strstr (stdout_str, "LOWER_UP")); + g_free (stdout_str); } else g_assert_not_reached (); } @@ -379,7 +382,7 @@ test_team (void) } static void -test_vlan () +test_vlan (void) { test_software (NM_LINK_TYPE_VLAN, "vlan"); } diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index d45730ac5..2c70b412b 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -1,3 +1,5 @@ +#include "config.h" + #include "test-common.h" #include "nm-test-utils.h" @@ -48,7 +50,7 @@ ip6_route_callback (NMPlatform *platform, int ifindex, NMPlatformIP6Route *recei } static void -test_ip4_route () +test_ip4_route (void) { int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME); SignalData *route_added = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_route_callback); @@ -59,63 +61,64 @@ test_ip4_route () in_addr_t network; int plen = 24; in_addr_t gateway; - int metric = 20; + /* Choose a high metric so that we hopefully don't conflict. */ + int metric = 22986; int mss = 1000; inet_pton (AF_INET, "192.0.3.0", &network); inet_pton (AF_INET, "198.51.100.1", &gateway); /* Add route to gateway */ - g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway, 32, INADDR_ANY, metric, mss)); + g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 32, INADDR_ANY, 0, metric, mss)); no_error (); accept_signal (route_added); /* Add route */ g_assert (!nm_platform_ip4_route_exists (ifindex, network, plen, metric)); no_error (); - g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss)); + g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss)); no_error (); g_assert (nm_platform_ip4_route_exists (ifindex, network, plen, metric)); no_error (); accept_signal (route_added); /* Add route again */ - g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss)); + g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss)); no_error (); accept_signal (route_changed); /* Add default route */ g_assert (!nm_platform_ip4_route_exists (ifindex, 0, 0, metric)); no_error (); - g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, 0, 0, gateway, metric, mss)); + g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss)); no_error (); g_assert (nm_platform_ip4_route_exists (ifindex, 0, 0, metric)); no_error (); accept_signal (route_added); /* Add default route again */ - g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, 0, 0, gateway, metric, mss)); + g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss)); no_error (); accept_signal (route_changed); /* Test route listing */ - routes = nm_platform_ip4_route_get_all (ifindex, TRUE); + routes = nm_platform_ip4_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL); memset (rts, 0, sizeof (rts)); - rts[0].source = NM_PLATFORM_SOURCE_USER; + rts[0].source = NM_IP_CONFIG_SOURCE_USER; rts[0].network = gateway; rts[0].plen = 32; rts[0].ifindex = ifindex; rts[0].gateway = INADDR_ANY; rts[0].metric = metric; rts[0].mss = mss; - rts[1].source = NM_PLATFORM_SOURCE_USER; + rts[1].source = NM_IP_CONFIG_SOURCE_USER; rts[1].network = network; rts[1].plen = plen; rts[1].ifindex = ifindex; rts[1].gateway = gateway; rts[1].metric = metric; rts[1].mss = mss; - rts[2].source = NM_PLATFORM_SOURCE_USER; + rts[2].source = NM_IP_CONFIG_SOURCE_USER; rts[2].network = 0; rts[2].plen = 0; rts[2].ifindex = ifindex; @@ -143,7 +146,7 @@ test_ip4_route () } static void -test_ip6_route () +test_ip6_route (void) { int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME); SignalData *route_added = add_signal (NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip6_route_callback); @@ -154,63 +157,64 @@ test_ip6_route () struct in6_addr network; int plen = 64; struct in6_addr gateway; - int metric = 20; + /* Choose a high metric so that we hopefully don't conflict. */ + int metric = 22987; int mss = 1000; inet_pton (AF_INET6, "2001:db8:a:b:0:0:0:0", &network); inet_pton (AF_INET6, "2001:db8:c:d:1:2:3:4", &gateway); /* Add route to gateway */ - g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway, 128, in6addr_any, metric, mss)); + g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 128, in6addr_any, metric, mss)); no_error (); accept_signal (route_added); /* Add route */ g_assert (!nm_platform_ip6_route_exists (ifindex, network, plen, metric)); no_error (); - g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss)); + g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, metric, mss)); no_error (); g_assert (nm_platform_ip6_route_exists (ifindex, network, plen, metric)); no_error (); accept_signal (route_added); /* Add route again */ - g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss)); + g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, metric, mss)); no_error (); accept_signal (route_changed); /* Add default route */ g_assert (!nm_platform_ip6_route_exists (ifindex, in6addr_any, 0, metric)); no_error (); - g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, in6addr_any, 0, gateway, metric, mss)); + g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, metric, mss)); no_error (); g_assert (nm_platform_ip6_route_exists (ifindex, in6addr_any, 0, metric)); no_error (); accept_signal (route_added); /* Add default route again */ - g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, in6addr_any, 0, gateway, metric, mss)); + g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, metric, mss)); no_error (); accept_signal (route_changed); /* Test route listing */ - routes = nm_platform_ip6_route_get_all (ifindex, TRUE); + routes = nm_platform_ip6_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL); memset (rts, 0, sizeof (rts)); - rts[0].source = NM_PLATFORM_SOURCE_USER; + rts[0].source = NM_IP_CONFIG_SOURCE_USER; rts[0].network = gateway; rts[0].plen = 128; rts[0].ifindex = ifindex; rts[0].gateway = in6addr_any; rts[0].metric = metric; rts[0].mss = mss; - rts[1].source = NM_PLATFORM_SOURCE_USER; + rts[1].source = NM_IP_CONFIG_SOURCE_USER; rts[1].network = network; rts[1].plen = plen; rts[1].ifindex = ifindex; rts[1].gateway = gateway; rts[1].metric = metric; rts[1].mss = mss; - rts[2].source = NM_PLATFORM_SOURCE_USER; + rts[2].source = NM_IP_CONFIG_SOURCE_USER; rts[2].network = in6addr_any; rts[2].plen = 0; rts[2].ifindex = ifindex; diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c index 25ebd1b3c..752da926a 100644 --- a/src/platform/wifi/wifi-utils-nl80211.c +++ b/src/platform/wifi/wifi-utils-nl80211.c @@ -20,7 +20,8 @@ * Copyright (C) 2011 Intel Corporation. All rights reserved. */ -#include <config.h> +#include "config.h" + #include <errno.h> #include <string.h> #include <sys/ioctl.h> @@ -442,7 +443,7 @@ wifi_nl80211_get_ssid (WifiData *data) } static gboolean -wifi_nl80211_get_bssid (WifiData *data, struct ether_addr *out_bssid) +wifi_nl80211_get_bssid (WifiData *data, guint8 *out_bssid) { WifiDataNl80211 *nl80211 = (WifiDataNl80211 *) data; struct nl80211_bss_info bss_info; @@ -679,11 +680,20 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg) static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = { [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 }, [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG }, +#ifdef NL80211_FREQUENCY_ATTR_NO_IR + [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG }, +#else [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG }, [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, +#endif [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG }, [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 }, }; +#ifdef NL80211_FREQUENCY_ATTR_NO_IR + G_STATIC_ASSERT (NL80211_FREQUENCY_ATTR_PASSIVE_SCAN == NL80211_FREQUENCY_ATTR_NO_IR && NL80211_FREQUENCY_ATTR_NO_IBSS == NL80211_FREQUENCY_ATTR_NO_IR); +#else + G_STATIC_ASSERT (NL80211_FREQUENCY_ATTR_PASSIVE_SCAN != NL80211_FREQUENCY_ATTR_NO_IBSS); +#endif if (nla_parse (tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen (gnlh, 0), NULL) < 0) @@ -924,48 +934,3 @@ error: return NULL; } -gboolean -wifi_nl80211_is_wifi (const char *iface) -{ - struct nl_sock *nl_sock; - struct nl_cb *nl_cb = NULL; - struct nl_msg *msg = NULL; - int id, ifindex; - struct nl80211_iface_info iface_info = { - .mode = NM_802_11_MODE_UNKNOWN, - }; - gboolean is_wifi = FALSE; - - nl_sock = nl_socket_alloc (); - if (nl_sock == NULL) - return FALSE; - - if (genl_connect (nl_sock)) - goto error; - - ifindex = nm_platform_link_get_ifindex (iface); - if (ifindex < 0) - goto error; - - id = genl_ctrl_resolve (nl_sock, "nl80211"); - if (id < 0) - goto error; - - nl_cb = nl_cb_alloc (NL_CB_DEFAULT); - if (nl_cb) { - msg = _nl80211_alloc_msg (id, ifindex, -1, NL80211_CMD_GET_INTERFACE, 0); - if (_nl80211_send_and_recv (nl_sock, - nl_cb, - msg, - nl80211_iface_info_handler, - &iface_info) >= 0) - is_wifi = (iface_info.mode != NM_802_11_MODE_UNKNOWN); - } - - error: - if (nl_cb) - nl_cb_put (nl_cb); - nl_socket_free (nl_sock); - return is_wifi; -} - diff --git a/src/platform/wifi/wifi-utils-nl80211.h b/src/platform/wifi/wifi-utils-nl80211.h index 2a7fe874a..b3e8c8976 100644 --- a/src/platform/wifi/wifi-utils-nl80211.h +++ b/src/platform/wifi/wifi-utils-nl80211.h @@ -18,13 +18,11 @@ * Copyright (C) 2011 Intel Corporation. All rights reserved. */ -#ifndef WIFI_UTILS_NL80211_H -#define WIFI_UTILS_NL80211_H +#ifndef __WIFI_UTILS_NL80211_H__ +#define __WIFI_UTILS_NL80211_H__ #include "wifi-utils.h" WifiData *wifi_nl80211_init (const char *iface, int ifindex); -gboolean wifi_nl80211_is_wifi (const char *iface); - -#endif /* WIFI_UTILS_NL80211_H */ +#endif /* __WIFI_UTILS_NL80211_H__ */ diff --git a/src/platform/wifi/wifi-utils-private.h b/src/platform/wifi/wifi-utils-private.h index e7601752d..aaedd5b7a 100644 --- a/src/platform/wifi/wifi-utils-private.h +++ b/src/platform/wifi/wifi-utils-private.h @@ -18,12 +18,12 @@ * Copyright (C) 2011 Red Hat, Inc. */ -#ifndef WIFI_UTILS_PRIVATE_H -#define WIFI_UTILS_PRIVATE_H +#ifndef __WIFI_UTILS_PRIVATE_H__ +#define __WIFI_UTILS_PRIVATE_H__ #include <glib.h> -#include "NetworkManager.h" +#include "nm-dbus-interface.h" #include "wifi-utils.h" struct WifiData { @@ -47,7 +47,7 @@ struct WifiData { /* Return current bitrate in Kbps */ guint32 (*get_rate) (WifiData *data); - gboolean (*get_bssid) (WifiData *data, struct ether_addr *out_bssid); + gboolean (*get_bssid) (WifiData *data, guint8 *out_bssid); /* Return a signal strength percentage 0 - 100% for the current BSSID; * return -1 on errors or if not associated. @@ -66,7 +66,7 @@ struct WifiData { gboolean (*set_mesh_channel) (WifiData *data, guint32 channel); /* ssid == NULL means "auto SSID" */ - gboolean (*set_mesh_ssid) (WifiData *data, const GByteArray *ssid); + gboolean (*set_mesh_ssid) (WifiData *data, const guint8 *ssid, gsize len); gboolean (*indicate_addressing_running) (WifiData *data, gboolean running); }; @@ -74,4 +74,4 @@ struct WifiData { gpointer wifi_data_new (const char *iface, int ifindex, gsize len); void wifi_data_free (WifiData *data); -#endif /* WIFI_UTILS_PRIVATE_H */ +#endif /* __WIFI_UTILS_PRIVATE_H__ */ diff --git a/src/platform/wifi/wifi-utils-wext.c b/src/platform/wifi/wifi-utils-wext.c index cc94b69a3..e0331de7c 100644 --- a/src/platform/wifi/wifi-utils-wext.c +++ b/src/platform/wifi/wifi-utils-wext.c @@ -19,7 +19,8 @@ * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include <config.h> +#include "config.h" + #include <errno.h> #include <string.h> #include <sys/ioctl.h> @@ -41,7 +42,6 @@ #include <sys/types.h> #include <linux/types.h> #include <sys/socket.h> -#include <linux/if.h> #include <linux/wireless.h> @@ -230,7 +230,7 @@ wifi_wext_get_ssid (WifiData *data) } static gboolean -wifi_wext_get_bssid (WifiData *data, struct ether_addr *out_bssid) +wifi_wext_get_bssid (WifiData *data, guint8 *out_bssid) { WifiDataWext *wext = (WifiDataWext *) data; struct iwreq wrq; @@ -243,7 +243,7 @@ wifi_wext_get_bssid (WifiData *data, struct ether_addr *out_bssid) wext->parent.iface, strerror (errno)); return FALSE; } - memcpy (out_bssid->ether_addr_octet, &(wrq.u.ap_addr.sa_data), ETH_ALEN); + memcpy (out_bssid, &(wrq.u.ap_addr.sa_data), ETH_ALEN); return TRUE; } @@ -421,18 +421,15 @@ wifi_wext_set_mesh_channel (WifiData *data, guint32 channel) } static gboolean -wifi_wext_set_mesh_ssid (WifiData *data, const GByteArray *ssid) +wifi_wext_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len) { WifiDataWext *wext = (WifiDataWext *) data; struct iwreq wrq; - guint32 len = 0; char buf[IW_ESSID_MAX_SIZE + 1]; memset (buf, 0, sizeof (buf)); - if (ssid) { - len = ssid->len; - memcpy (buf, ssid->data, MIN (sizeof (buf) - 1, len)); - } + memcpy (buf, ssid, MIN (sizeof (buf) - 1, len)); + wrq.u.essid.pointer = (caddr_t) buf; wrq.u.essid.length = len; wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */ @@ -445,7 +442,7 @@ wifi_wext_set_mesh_ssid (WifiData *data, const GByteArray *ssid) nm_log_err (LOGD_HW | LOGD_WIFI | LOGD_OLPC, "(%s): error setting SSID to '%s': %s", wext->parent.iface, - ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(null)", + ssid ? nm_utils_escape_ssid (ssid, len) : "(null)", strerror (errno)); } diff --git a/src/platform/wifi/wifi-utils-wext.h b/src/platform/wifi/wifi-utils-wext.h index 96ad74eb4..e168fe28a 100644 --- a/src/platform/wifi/wifi-utils-wext.h +++ b/src/platform/wifi/wifi-utils-wext.h @@ -18,8 +18,8 @@ * Copyright (C) 2011 Red Hat, Inc. */ -#ifndef WIFI_UTILS_WEXT_H -#define WIFI_UTILS_WEXT_H +#ifndef __WIFI_UTILS_WEXT_H__ +#define __WIFI_UTILS_WEXT_H__ #include "wifi-utils.h" @@ -27,4 +27,4 @@ WifiData *wifi_wext_init (const char *iface, int ifindex, gboolean check_scan); gboolean wifi_wext_is_wifi (const char *iface); -#endif /* WIFI_UTILS_WEXT_H */ +#endif /* __WIFI_UTILS_WEXT_H__ */ diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c index ff4802752..daef881bf 100644 --- a/src/platform/wifi/wifi-utils.c +++ b/src/platform/wifi/wifi-utils.c @@ -19,7 +19,8 @@ * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include <config.h> +#include "config.h" + #include <sys/stat.h> #include <stdio.h> #include <string.h> @@ -120,12 +121,12 @@ wifi_utils_get_ssid (WifiData *data) } gboolean -wifi_utils_get_bssid (WifiData *data, struct ether_addr *out_bssid) +wifi_utils_get_bssid (WifiData *data, guint8 *out_bssid) { g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (out_bssid != NULL, FALSE); - memset (out_bssid, 0, sizeof (*out_bssid)); + memset (out_bssid, 0, ETH_ALEN); return data->get_bssid (data, out_bssid); } @@ -161,13 +162,20 @@ wifi_utils_deinit (WifiData *data) } gboolean -wifi_utils_is_wifi (const char *iface, const char *sysfs_path) +wifi_utils_is_wifi (const char *iface, const char *sysfs_path, const char *devtype) { char phy80211_path[255]; struct stat s; g_return_val_if_fail (iface != NULL, FALSE); + if (g_strcmp0 (devtype, "wlan") == 0) { + /* All Wi-Fi drivers should set DEVTYPE=wlan. Since the kernel's + * cfg80211/nl80211 stack does, this check should match any nl80211 + * capable driver (including mac82011-based ones). */ + return TRUE; + } + if (sysfs_path) { /* Check for nl80211 sysfs paths */ g_snprintf (phy80211_path, sizeof (phy80211_path), "%s/phy80211", sysfs_path); @@ -175,9 +183,6 @@ wifi_utils_is_wifi (const char *iface, const char *sysfs_path) return TRUE; } - if (wifi_nl80211_is_wifi (iface)) - return TRUE; - #if HAVE_WEXT if (wifi_wext_is_wifi (iface)) return TRUE; @@ -207,11 +212,11 @@ wifi_utils_set_mesh_channel (WifiData *data, guint32 channel) } gboolean -wifi_utils_set_mesh_ssid (WifiData *data, const GByteArray *ssid) +wifi_utils_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len) { g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (data->set_mesh_ssid != NULL, FALSE); - return data->set_mesh_ssid (data, ssid); + return data->set_mesh_ssid (data, ssid, len); } gboolean diff --git a/src/platform/wifi/wifi-utils.h b/src/platform/wifi/wifi-utils.h index 455e075f5..f1b57aced 100644 --- a/src/platform/wifi/wifi-utils.h +++ b/src/platform/wifi/wifi-utils.h @@ -19,17 +19,17 @@ * Copyright (C) 2006 - 2008 Novell, Inc. */ -#ifndef WIFI_UTILS_H -#define WIFI_UTILS_H +#ifndef __WIFI_UTILS_H__ +#define __WIFI_UTILS_H__ #include <net/ethernet.h> #include <glib.h> -#include "NetworkManager.h" +#include "nm-dbus-interface.h" typedef struct WifiData WifiData; -gboolean wifi_utils_is_wifi (const char *iface, const char *sysfs_path); +gboolean wifi_utils_is_wifi (const char *iface, const char *sysfs_path, const char *devtype); WifiData *wifi_utils_init (const char *iface, int ifindex, gboolean check_scan); @@ -50,8 +50,8 @@ guint32 wifi_utils_find_freq (WifiData *data, const guint32 *freqs); /* Caller must free returned byte array */ GByteArray *wifi_utils_get_ssid (WifiData *data); -/* Caller must free returned byte array */ -gboolean wifi_utils_get_bssid (WifiData *data, struct ether_addr *out_bssid); +/* out_bssid must be ETH_ALEN bytes */ +gboolean wifi_utils_get_bssid (WifiData *data, guint8 *out_bssid); /* Returns current bitrate in Kbps */ guint32 wifi_utils_get_rate (WifiData *data); @@ -71,6 +71,6 @@ guint32 wifi_utils_get_mesh_channel (WifiData *data); gboolean wifi_utils_set_mesh_channel (WifiData *data, guint32 channel); -gboolean wifi_utils_set_mesh_ssid (WifiData *data, const GByteArray *ssid); +gboolean wifi_utils_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len); -#endif /* WIFI_UTILS_H */ +#endif /* __WIFI_UTILS_H__ */ |