diff options
| author | Michael Biebl <biebl@debian.org> | 2016-01-20 16:26:51 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2016-01-20 16:26:51 +0100 |
| commit | 494f296a3baab08522617b24b1f126d8f9a17502 (patch) | |
| tree | c8ef32fb0dd1c4ff35a0b38e787abb58692de0cd /src/platform/nm-platform.c | |
| parent | 54f6333410ffd570e62717d9e77c5c987175e397 (diff) | |
Imported Upstream version 1.1.90 upstream/1.1.90
Diffstat (limited to 'src/platform/nm-platform.c')
| -rw-r--r-- | src/platform/nm-platform.c | 1731 |
1 files changed, 1409 insertions, 322 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 9948ac8b..3bb44e1a 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -28,20 +28,27 @@ #include <string.h> #include <netlink/route/addr.h> #include <netlink/route/rtnl.h> +#include <linux/ip.h> +#include <linux/if_tun.h> +#include <linux/if_tunnel.h> -#include "gsystem-local-alloc.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-platform.h" #include "nm-platform-utils.h" +#include "nmp-object.h" #include "NetworkManagerUtils.h" -#include "nm-logging.h" +#include "nm-default.h" #include "nm-enum-types.h" #include "nm-core-internal.h" #define ADDRESS_LIFETIME_PADDING 5 G_STATIC_ASSERT (sizeof ( ((NMPlatformLink *) NULL)->addr.data ) == NM_UTILS_HWADDR_LEN_MAX); +G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Address, address)); +G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP6Address, address)); +G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Route, network)); +G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP6Route, network)); #define _NMLOG_DOMAIN LOGD_PLATFORM #define _NMLOG_PREFIX_NAME "platform" @@ -64,21 +71,15 @@ G_STATIC_ASSERT (sizeof ( ((NMPlatformLink *) NULL)->addr.data ) == NM_UTILS_HWA } \ } G_STMT_END +#define LOG_FMT_IP_TUNNEL "adding %s '%s' parent %u local %s remote %s" + +/*****************************************************************************/ + #define NM_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_PLATFORM, NMPlatformPrivate)) G_DEFINE_TYPE (NMPlatform, nm_platform, G_TYPE_OBJECT) -/* NMPlatform signals */ -enum { - SIGNAL_LINK_CHANGED, - SIGNAL_IP4_ADDRESS_CHANGED, - SIGNAL_IP6_ADDRESS_CHANGED, - SIGNAL_IP4_ROUTE_CHANGED, - SIGNAL_IP6_ROUTE_CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; +static guint signals[_NM_PLATFORM_SIGNAL_ID_LAST] = { 0 }; enum { PROP_0, @@ -92,10 +93,22 @@ typedef struct { /******************************************************************/ +guint +_nm_platform_signal_id_get (NMPlatformSignalIdType signal_type) +{ + nm_assert ( signal_type > 0 + && signal_type != NM_PLATFORM_SIGNAL_ID_NONE + && signal_type < _NM_PLATFORM_SIGNAL_ID_LAST); + + return signals[signal_type]; +} + +/******************************************************************/ + /* Singleton NMPlatform subclass instance and cached class object */ NM_DEFINE_SINGLETON_INSTANCE (NMPlatform); -NM_DEFINE_SINGLETON_WEAK_REF (NMPlatform); +NM_DEFINE_SINGLETON_REGISTER (NMPlatform); /* Just always initialize a @klass instance. NM_PLATFORM_GET_CLASS() * is only a plain read on the self instance, which the compiler @@ -137,9 +150,9 @@ nm_platform_setup (NMPlatform *instance) singleton_instance = instance; - nm_singleton_instance_weak_ref_register (); + nm_singleton_instance_register (); - nm_log_dbg (LOGD_CORE, "setup NMPlatform singleton (%p, %s)", instance, G_OBJECT_TYPE_NAME (instance)); + nm_log_dbg (LOGD_CORE, "setup %s singleton (%p, %s)", "NMPlatform", singleton_instance, G_OBJECT_TYPE_NAME (instance)); } /** @@ -204,22 +217,6 @@ nm_platform_error_to_string (NMPlatformError error) /******************************************************************/ -#define IFA_F_MANAGETEMPADDR_STR "mngtmpaddr" -#define IFA_F_NOPREFIXROUTE_STR "noprefixroute" -gboolean -nm_platform_check_support_libnl_extended_ifa_flags () -{ - static int supported = -1; - - /* support for extended ifa-flags was added together - * with the IFA_F_MANAGETEMPADDR flag. So, check if libnl - * is able to parse this flag. */ - if (supported == -1) - supported = rtnl_addr_str2flags (IFA_F_MANAGETEMPADDR_STR) == IFA_F_MANAGETEMPADDR; - - return supported; -} - gboolean nm_platform_check_support_kernel_extended_ifa_flags (NMPlatform *self) { @@ -284,7 +281,6 @@ nm_platform_sysctl_set (NMPlatform *self, const char *path, const char *value) g_return_val_if_fail (path, FALSE); g_return_val_if_fail (value, FALSE); - g_return_val_if_fail (klass->sysctl_set, FALSE); return klass->sysctl_set (self, path, value); } @@ -336,7 +332,6 @@ nm_platform_sysctl_get (NMPlatform *self, const char *path) _CHECK_SELF (self, klass, NULL); g_return_val_if_fail (path, NULL); - g_return_val_if_fail (klass->sysctl_get, NULL); return klass->sysctl_get (self, path); } @@ -416,8 +411,6 @@ nm_platform_link_get_all (NMPlatform *self) _CHECK_SELF (self, klass, NULL); - g_return_val_if_fail (klass->link_get_all, NULL); - links = klass->link_get_all (self); if (!links || links->len == 0) @@ -427,7 +420,7 @@ nm_platform_link_get_all (NMPlatform *self) for (i = 0; i < links->len; i++) { item = &g_array_index (links, NMPlatformLink, i); - _LOGt ("link-get: %3d: %s", i, nm_platform_link_to_string (item)); + _LOGt ("link-get: %3d: %s", i, nm_platform_link_to_string (item, NULL, 0)); nm_assert (item->ifindex > 0 && !g_hash_table_contains (unseen, GINT_TO_POINTER (item->ifindex))); @@ -450,8 +443,7 @@ nm_platform_link_get_all (NMPlatform *self) if (item->parent != NM_PLATFORM_LINK_OTHER_NETNS) { g_warn_if_fail (item->parent > 0); g_warn_if_fail (item->parent != item->ifindex); - g_warn_if_fail ( !nm_platform_check_support_libnl_link_netnsid () - || g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent))); + g_warn_if_fail (g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent))); } } } @@ -483,7 +475,7 @@ nm_platform_link_get_all (NMPlatform *self) if (item->parent > 0 && g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent))) continue; - _LOGt ("link-get: add %3d -> %3d: %s", i, j, nm_platform_link_to_string (item)); + _LOGt ("link-get: add %3d -> %3d: %s", i, j, nm_platform_link_to_string (item, NULL, 0)); g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex)); g_array_index (result, NMPlatformLink, j++) = *item; @@ -496,7 +488,7 @@ nm_platform_link_get_all (NMPlatform *self) * This can happen for veth pairs where each peer is parent of the other end. */ item = &g_array_index (links, NMPlatformLink, first_idx); - _LOGt ("link-get: add (loop) %3d -> %3d: %s", first_idx, j, nm_platform_link_to_string (item)); + _LOGt ("link-get: add (loop) %3d -> %3d: %s", first_idx, j, nm_platform_link_to_string (item, NULL, 0)); g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex)); g_array_index (result, NMPlatformLink, j++) = *item; @@ -575,7 +567,7 @@ nm_platform_link_get_by_address (NMPlatform *self, } static NMPlatformError -_link_add_check_existing (NMPlatform *self, const char *name, NMLinkType type, NMPlatformLink *out_link) +_link_add_check_existing (NMPlatform *self, const char *name, NMLinkType type, const NMPlatformLink **out_link) { const NMPlatformLink *pllink; @@ -590,11 +582,13 @@ _link_add_check_existing (NMPlatform *self, const char *name, NMLinkType type, N wrong_type ? ", expected " : "", wrong_type ? nm_link_type_to_string (type) : ""); if (out_link) - *out_link = *pllink; + *out_link = pllink; if (wrong_type) return NM_PLATFORM_ERROR_WRONG_TYPE; return NM_PLATFORM_ERROR_EXISTS; } + if (out_link) + *out_link = NULL; return NM_PLATFORM_ERROR_SUCCESS; } @@ -623,14 +617,13 @@ nm_platform_link_add (NMPlatform *self, NMLinkType type, const void *address, size_t address_len, - NMPlatformLink *out_link) + const NMPlatformLink **out_link) { NMPlatformError plerr; _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); - g_return_val_if_fail (klass->link_add, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail ( (address != NULL) ^ (address_len == 0) , NM_PLATFORM_ERROR_BUG); plerr = _link_add_check_existing (self, name, type, out_link); @@ -644,7 +637,7 @@ nm_platform_link_add (NMPlatform *self, } /** - * nm_platform_dummy_add: + * nm_platform_link_dummy_add: * @self: platform instance * @name: New interface name * @out_link: on success, the link object @@ -652,7 +645,9 @@ nm_platform_link_add (NMPlatform *self, * Create a software ethernet-like interface */ NMPlatformError -nm_platform_dummy_add (NMPlatform *self, const char *name, NMPlatformLink *out_link) +nm_platform_link_dummy_add (NMPlatform *self, + const char *name, + const NMPlatformLink **out_link) { return nm_platform_link_add (self, name, NM_LINK_TYPE_DUMMY, NULL, 0, out_link); } @@ -746,8 +741,6 @@ nm_platform_link_get_type_name (NMPlatform *self, int ifindex) { _CHECK_SELF (self, klass, NULL); - g_return_val_if_fail (klass->link_get_type_name, NULL); - return klass->link_get_type_name (self, ifindex); } @@ -890,22 +883,19 @@ nm_platform_link_uses_arp (NMPlatform *self, int ifindex) gboolean nm_platform_link_get_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId *iid) { + const NMPlatformLink *pllink; + _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex >= 0, FALSE); g_return_val_if_fail (iid, FALSE); -#if HAVE_LIBNL_INET6_TOKEN - { - const NMPlatformLink *pllink; - pllink = nm_platform_link_get (self, ifindex); - if (pllink && pllink->inet6_token.is_valid) { - *iid = pllink->inet6_token.iid; - return TRUE; - } + pllink = nm_platform_link_get (self, ifindex); + if (pllink && pllink->inet6_token.is_valid) { + *iid = pllink->inet6_token.iid; + return TRUE; } -#endif return FALSE; } @@ -947,23 +937,18 @@ nm_platform_link_get_udev_device (NMPlatform *self, int ifindex) gboolean nm_platform_link_get_user_ipv6ll_enabled (NMPlatform *self, int ifindex) { + const NMPlatformLink *pllink; + _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex >= 0, FALSE); -#if HAVE_LIBNL_INET6_ADDR_GEN_MODE - { - const NMPlatformLink *pllink; - - pllink = nm_platform_link_get (self, ifindex); - if (pllink && pllink->inet6_addr_gen_mode_inv) - return _nm_platform_uint8_inv (pllink->inet6_addr_gen_mode_inv) == IN6_ADDR_GEN_MODE_NONE; - } -#endif + pllink = nm_platform_link_get (self, ifindex); + if (pllink && pllink->inet6_addr_gen_mode_inv) + return _nm_platform_uint8_inv (pllink->inet6_addr_gen_mode_inv) == NM_IN6_ADDR_GEN_MODE_NONE; return FALSE; } - /** * nm_platform_link_set_user_ip6vll_enabled: * @self: platform instance @@ -981,7 +966,6 @@ nm_platform_link_set_user_ipv6ll_enabled (NMPlatform *self, int ifindex, gboolea _CHECK_SELF (self, klass, FALSE); 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 (self, ifindex, enabled); @@ -1004,7 +988,6 @@ nm_platform_link_set_address (NMPlatform *self, int ifindex, gconstpointer addre g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (address, FALSE); g_return_val_if_fail (length > 0, FALSE); - g_return_val_if_fail (klass->link_set_address, FALSE); _LOGD ("link: setting '%s' (%d) hardware address", nm_platform_link_get_name (self, ifindex), ifindex); return klass->link_set_address (self, ifindex, address, length); @@ -1083,7 +1066,6 @@ nm_platform_link_supports_carrier_detect (NMPlatform *self, int ifindex) _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex >= 0, FALSE); - g_return_val_if_fail (klass->link_supports_carrier_detect, FALSE); return klass->link_supports_carrier_detect (self, ifindex); } @@ -1094,7 +1076,6 @@ nm_platform_link_supports_vlans (NMPlatform *self, int ifindex) _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex >= 0, FALSE); - g_return_val_if_fail (klass->link_supports_vlans, FALSE); return klass->link_supports_vlans (self, ifindex); } @@ -1113,7 +1094,6 @@ nm_platform_link_set_up (NMPlatform *self, int ifindex, gboolean *out_no_firmwar _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (klass->link_set_up, FALSE); _LOGD ("link: setting up '%s' (%d)", nm_platform_link_get_name (self, ifindex), ifindex); return klass->link_set_up (self, ifindex, out_no_firmware); @@ -1132,7 +1112,6 @@ nm_platform_link_set_down (NMPlatform *self, int ifindex) _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (klass->link_set_down, FALSE); _LOGD ("link: setting down '%s' (%d)", nm_platform_link_get_name (self, ifindex), ifindex); return klass->link_set_down (self, ifindex); @@ -1151,7 +1130,6 @@ nm_platform_link_set_arp (NMPlatform *self, int ifindex) _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex >= 0, FALSE); - g_return_val_if_fail (klass->link_set_arp, FALSE); _LOGD ("link: setting arp '%s' (%d)", nm_platform_link_get_name (self, ifindex), ifindex); return klass->link_set_arp (self, ifindex); @@ -1170,7 +1148,6 @@ nm_platform_link_set_noarp (NMPlatform *self, int ifindex) _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex >= 0, FALSE); - g_return_val_if_fail (klass->link_set_noarp, FALSE); _LOGD ("link: setting noarp '%s' (%d)", nm_platform_link_get_name (self, ifindex), ifindex); return klass->link_set_noarp (self, ifindex); @@ -1191,7 +1168,6 @@ nm_platform_link_set_mtu (NMPlatform *self, int ifindex, guint32 mtu) g_return_val_if_fail (ifindex >= 0, FALSE); g_return_val_if_fail (mtu > 0, FALSE); - g_return_val_if_fail (klass->link_set_mtu, FALSE); _LOGD ("link: setting '%s' (%d) mtu %"G_GUINT32_FORMAT, nm_platform_link_get_name (self, ifindex), ifindex, mtu); return klass->link_set_mtu (self, ifindex, mtu); @@ -1306,7 +1282,6 @@ nm_platform_link_get_driver_info (NMPlatform *self, _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex >= 0, FALSE); - g_return_val_if_fail (klass->link_get_driver_info, FALSE); return klass->link_get_driver_info (self, ifindex, @@ -1330,7 +1305,6 @@ nm_platform_link_enslave (NMPlatform *self, int master, int slave) g_return_val_if_fail (master > 0, FALSE); g_return_val_if_fail (slave> 0, FALSE); - g_return_val_if_fail (klass->link_enslave, FALSE); _LOGD ("link: enslaving '%s' (%d) to master '%s' (%d)", nm_platform_link_get_name (self, slave), slave, @@ -1353,7 +1327,6 @@ nm_platform_link_release (NMPlatform *self, int master, int slave) g_return_val_if_fail (master > 0, FALSE); g_return_val_if_fail (slave > 0, FALSE); - g_return_val_if_fail (klass->link_release, FALSE); if (nm_platform_link_get_master (self, slave) != master) return FALSE; @@ -1384,8 +1357,109 @@ nm_platform_link_get_master (NMPlatform *self, int slave) return pllink ? pllink->master : 0; } +/*****************************************************************************/ + /** - * nm_platform_bridge_add: + * nm_platform_link_get_lnk: + * @self: the platform instance + * @ifindex: the link ifindex to lookup + * @link_type: filter by link-type. + * @out_link: (allow-none): returns the platform link instance + * + * If the function returns %NULL, that could mean that no such ifindex + * exists, of that the link has no lnk data. You can find that out + * by checking @out_link. @out_link will always be set if a link + * with @ifindex exists. + * + * If @link_type is %NM_LINK_TYPE_NONE, the function returns the lnk + * object if it is present. If you set link-type, you can be sure + * that only a link type of the matching type is returned (or %NULL). + * + * Returns: the internal link lnk object. The returned object + * is owned by the platform cache and must not be modified. Note + * however, that the object is guaranteed to be immutable, so + * you can savely take a reference and keep it for yourself + * (but don't modify it). + */ +const NMPObject * +nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link) +{ + _CHECK_SELF (self, klass, FALSE); + + NM_SET_OUT (out_link, NULL); + + g_return_val_if_fail (ifindex > 0, NULL); + + return klass->link_get_lnk (self, ifindex, link_type, out_link); +} + +static gconstpointer +_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link) +{ + const NMPObject *lnk; + + lnk = nm_platform_link_get_lnk (self, ifindex, link_type, out_link); + return lnk ? &lnk->object : NULL; +} + +const NMPlatformLnkGre * +nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_GRE, out_link); +} + +const NMPlatformLnkInfiniband * +nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_INFINIBAND, out_link); +} + +const NMPlatformLnkIp6Tnl * +nm_platform_link_get_lnk_ip6tnl (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IP6TNL, out_link); +} + +const NMPlatformLnkIpIp * +nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IPIP, out_link); +} + +const NMPlatformLnkMacvlan * +nm_platform_link_get_lnk_macvlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_MACVLAN, out_link); +} + +const NMPlatformLnkMacvtap * +nm_platform_link_get_lnk_macvtap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_MACVTAP, out_link); +} + +const NMPlatformLnkSit * +nm_platform_link_get_lnk_sit (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_SIT, out_link); +} + +const NMPlatformLnkVlan * +nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VLAN, out_link); +} + +const NMPlatformLnkVxlan * +nm_platform_link_get_lnk_vxlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VXLAN, out_link); +} + +/*****************************************************************************/ + +/** + * nm_platform_link_bridge_add: * @self: platform instance * @name: New interface name * @address: (allow-none): set the mac address of the new bridge @@ -1395,17 +1469,17 @@ nm_platform_link_get_master (NMPlatform *self, int slave) * Create a software bridge. */ NMPlatformError -nm_platform_bridge_add (NMPlatform *self, - const char *name, - const void *address, - size_t address_len, - NMPlatformLink *out_link) +nm_platform_link_bridge_add (NMPlatform *self, + const char *name, + const void *address, + size_t address_len, + const NMPlatformLink **out_link) { return nm_platform_link_add (self, name, NM_LINK_TYPE_BRIDGE, address, address_len, out_link); } /** - * nm_platform_bond_add: + * nm_platform_link_bond_add: * @self: platform instance * @name: New interface name * @out_link: on success, the link object @@ -1413,13 +1487,15 @@ nm_platform_bridge_add (NMPlatform *self, * Create a software bonding device. */ NMPlatformError -nm_platform_bond_add (NMPlatform *self, const char *name, NMPlatformLink *out_link) +nm_platform_link_bond_add (NMPlatform *self, + const char *name, + const NMPlatformLink **out_link) { return nm_platform_link_add (self, name, NM_LINK_TYPE_BOND, NULL, 0, out_link); } /** - * nm_platform_team_add: + * nm_platform_link_team_add: * @self: platform instance * @name: New interface name * @out_link: on success, the link object @@ -1427,13 +1503,15 @@ nm_platform_bond_add (NMPlatform *self, const char *name, NMPlatformLink *out_li * Create a software teaming device. */ NMPlatformError -nm_platform_team_add (NMPlatform *self, const char *name, NMPlatformLink *out_link) +nm_platform_link_team_add (NMPlatform *self, + const char *name, + const NMPlatformLink **out_link) { return nm_platform_link_add (self, name, NM_LINK_TYPE_TEAM, NULL, 0, out_link); } /** - * nm_platform_vlan_add: + * nm_platform_link_vlan_add: * @self: platform instance * @name: New interface name * @vlanid: VLAN identifier @@ -1443,12 +1521,12 @@ nm_platform_team_add (NMPlatform *self, const char *name, NMPlatformLink *out_li * Create a software VLAN device. */ NMPlatformError -nm_platform_vlan_add (NMPlatform *self, - const char *name, - int parent, - int vlanid, - guint32 vlanflags, - NMPlatformLink *out_link) +nm_platform_link_vlan_add (NMPlatform *self, + const char *name, + int parent, + int vlanid, + guint32 vlanflags, + const NMPlatformLink **out_link) { NMPlatformError plerr; @@ -1457,7 +1535,6 @@ nm_platform_vlan_add (NMPlatform *self, g_return_val_if_fail (parent >= 0, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (vlanid >= 0, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); - g_return_val_if_fail (klass->vlan_add, NM_PLATFORM_ERROR_BUG); plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_VLAN, out_link); if (plerr != NM_PLATFORM_ERROR_SUCCESS) @@ -1470,98 +1547,321 @@ nm_platform_vlan_add (NMPlatform *self, return NM_PLATFORM_ERROR_SUCCESS; } +/** + * nm_platform_link_vxlan_add: + * @self: platform instance + * @name: New interface name + * @props: properties of the new link + * @out_link: on success, the link object + * + * Create a VXLAN device. + */ +NMPlatformError +nm_platform_link_vxlan_add (NMPlatform *self, + const char *name, + const NMPlatformLnkVxlan *props, + const NMPlatformLink **out_link) +{ + NMPlatformError plerr; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_VXLAN, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD ("link: adding vxlan '%s' parent %d id %d", + name, props->parent_ifindex, props->id); + if (!klass->link_vxlan_add (self, name, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; +} + +/** + * nm_platform_link_tun_add: + * @self: platform instance + * @name: new interface name + * @tap: whether the interface is a TAP + * @owner: interface owner or -1 + * @group: interface group or -1 + * @pi: whether to clear the IFF_NO_PI flag + * @vnet_hdr: whether to set the IFF_VNET_HDR flag + * @multi_queue: whether to set the IFF_MULTI_QUEUE flag + * @out_link: on success, the link object + * + * Create a TUN or TAP interface. + */ +NMPlatformError +nm_platform_link_tun_add (NMPlatform *self, + const char *name, + gboolean tap, + gint64 owner, + gint64 group, + gboolean pi, + gboolean vnet_hdr, + gboolean multi_queue, + const NMPlatformLink **out_link) +{ + NMPlatformError plerr; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, tap ? NM_LINK_TYPE_TAP : NM_LINK_TYPE_TUN, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD ("link: adding %s '%s' owner %" G_GINT64_FORMAT " group %" G_GINT64_FORMAT, + tap ? "tap" : "tun", name, owner, group); + if (!klass->tun_add (self, name, tap, owner, group, pi, vnet_hdr, multi_queue, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; +} + +/*****************************************************************************/ + +static char * +link_option_path (NMPlatform *self, int master, const char *category, const char *option) +{ + const char *name = nm_platform_link_get_name (self, master); + + if (!name || !category || !option) + return NULL; + + return g_strdup_printf ("/sys/class/net/%s/%s/%s", + ASSERT_VALID_PATH_COMPONENT (name), + ASSERT_VALID_PATH_COMPONENT (category), + ASSERT_VALID_PATH_COMPONENT (option)); +} + +static gboolean +link_set_option (NMPlatform *self, int master, const char *category, const char *option, const char *value) +{ + gs_free char *path = link_option_path (self, master, category, option); + + return path && nm_platform_sysctl_set (self, path, value); +} + +static char * +link_get_option (NMPlatform *self, int master, const char *category, const char *option) +{ + gs_free char *path = link_option_path (self, master, category, option); + + return path ? nm_platform_sysctl_get (self, path) : NULL; +} + +static const char * +master_category (NMPlatform *self, int master) +{ + switch (nm_platform_link_get_type (self, master)) { + case NM_LINK_TYPE_BRIDGE: + return "bridge"; + case NM_LINK_TYPE_BOND: + return "bonding"; + default: + return NULL; + } +} + +static const char * +slave_category (NMPlatform *self, int slave) +{ + int master = nm_platform_link_get_master (self, slave); + + if (master <= 0) + return NULL; + + switch (nm_platform_link_get_type (self, master)) { + case NM_LINK_TYPE_BRIDGE: + return "brport"; + default: + return NULL; + } +} + gboolean -nm_platform_master_set_option (NMPlatform *self, int ifindex, const char *option, const char *value) +nm_platform_sysctl_master_set_option (NMPlatform *self, int ifindex, const char *option, const char *value) { _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (option, FALSE); g_return_val_if_fail (value, FALSE); - g_return_val_if_fail (klass->master_set_option, FALSE); - return klass->master_set_option (self, ifindex, option, value); + return link_set_option (self, ifindex, master_category (self, ifindex), option, value); } char * -nm_platform_master_get_option (NMPlatform *self, int ifindex, const char *option) +nm_platform_sysctl_master_get_option (NMPlatform *self, int ifindex, const char *option) { _CHECK_SELF (self, klass, NULL); g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (option, FALSE); - g_return_val_if_fail (klass->master_set_option, FALSE); - return klass->master_get_option (self, ifindex, option); + return link_get_option (self, ifindex, master_category (self, ifindex), option); } gboolean -nm_platform_slave_set_option (NMPlatform *self, int ifindex, const char *option, const char *value) +nm_platform_sysctl_slave_set_option (NMPlatform *self, int ifindex, const char *option, const char *value) { _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (option, FALSE); g_return_val_if_fail (value, FALSE); - g_return_val_if_fail (klass->slave_set_option, FALSE); - return klass->slave_set_option (self, ifindex, option, value); + return link_set_option (self, ifindex, slave_category (self, ifindex), option, value); } char * -nm_platform_slave_get_option (NMPlatform *self, int ifindex, const char *option) +nm_platform_sysctl_slave_get_option (NMPlatform *self, int ifindex, const char *option) { _CHECK_SELF (self, klass, NULL); g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (option, FALSE); - g_return_val_if_fail (klass->slave_set_option, FALSE); - return klass->slave_get_option (self, ifindex, option); + return link_get_option (self, ifindex, slave_category (self, ifindex), option); } +/******************************************************************************/ + gboolean -nm_platform_vlan_get_info (NMPlatform *self, int ifindex, int *parent, int *vlanid) +nm_platform_link_vlan_change (NMPlatform *self, + int ifindex, + NMVlanFlags flags_mask, + NMVlanFlags flags_set, + gboolean ingress_reset_all, + const NMVlanQosMapping *ingress_map, + gsize n_ingress_map, + gboolean egress_reset_all, + const NMVlanQosMapping *egress_map, + gsize n_egress_map) { _CHECK_SELF (self, klass, FALSE); - g_return_val_if_fail (klass->vlan_get_info, FALSE); + nm_assert (klass->link_vlan_change); - if (parent) - *parent = 0; - if (vlanid) - *vlanid = 0; + g_return_val_if_fail (!n_ingress_map || ingress_map, FALSE); + g_return_val_if_fail (!n_egress_map || egress_map, FALSE); - if (nm_platform_link_get_type (self, ifindex) != NM_LINK_TYPE_VLAN) - return FALSE; + flags_set &= flags_mask; + + if (_LOGD_ENABLED ()) { + char buf[512]; + char *b = buf; + gsize len, i; + + b[0] = '\0'; + len = sizeof (buf); + + if (flags_mask) + nm_utils_strbuf_append (&b, &len, " flags 0x%x/0x%x", (unsigned) flags_set, (unsigned) flags_mask); + + if (ingress_reset_all || n_ingress_map) { + nm_utils_strbuf_append_str (&b, &len, " ingress-qos-map"); + nm_platform_vlan_qos_mapping_to_string ("", ingress_map, n_ingress_map, b, len); + i = strlen (b); + b += i; + len -= i; + if (ingress_reset_all) + nm_utils_strbuf_append_str (&b, &len, " (reset-all)"); + } + + if (egress_reset_all || n_egress_map) { + nm_utils_strbuf_append_str (&b, &len, " egress-qos-map"); + nm_platform_vlan_qos_mapping_to_string ("", egress_map, n_egress_map, b, len); + i = strlen (b); + b += i; + len -= i; + if (egress_reset_all) + nm_utils_strbuf_append_str (&b, &len, " (reset-all)"); + } - return klass->vlan_get_info (self, ifindex, parent, vlanid); + _LOGD ("link: change vlan %d:%s", ifindex, buf); + } + return klass->link_vlan_change (self, + ifindex, + flags_mask, + flags_set, + ingress_reset_all, + ingress_map, + n_ingress_map, + egress_reset_all, + egress_map, + n_egress_map); } gboolean -nm_platform_vlan_set_ingress_map (NMPlatform *self, int ifindex, int from, int to) +nm_platform_link_vlan_set_ingress_map (NMPlatform *self, int ifindex, int from, int to) { - _CHECK_SELF (self, klass, FALSE); - - g_return_val_if_fail (klass->vlan_set_ingress_map, FALSE); + NMVlanQosMapping map = { + .from = from, + .to = to, + }; - _LOGD ("link: setting vlan ingress map for %d from %d to %d", ifindex, from, to); - return klass->vlan_set_ingress_map (self, ifindex, from, to); + return nm_platform_link_vlan_change (self, ifindex, 0, 0, FALSE, &map, 1, FALSE, NULL, 0); } gboolean -nm_platform_vlan_set_egress_map (NMPlatform *self, int ifindex, int from, int to) +nm_platform_link_vlan_set_egress_map (NMPlatform *self, int ifindex, int from, int to) { - _CHECK_SELF (self, klass, FALSE); + NMVlanQosMapping map = { + .from = from, + .to = to, + }; - g_return_val_if_fail (klass->vlan_set_egress_map, FALSE); + return nm_platform_link_vlan_change (self, ifindex, 0, 0, FALSE, NULL, 0, FALSE, &map, 1); +} - _LOGD ("link: setting vlan egress map for %d from %d to %d", ifindex, from, to); - return klass->vlan_set_egress_map (self, ifindex, from, to); +/** + * nm_platform_link_gre_add: + * @self: platform instance + * @name: name of the new interface + * @props: interface properties + * @out_link: on success, the link object + * + * Create a software GRE device. + */ +NMPlatformError +nm_platform_link_gre_add (NMPlatform *self, + const char *name, + const NMPlatformLnkGre *props, + const NMPlatformLink **out_link) +{ + NMPlatformError plerr; + char buffer[INET_ADDRSTRLEN]; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_GRE, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD (LOG_FMT_IP_TUNNEL, + "gre", + name, + props->parent_ifindex, + nm_utils_inet4_ntop (props->local, NULL), + nm_utils_inet4_ntop (props->remote, buffer)); + + if (!klass->link_gre_add (self, name, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; } NMPlatformError -nm_platform_infiniband_partition_add (NMPlatform *self, int parent, int p_key, NMPlatformLink *out_link) +nm_platform_link_infiniband_add (NMPlatform *self, + int parent, + int p_key, + const NMPlatformLink **out_link) { gs_free char *parent_name = NULL; gs_free char *name = NULL; @@ -1571,7 +1871,6 @@ nm_platform_infiniband_partition_add (NMPlatform *self, int parent, int p_key, N g_return_val_if_fail (parent >= 0, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (p_key >= 0, NM_PLATFORM_ERROR_BUG); - g_return_val_if_fail (klass->infiniband_partition_add, NM_PLATFORM_ERROR_BUG); parent_name = g_strdup (nm_platform_link_get_name (self, parent)); if ( !parent_name @@ -1591,73 +1890,330 @@ nm_platform_infiniband_partition_add (NMPlatform *self, int parent, int p_key, N } gboolean -nm_platform_infiniband_get_info (NMPlatform *self, - int ifindex, - int *parent, - int *p_key, - const char **mode) -{ +nm_platform_link_infiniband_get_properties (NMPlatform *self, + int ifindex, + int *out_parent, + int *out_p_key, + const char **out_mode) +{ + const NMPlatformLnkInfiniband *plnk; + const NMPlatformLink *plink; + const char *iface; + char *path, *contents; + const char *mode; + int p_key = 0; + _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (klass->infiniband_get_info, FALSE); - return klass->infiniband_get_info (self, ifindex, parent, p_key, mode); + plnk = nm_platform_link_get_lnk_infiniband (self, ifindex, &plink); + + if ( !plink + || plink->type != NM_LINK_TYPE_INFINIBAND) + return FALSE; + + if (plnk) { + NM_SET_OUT (out_parent, plink->parent); + NM_SET_OUT (out_p_key, plnk->p_key); + NM_SET_OUT (out_mode, plnk->mode); + return TRUE; + } + + /* Could not get the link information via netlink. To support older kernels, + * fallback to reading sysfs. */ + + iface = ASSERT_VALID_PATH_COMPONENT (plink->name); + + /* Fall back to reading sysfs */ + path = g_strdup_printf ("/sys/class/net/%s/mode", iface); + contents = nm_platform_sysctl_get (self, path); + g_free (path); + if (!contents) + return FALSE; + + if (strstr (contents, "datagram")) + mode = "datagram"; + else if (strstr (contents, "connected")) + mode = "connected"; + else + mode = NULL; + g_free (contents); + + path = g_strdup_printf ("/sys/class/net/%s/pkey", iface); + contents = nm_platform_sysctl_get (self, path); + g_free (path); + if (!contents) + return FALSE; + p_key = (int) _nm_utils_ascii_str_to_int64 (contents, 16, 0, 0xFFFF, -1); + g_free (contents); + if (p_key < 0) + return FALSE; + + NM_SET_OUT (out_parent, plink->parent); + NM_SET_OUT (out_p_key, p_key); + NM_SET_OUT (out_mode, mode); + return TRUE; } -gboolean -nm_platform_veth_get_properties (NMPlatform *self, int ifindex, NMPlatformVethProperties *props) +/** + * nm_platform_ip6tnl_add: + * @self: platform instance + * @name: name of the new interface + * @props: interface properties + * @out_link: on success, the link object + * + * Create an IPv6 tunnel. + */ +NMPlatformError +nm_platform_link_ip6tnl_add (NMPlatform *self, + const char *name, + const NMPlatformLnkIp6Tnl *props, + const NMPlatformLink **out_link) { - _CHECK_SELF (self, klass, FALSE); + NMPlatformError plerr; + char buffer[INET6_ADDRSTRLEN]; - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (props != NULL, FALSE); + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_IP6TNL, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; - return klass->veth_get_properties (self, ifindex, props); + _LOGD (LOG_FMT_IP_TUNNEL, + "ip6tnl", + name, + props->parent_ifindex, + nm_utils_inet6_ntop (&props->local, NULL), + nm_utils_inet6_ntop (&props->remote, buffer)); + + if (!klass->link_ip6tnl_add (self, name, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; } -gboolean -nm_platform_tun_get_properties (NMPlatform *self, int ifindex, NMPlatformTunProperties *props) +/** + * nm_platform_ipip_add: + * @self: platform instance + * @name: name of the new interface + * @props: interface properties + * @out_link: on success, the link object + * + * Create an IPIP tunnel. + */ +NMPlatformError +nm_platform_link_ipip_add (NMPlatform *self, + const char *name, + const NMPlatformLnkIpIp *props, + const NMPlatformLink **out_link) { - _CHECK_SELF (self, klass, FALSE); + NMPlatformError plerr; + char buffer[INET_ADDRSTRLEN]; - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (props != NULL, FALSE); + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); - return klass->tun_get_properties (self, ifindex, props); + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_IPIP, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD (LOG_FMT_IP_TUNNEL, + "ipip", + name, + props->parent_ifindex, + nm_utils_inet4_ntop (props->local, NULL), + nm_utils_inet4_ntop (props->remote, buffer)); + + if (!klass->link_ipip_add (self, name, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; +} + +/** + * nm_platform_macvlan_add: + * @self: platform instance + * @name: name of the new interface + * @props: interface properties + * @out_link: on success, the link object + * + * Create a MACVLAN or MACVTAP device. + */ +NMPlatformError +nm_platform_link_macvlan_add (NMPlatform *self, + const char *name, + int parent, + const NMPlatformLnkMacvlan *props, + const NMPlatformLink **out_link) +{ + NMPlatformError plerr; + NMLinkType type; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + + type = props->tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN; + + plerr = _link_add_check_existing (self, name, type, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD ("adding %s '%s' parent %u mode %u", + props->tap ? "macvtap" : "macvlan", + name, + parent, + props->mode); + + if (!klass->link_macvlan_add (self, name, parent, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; +} + +/** + * nm_platform_sit_add: + * @self: platform instance + * @name: name of the new interface + * @props: interface properties + * @out_link: on success, the link object + * + * Create a software SIT device. + */ +NMPlatformError +nm_platform_link_sit_add (NMPlatform *self, + const char *name, + const NMPlatformLnkSit *props, + const NMPlatformLink **out_link) +{ + NMPlatformError plerr; + char buffer[INET_ADDRSTRLEN]; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_SIT, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD (LOG_FMT_IP_TUNNEL, + "sit", + name, + props->parent_ifindex, + nm_utils_inet4_ntop (props->local, NULL), + nm_utils_inet4_ntop (props->remote, buffer)); + + if (!klass->link_sit_add (self, name, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; } gboolean -nm_platform_macvlan_get_properties (NMPlatform *self, int ifindex, NMPlatformMacvlanProperties *props) +nm_platform_link_veth_get_properties (NMPlatform *self, int ifindex, int *out_peer_ifindex) { + const NMPlatformLink *plink; + int peer_ifindex; _CHECK_SELF (self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (props != NULL, FALSE); + plink = nm_platform_link_get (self, ifindex); + + if (!plink) + return FALSE; + if (plink->type != NM_LINK_TYPE_VETH) + return FALSE; + + if (plink->parent != 0) { + NM_SET_OUT (out_peer_ifindex, plink->parent); + return TRUE; + } + + /* Pre-4.1 kernel did not expose the peer_ifindex as IFA_LINK. Lookup via ethtool. */ + if (out_peer_ifindex) { + peer_ifindex = nmp_utils_ethtool_get_peer_ifindex (plink->name); + if (peer_ifindex <= 0) + return FALSE; - return klass->macvlan_get_properties (self, ifindex, props); + *out_peer_ifindex = peer_ifindex; + } + return TRUE; } gboolean -nm_platform_vxlan_get_properties (NMPlatform *self, int ifindex, NMPlatformVxlanProperties *props) +nm_platform_link_tun_get_properties_ifname (NMPlatform *self, const char *ifname, NMPlatformTunProperties *props) { + char *path, *val; + gboolean success = TRUE; + _CHECK_SELF (self, klass, FALSE); - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (props != NULL, FALSE); + g_return_val_if_fail (props, FALSE); + + memset (props, 0, sizeof (*props)); + props->owner = -1; + props->group = -1; - return klass->vxlan_get_properties (self, ifindex, props); + if (!ifname || !nm_utils_iface_valid_name (ifname)) + return FALSE; + ifname = ASSERT_VALID_PATH_COMPONENT (ifname); + + path = g_strdup_printf ("/sys/class/net/%s/owner", ifname); + val = nm_platform_sysctl_get (self, path); + g_free (path); + if (val) { + props->owner = _nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1); + if (errno) + success = FALSE; + g_free (val); + } else + success = FALSE; + + path = g_strdup_printf ("/sys/class/net/%s/group", ifname); + val = nm_platform_sysctl_get (self, path); + g_free (path); + if (val) { + props->group = _nm_utils_ascii_str_to_int64 (val, 10, -1, G_MAXINT64, -1); + if (errno) + success = FALSE; + g_free (val); + } else + success = FALSE; + + path = g_strdup_printf ("/sys/class/net/%s/tun_flags", ifname); + val = nm_platform_sysctl_get (self, path); + g_free (path); + if (val) { + gint64 flags; + + flags = _nm_utils_ascii_str_to_int64 (val, 16, 0, G_MAXINT64, 0); + if (!errno) { + 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 & NM_IFF_MULTI_QUEUE); + } else + success = FALSE; + g_free (val); + } else + success = FALSE; + + return success; } gboolean -nm_platform_gre_get_properties (NMPlatform *self, int ifindex, NMPlatformGreProperties *props) +nm_platform_link_tun_get_properties (NMPlatform *self, int ifindex, NMPlatformTunProperties *props) { _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (props != NULL, FALSE); - return klass->gre_get_properties (self, ifindex, props); + return nm_platform_link_tun_get_properties_ifname (self, nm_platform_link_get_name (self, ifindex), props); } gboolean @@ -1680,16 +2236,6 @@ nm_platform_wifi_get_bssid (NMPlatform *self, int ifindex, guint8 *bssid) return klass->wifi_get_bssid (self, ifindex, bssid); } -GByteArray * -nm_platform_wifi_get_ssid (NMPlatform *self, int ifindex) -{ - _CHECK_SELF (self, klass, NULL); - - g_return_val_if_fail (ifindex > 0, NULL); - - return klass->wifi_get_ssid (self, ifindex); -} - guint32 nm_platform_wifi_get_frequency (NMPlatform *self, int ifindex) { @@ -1740,6 +2286,22 @@ nm_platform_wifi_set_mode (NMPlatform *self, int ifindex, NM80211Mode mode) klass->wifi_set_mode (self, ifindex, mode); } +static void +wifi_set_powersave (NMPlatform *p, int ifindex, guint32 powersave) +{ + /* empty */ +} + +void +nm_platform_wifi_set_powersave (NMPlatform *self, int ifindex, guint32 powersave) +{ + _CHECK_SELF_VOID (self, klass); + + g_return_if_fail (ifindex > 0); + + klass->wifi_set_powersave (self, ifindex, powersave); +} + guint32 nm_platform_wifi_find_frequency (NMPlatform *self, int ifindex, const guint32 *freqs) { @@ -1818,13 +2380,29 @@ _to_string_dev (NMPlatform *self, int ifindex, char *buf, size_t size) /******************************************************************/ +void +nm_platform_ip4_address_set_addr (NMPlatformIP4Address *addr, in_addr_t address, int plen) +{ + addr->address = address; + addr->peer_address = address; + addr->plen = plen; +} + +const struct in6_addr * +nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr) +{ + if ( IN6_IS_ADDR_UNSPECIFIED (&addr->peer_address) + || IN6_ARE_ADDR_EQUAL (&addr->peer_address, &addr->address)) + return &addr->address; + return &addr->peer_address; +} + GArray * nm_platform_ip4_address_get_all (NMPlatform *self, int ifindex) { _CHECK_SELF (self, klass, NULL); g_return_val_if_fail (ifindex > 0, NULL); - g_return_val_if_fail (klass->ip4_address_get_all, NULL); return klass->ip4_address_get_all (self, ifindex); } @@ -1835,17 +2413,16 @@ nm_platform_ip6_address_get_all (NMPlatform *self, int ifindex) _CHECK_SELF (self, klass, NULL); g_return_val_if_fail (ifindex > 0, NULL); - g_return_val_if_fail (klass->ip6_address_get_all, NULL); return klass->ip6_address_get_all (self, ifindex); } gboolean nm_platform_ip4_address_add (NMPlatform *self, - int ifindex, + int ifindex, in_addr_t address, - in_addr_t peer_address, int plen, + in_addr_t peer_address, guint32 lifetime, guint32 preferred, const char *label) @@ -1856,7 +2433,6 @@ nm_platform_ip4_address_add (NMPlatform *self, g_return_val_if_fail (plen > 0, FALSE); g_return_val_if_fail (lifetime > 0, FALSE); g_return_val_if_fail (preferred <= lifetime, FALSE); - g_return_val_if_fail (klass->ip4_address_add, FALSE); g_return_val_if_fail (!label || strlen (label) < sizeof (((NMPlatformIP4Address *) NULL)->label), FALSE); if (_LOGD_ENABLED ()) { @@ -1872,17 +2448,17 @@ nm_platform_ip4_address_add (NMPlatform *self, if (label) g_strlcpy (addr.label, label, sizeof (addr.label)); - _LOGD ("address: adding or updating IPv4 address: %s", nm_platform_ip4_address_to_string (&addr)); + _LOGD ("address: adding or updating IPv4 address: %s", nm_platform_ip4_address_to_string (&addr, NULL, 0)); } - return klass->ip4_address_add (self, ifindex, address, peer_address, plen, lifetime, preferred, label); + return klass->ip4_address_add (self, ifindex, address, plen, peer_address, lifetime, preferred, label); } gboolean nm_platform_ip6_address_add (NMPlatform *self, int ifindex, struct in6_addr address, - struct in6_addr peer_address, int plen, + struct in6_addr peer_address, guint32 lifetime, guint32 preferred, guint flags) @@ -1893,7 +2469,6 @@ nm_platform_ip6_address_add (NMPlatform *self, g_return_val_if_fail (plen > 0, FALSE); g_return_val_if_fail (lifetime > 0, FALSE); g_return_val_if_fail (preferred <= lifetime, FALSE); - g_return_val_if_fail (klass->ip6_address_add, FALSE); if (_LOGD_ENABLED ()) { NMPlatformIP6Address addr = { 0 }; @@ -1907,28 +2482,27 @@ nm_platform_ip6_address_add (NMPlatform *self, addr.preferred = preferred; addr.flags = flags; - _LOGD ("address: adding or updating IPv6 address: %s", nm_platform_ip6_address_to_string (&addr)); + _LOGD ("address: adding or updating IPv6 address: %s", nm_platform_ip6_address_to_string (&addr, NULL, 0)); } - return klass->ip6_address_add (self, ifindex, address, peer_address, plen, lifetime, preferred, flags); + return klass->ip6_address_add (self, ifindex, address, plen, peer_address, lifetime, preferred, flags); } gboolean nm_platform_ip4_address_delete (NMPlatform *self, 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]; + char str_peer2[NM_UTILS_INET_ADDRSTRLEN]; + char str_peer[100]; _CHECK_SELF (self, klass, FALSE); 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); - _LOGD ("address: deleting IPv4 address %s/%d, %s%s%sifindex %d%s", + _LOGD ("address: deleting IPv4 address %s/%d, %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 ? ", " : "", + peer_address != address + ? nm_sprintf_buf (str_peer, "peer %s, ", nm_utils_inet4_ntop (peer_address, str_peer2)) : "", ifindex, _to_string_dev (self, ifindex, str_dev, sizeof (str_dev))); return klass->ip4_address_delete (self, ifindex, address, plen, peer_address); @@ -1943,7 +2517,6 @@ nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr a 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); _LOGD ("address: deleting IPv6 address %s/%d, ifindex %d%s", nm_utils_inet6_ntop (&address, NULL), plen, ifindex, @@ -1952,21 +2525,21 @@ nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr a } const NMPlatformIP4Address * -nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen) +nm_platform_ip4_address_get (NMPlatform *self, int ifindex, in_addr_t address, int plen, guint32 peer_address) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF (self, klass, NULL); - g_return_val_if_fail (plen > 0, FALSE); + g_return_val_if_fail (plen > 0, NULL); - return klass->ip4_address_get (self, ifindex, address, plen); + return klass->ip4_address_get (self, ifindex, address, plen, peer_address); } const NMPlatformIP6Address * nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address, int plen) { - _CHECK_SELF (self, klass, FALSE); + _CHECK_SELF (self, klass, NULL); - g_return_val_if_fail (plen > 0, FALSE); + g_return_val_if_fail (plen > 0, NULL); return klass->ip6_address_get (self, ifindex, address, plen); } @@ -1980,7 +2553,9 @@ array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address for (i = 0; i < len; i++) { NMPlatformIP4Address *candidate = &g_array_index (addresses, NMPlatformIP4Address, i); - if (candidate->address == address->address && candidate->plen == address->plen) { + if ( candidate->address == address->address + && candidate->plen == address->plen + && ((candidate->peer_address ^ address->peer_address) & nm_utils_ip4_prefix_to_netmask (address->plen)) == 0) { guint32 lifetime, preferred; if (nmp_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred, @@ -2064,7 +2639,7 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known now, ADDRESS_LIFETIME_PADDING, &lifetime, &preferred)) continue; - if (!nm_platform_ip4_address_add (self, ifindex, known_address->address, known_address->peer_address, known_address->plen, lifetime, preferred, known_address->label)) + if (!nm_platform_ip4_address_add (self, ifindex, known_address->address, known_address->plen, known_address->peer_address, lifetime, preferred, known_address->label)) return FALSE; if (out_added_addresses) { @@ -2125,7 +2700,7 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known continue; if (!nm_platform_ip6_address_add (self, ifindex, known_address->address, - known_address->peer_address, known_address->plen, + known_address->plen, known_address->peer_address, lifetime, preferred, known_address->flags)) return FALSE; } @@ -2164,17 +2739,46 @@ nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRoute return klass->ip6_route_get_all (self, ifindex, flags); } +/** + * nm_platform_ip4_route_add: + * @self: + * @ifindex: + * @source: + * network: + * plen: + * gateway: + * pref_src: + * metric: + * mss: + * + * For kernel, a gateway can be either explicitly set or left + * at zero (0.0.0.0). In addition, there is the scope of the IPv4 + * route. + * When adding a route with + * $ ip route add default dev $IFNAME + * the resulting route will have gateway 0.0.0.0 and scope "link". + * Contrary to + * $ ip route add default via 0.0.0.0 dev $IFNAME + * which adds the route with scope "global". + * + * NetworkManager's Platform can currently only add on-link-routes with scope + * "link" (and gateway 0.0.0.0) or gateway-routes with scope "global" (and + * gateway not 0.0.0.0). + * + * It does not support adding globally scoped routes via 0.0.0.0. + * + * Returns: %TRUE in case of success. + */ gboolean nm_platform_ip4_route_add (NMPlatform *self, int ifindex, NMIPConfigSource source, in_addr_t network, int plen, - in_addr_t gateway, guint32 pref_src, + in_addr_t gateway, in_addr_t pref_src, guint32 metric, guint32 mss) { _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (0 <= plen && plen <= 32, FALSE); - g_return_val_if_fail (klass->ip4_route_add, FALSE); if (_LOGD_ENABLED ()) { NMPlatformIP4Route route = { 0 }; @@ -2188,7 +2792,7 @@ nm_platform_ip4_route_add (NMPlatform *self, route.mss = mss; route.pref_src = pref_src; - _LOGD ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (&route)); + _LOGD ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (&route, NULL, 0)); } return klass->ip4_route_add (self, ifindex, source, network, plen, gateway, pref_src, metric, mss); } @@ -2202,7 +2806,6 @@ nm_platform_ip6_route_add (NMPlatform *self, _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (0 <= plen && plen <= 128, FALSE); - g_return_val_if_fail (klass->ip6_route_add, FALSE); if (_LOGD_ENABLED ()) { NMPlatformIP6Route route = { 0 }; @@ -2215,7 +2818,7 @@ nm_platform_ip6_route_add (NMPlatform *self, route.metric = metric; route.mss = mss; - _LOGD ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (&route)); + _LOGD ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (&route, NULL, 0)); } return klass->ip6_route_add (self, ifindex, source, network, plen, gateway, metric, mss); } @@ -2227,8 +2830,6 @@ nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, _CHECK_SELF (self, klass, FALSE); - g_return_val_if_fail (klass->ip4_route_delete, FALSE); - _LOGD ("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 (self, ifindex, str_dev, sizeof (str_dev))); @@ -2242,8 +2843,6 @@ nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr net _CHECK_SELF (self, klass, FALSE); - g_return_val_if_fail (klass->ip6_route_delete, FALSE); - _LOGD ("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 (self, ifindex, str_dev, sizeof (str_dev))); @@ -2268,6 +2867,40 @@ nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr networ /******************************************************************/ +const char * +nm_platform_vlan_qos_mapping_to_string (const char *name, + const NMVlanQosMapping *map, + gsize n_map, + char *buf, + gsize len) +{ + gsize i; + char *b; + + nm_utils_to_string_buffer_init (&buf, &len); + + if (!n_map) { + nm_utils_strbuf_append_str (&buf, &len, ""); + return buf; + } + + if (!map) + g_return_val_if_reached (""); + + b = buf; + + if (name) { + nm_utils_strbuf_append_str (&b, &len, name); + nm_utils_strbuf_append_str (&b, &len, " {"); + } else + nm_utils_strbuf_append_c (&b, &len, '{'); + + for (i = 0; i < n_map; i++) + nm_utils_strbuf_append (&b, &len, " %u:%u", map[i].from, map[i].to); + nm_utils_strbuf_append_str (&b, &len, " }"); + return buf; +} + static const char * source_to_string (NMIPConfigSource source) { @@ -2320,21 +2953,29 @@ _lifetime_summary_to_string (gint32 now, guint32 timestamp, guint32 preferred, g return buf; } -char _nm_platform_to_string_buffer[256]; - +/** + * nm_platform_link_to_string: + * @route: pointer to NMPlatformLink address structure + * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used. + * @len: the size of the @buf. If @buf is %NULL, this argument is ignored. + * + * A method for converting an link struct into a string representation. + * + * Returns: a string representation of the link. + */ const char * -nm_platform_link_to_string (const NMPlatformLink *link) +nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len) { char master[20]; char parent[20]; - char str_vlan[16]; GString *str_flags; char str_addrmode[30]; gs_free char *str_addr = NULL; gs_free char *str_inet6_token = NULL; + const char *str_link_type; - if (!link) - return "(unknown link)"; + if (!nm_utils_to_string_buffer_init_null (link, &buf, &len)) + return buf; str_flags = g_string_new (NULL); if (NM_FLAGS_HAS (link->flags, IFF_NOARP)) @@ -2349,7 +2990,7 @@ nm_platform_link_to_string (const NMPlatformLink *link) if (link->flags) { char str_flags_buf[64]; - rtnl_link_flags2str (link->flags, str_flags_buf, sizeof (str_flags_buf)); + nm_platform_link_flags2str (link->flags, str_flags_buf, sizeof (str_flags_buf)); g_string_append_printf (str_flags, ";%s", str_flags_buf); } @@ -2365,11 +3006,6 @@ nm_platform_link_to_string (const NMPlatformLink *link) else parent[0] = 0; - if (link->vlan_id) - g_snprintf (str_vlan, sizeof (str_vlan), " vlan %u", (guint) link->vlan_id); - else - str_vlan[0] = '\0'; - if (link->inet6_addr_gen_mode_inv) { switch (_nm_platform_uint8_inv (link->inet6_addr_gen_mode_inv)) { case 0: @@ -2390,14 +3026,15 @@ nm_platform_link_to_string (const NMPlatformLink *link) if (link->inet6_token.is_valid) str_inet6_token = nm_utils_hwaddr_ntoa (&link->inet6_token.iid, sizeof (link->inet6_token.iid)); - g_snprintf (_nm_platform_to_string_buffer, sizeof (_nm_platform_to_string_buffer), + str_link_type = nm_link_type_to_string (link->type); + + g_snprintf (buf, len, "%d: " /* ifindex */ "%s" /* name */ "%s" /* parent */ " <%s>" /* flags */ " mtu %d" "%s" /* master */ - "%s" /* vlan */ " arp %u" /* arptype */ "%s%s" /* link->type */ "%s%s" /* kind */ @@ -2412,12 +3049,11 @@ nm_platform_link_to_string (const NMPlatformLink *link) parent, str_flags->str, link->mtu, master, - str_vlan, link->arptype, - nm_link_type_to_string (link->type) ? " " : "", - str_if_set (nm_link_type_to_string (link->type), "???"), - link->kind ? (g_strcmp0 (nm_link_type_to_string (link->type), link->kind) ? "/" : "*") : "", - link->kind && g_strcmp0 (nm_link_type_to_string (link->type), link->kind) ? link->kind : "", + str_link_type ? " " : "", + str_if_set (str_link_type, "???"), + link->kind ? (g_strcmp0 (str_link_type, link->kind) ? "/" : "*") : "", + link->kind && g_strcmp0 (str_link_type, link->kind) ? link->kind : "", link->initialized ? " init" : " not-init", str_addrmode, str_addr ? " addr " : "", @@ -2427,23 +3063,313 @@ nm_platform_link_to_string (const NMPlatformLink *link) link->driver ? " driver " : "", link->driver ? link->driver : ""); g_string_free (str_flags, TRUE); - return _nm_platform_to_string_buffer; + return buf; +} + +const char * +nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len) +{ + char str_local[30]; + char str_local1[NM_UTILS_INET_ADDRSTRLEN]; + char str_remote[30]; + char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; + char str_ttl[30]; + char str_tos[30]; + char str_parent_ifindex[30]; + char str_input_flags[30]; + char str_output_flags[30]; + char str_input_key[30]; + char str_input_key1[NM_UTILS_INET_ADDRSTRLEN]; + char str_output_key[30]; + char str_output_key1[NM_UTILS_INET_ADDRSTRLEN]; + + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + g_snprintf (buf, len, + "gre" + "%s" /* remote */ + "%s" /* local */ + "%s" /* parent_ifindex */ + "%s" /* ttl */ + "%s" /* tos */ + "%s" /* path_mtu_discovery */ + "%s" /* iflags */ + "%s" /* oflags */ + "%s" /* ikey */ + "%s" /* okey */ + "", + lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", + lnk->local ? nm_sprintf_buf (str_local, " local %s", nm_utils_inet4_ntop (lnk->local, str_local1)) : "", + lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", + lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", + lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos 0x%x", lnk->tos)) : "", + lnk->path_mtu_discovery ? "" : " nopmtudisc", + lnk->input_flags ? nm_sprintf_buf (str_input_flags, " iflags 0x%x", lnk->input_flags) : "", + lnk->output_flags ? nm_sprintf_buf (str_output_flags, " oflags 0x%x", lnk->output_flags) : "", + NM_FLAGS_HAS (lnk->input_flags, GRE_KEY) || lnk->input_key ? nm_sprintf_buf (str_input_key, " ikey %s", nm_utils_inet4_ntop (lnk->input_key, str_input_key1)) : "", + NM_FLAGS_HAS (lnk->output_flags, GRE_KEY) || lnk->output_key ? nm_sprintf_buf (str_output_key, " okey %s", nm_utils_inet4_ntop (lnk->output_key, str_output_key1)) : ""); + return buf; +} + +const char * +nm_platform_lnk_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char *buf, gsize len) +{ + char str_p_key[64]; + + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + g_snprintf (buf, len, + "infiniband" + "%s" /* p_key */ + "%s%s" /* mode */ + "", + lnk->p_key ? nm_sprintf_buf (str_p_key, " pkey %d", lnk->p_key) : "", + lnk->mode ? " mode " : "", + lnk->mode ?: ""); + return buf; +} + +const char * +nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len) +{ + char str_local[30]; + char str_local1[NM_UTILS_INET_ADDRSTRLEN]; + char str_remote[30]; + char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; + char str_ttl[30]; + char str_tclass[30]; + char str_flow[30]; + char str_encap[30]; + char str_proto[30]; + char str_parent_ifindex[30]; + + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + g_snprintf (buf, len, + "ip6tnl" + "%s" /* remote */ + "%s" /* local */ + "%s" /* parent_ifindex */ + "%s" /* ttl */ + "%s" /* tclass */ + "%s" /* encap limit */ + "%s" /* flow label */ + "%s" /* proto */ + "", + nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet6_ntop (&lnk->remote, str_remote1)), + nm_sprintf_buf (str_local, " local %s", nm_utils_inet6_ntop (&lnk->local, str_local1)), + lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", + lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", + lnk->tclass == 1 ? " tclass inherit" : nm_sprintf_buf (str_tclass, " tclass 0x%x", lnk->tclass), + nm_sprintf_buf (str_encap, " encap-limit %u", lnk->encap_limit), + nm_sprintf_buf (str_flow, " flow-label 0x05%x", lnk->flow_label), + nm_sprintf_buf (str_proto, " proto %u", lnk->proto)); + return buf; +} + +const char * +nm_platform_lnk_ipip_to_string (const NMPlatformLnkIpIp *lnk, char *buf, gsize len) +{ + char str_local[30]; + char str_local1[NM_UTILS_INET_ADDRSTRLEN]; + char str_remote[30]; + char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; + char str_ttl[30]; + char str_tos[30]; + char str_parent_ifindex[30]; + + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + g_snprintf (buf, len, + "ipip" + "%s" /* remote */ + "%s" /* local */ + "%s" /* parent_ifindex */ + "%s" /* ttl */ + "%s" /* tos */ + "%s" /* path_mtu_discovery */ + "", + lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", + lnk->local ? nm_sprintf_buf (str_local, " local %s", nm_utils_inet4_ntop (lnk->local, str_local1)) : "", + lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", + lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", + lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos 0x%x", lnk->tos)) : "", + lnk->path_mtu_discovery ? "" : " nopmtudisc"); + return buf; +} + +const char * +nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, char *buf, gsize len) +{ + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + g_snprintf (buf, len, + "macvlan mode %u %s", + lnk->mode, + lnk->no_promisc ? "not-promisc" : "promisc"); + return buf; +} + +const char * +nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len) +{ + char str_local[30]; + char str_local1[NM_UTILS_INET_ADDRSTRLEN]; + char str_remote[30]; + char str_remote1[NM_UTILS_INET_ADDRSTRLEN]; + char str_ttl[30]; + char str_tos[30]; + char str_flags[30]; + char str_proto[30]; + char str_parent_ifindex[30]; + + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + g_snprintf (buf, len, + "sit" + "%s" /* remote */ + "%s" /* local */ + "%s" /* parent_ifindex */ + "%s" /* ttl */ + "%s" /* tos */ + "%s" /* path_mtu_discovery */ + "%s" /* flags */ + "%s" /* proto */ + "", + lnk->remote ? nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet4_ntop (lnk->remote, str_remote1)) : "", + lnk->local ? nm_sprintf_buf (str_local, " local %s", nm_utils_inet4_ntop (lnk->local, str_local1)) : "", + lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", + lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : " ttl inherit", + lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos 0x%x", lnk->tos)) : "", + lnk->path_mtu_discovery ? "" : " nopmtudisc", + lnk->flags ? nm_sprintf_buf (str_flags, " flags 0x%x", lnk->flags) : "", + lnk->proto ? nm_sprintf_buf (str_proto, " proto 0x%x", lnk->proto) : ""); + return buf; +} + +const char * +nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len) +{ + char *b; + + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + b = buf; + + nm_utils_strbuf_append (&b, &len, "vlan %u", lnk->id); + if (lnk->flags) + nm_utils_strbuf_append (&b, &len, " flags 0x%x", lnk->flags); + return buf; +} + +const char * +nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize len) +{ + char str_group[100]; + char str_group6[100]; + char str_local[100]; + char str_local6[100]; + char str_dev[25]; + char str_limit[25]; + char str_src_port[35]; + char str_dst_port[25]; + char str_tos[25]; + char str_ttl[25]; + + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + if (lnk->group == 0) + str_group[0] = '\0'; + else { + g_snprintf (str_group, sizeof (str_group), + " %s %s", + IN_MULTICAST (ntohl (lnk->group)) ? "group" : "remote", + nm_utils_inet4_ntop (lnk->group, NULL)); + } + if (IN6_IS_ADDR_UNSPECIFIED (&lnk->group6)) + str_group6[0] = '\0'; + else { + g_snprintf (str_group6, sizeof (str_group6), + " %s%s %s", + IN6_IS_ADDR_MULTICAST (&lnk->group6) ? "group" : "remote", + str_group[0] ? "6" : "", /* usually, a vxlan has either v4 or v6 only. */ + nm_utils_inet6_ntop (&lnk->group6, NULL)); + } + + if (lnk->local == 0) + str_local[0] = '\0'; + else { + g_snprintf (str_local, sizeof (str_local), + " local %s", + nm_utils_inet4_ntop (lnk->local, NULL)); + } + if (IN6_IS_ADDR_UNSPECIFIED (&lnk->local6)) + str_local6[0] = '\0'; + else { + g_snprintf (str_local6, sizeof (str_local6), + " local%s %s", + str_local[0] ? "6" : "", /* usually, a vxlan has either v4 or v6 only. */ + nm_utils_inet6_ntop (&lnk->local6, NULL)); + } + + g_snprintf (buf, len, + "vxlan" + " id %u" /* id */ + "%s%s" /* group/group6 */ + "%s%s" /* local/local6 */ + "%s" /* dev */ + "%s" /* src_port_min/src_port_max */ + "%s" /* dst_port */ + "%s" /* learning */ + "%s" /* proxy */ + "%s" /* rsc */ + "%s" /* l2miss */ + "%s" /* l3miss */ + "%s" /* tos */ + "%s" /* ttl */ + " ageing %u" /* ageing */ + "%s" /* limit */ + "", + (guint) lnk->id, + str_group, str_group6, + str_local, str_local6, + lnk->parent_ifindex ? nm_sprintf_buf (str_dev, " dev %d", lnk->parent_ifindex) : "", + lnk->src_port_min || lnk->src_port_max ? nm_sprintf_buf (str_src_port, " srcport %u %u", lnk->src_port_min, lnk->src_port_max) : "", + lnk->dst_port ? nm_sprintf_buf (str_dst_port, " dstport %u", lnk->dst_port) : "", + !lnk->learning ? " nolearning" : "", + lnk->proxy ? " proxy" : "", + lnk->rsc ? " rsc" : "", + lnk->l2miss ? " l2miss" : "", + lnk->l3miss ? " l3miss" : "", + lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf (str_tos, " tos %#x", lnk->tos), + lnk->ttl ? nm_sprintf_buf (str_ttl, " ttl %u", lnk->ttl) : "", + lnk->ageing, + lnk->limit ? nm_sprintf_buf (str_limit, " maxaddr %u", lnk->limit) : ""); + return buf; } /** * nm_platform_ip4_address_to_string: * @route: pointer to NMPlatformIP4Address address structure + * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used. + * @len: the size of the @buf. If @buf is %NULL, this argument is ignored. * * A method for converting an address struct into a string representation. * * Example output: "" * - * Returns: a string representation of the address. The returned string - * is an internal buffer, so do not keep or free the returned string. - * Also, this function is not thread safe. + * Returns: a string representation of the address. */ const char * -nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address) +nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *buf, gsize len) { char s_address[INET_ADDRSTRLEN]; char s_peer[INET_ADDRSTRLEN]; @@ -2454,11 +3380,12 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address) const char *str_lft_p, *str_pref_p, *str_time_p; gint32 now = nm_utils_get_monotonic_timestamp_s (); - g_return_val_if_fail (address, "(unknown)"); + if (!nm_utils_to_string_buffer_init_null (address, &buf, &len)) + return buf; inet_ntop (AF_INET, &address->address, s_address, sizeof (s_address)); - if (address->peer_address) { + if (address->peer_address != address->address) { inet_ntop (AF_INET, &address->peer_address, s_peer, sizeof (s_peer)); str_peer = g_strconcat (" ptp ", s_peer, NULL); } @@ -2480,66 +3407,92 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address) now, str_pref, sizeof (str_pref)) ); str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time)); - g_snprintf (_nm_platform_to_string_buffer, sizeof (_nm_platform_to_string_buffer), "%s/%d lft %s pref %s%s%s%s%s src %s", + g_snprintf (buf, len, + "%s/%d lft %s pref %s%s%s%s%s src %s", s_address, address->plen, str_lft_p, str_pref_p, str_time_p, str_peer ? str_peer : "", str_dev, str_label, source_to_string (address->source)); g_free (str_peer); - return _nm_platform_to_string_buffer; + return buf; } -/** - * nm_platform_addr_flags2str: wrapper for rtnl_addr_flags2str(), - * which might not yet support some recent address flags. - **/ -void -nm_platform_addr_flags2str (int flags, char *buf, size_t size) -{ - rtnl_addr_flags2str(flags, buf, size); - - /* There are two recent flags IFA_F_MANAGETEMPADDR and IFA_F_NOPREFIXROUTE. - * If libnl does not yet support them, add them by hand. - * These two flags were introduced together with the extended ifa_flags, - * so, check for that. - */ - if ((flags & IFA_F_MANAGETEMPADDR) && !nm_platform_check_support_libnl_extended_ifa_flags ()) { - strncat (buf, buf[0] ? "," IFA_F_MANAGETEMPADDR_STR : IFA_F_MANAGETEMPADDR_STR, - size - strlen (buf) - 1); - } - if ((flags & IFA_F_NOPREFIXROUTE) && !nm_platform_check_support_libnl_extended_ifa_flags ()) { - strncat (buf, buf[0] ? "," IFA_F_NOPREFIXROUTE_STR : IFA_F_NOPREFIXROUTE_STR, - size - strlen (buf) - 1); - } -} +NM_UTILS_FLAGS2STR_DEFINE (nm_platform_link_flags2str, unsigned, + NM_UTILS_FLAGS2STR (IFF_LOOPBACK, "loopback"), + NM_UTILS_FLAGS2STR (IFF_BROADCAST, "broadcast"), + NM_UTILS_FLAGS2STR (IFF_POINTOPOINT, "pointopoint"), + NM_UTILS_FLAGS2STR (IFF_MULTICAST, "multicast"), + NM_UTILS_FLAGS2STR (IFF_NOARP, "noarp"), + NM_UTILS_FLAGS2STR (IFF_ALLMULTI, "allmulti"), + NM_UTILS_FLAGS2STR (IFF_PROMISC, "promisc"), + NM_UTILS_FLAGS2STR (IFF_MASTER, "master"), + NM_UTILS_FLAGS2STR (IFF_SLAVE, "slave"), + NM_UTILS_FLAGS2STR (IFF_DEBUG, "debug"), + NM_UTILS_FLAGS2STR (IFF_DYNAMIC, "dynamic"), + NM_UTILS_FLAGS2STR (IFF_AUTOMEDIA, "automedia"), + NM_UTILS_FLAGS2STR (IFF_PORTSEL, "portsel"), + NM_UTILS_FLAGS2STR (IFF_NOTRAILERS, "notrailers"), + NM_UTILS_FLAGS2STR (IFF_UP, "up"), + NM_UTILS_FLAGS2STR (IFF_RUNNING, "running"), + NM_UTILS_FLAGS2STR (IFF_LOWER_UP, "lowerup"), + NM_UTILS_FLAGS2STR (IFF_DORMANT, "dormant"), + NM_UTILS_FLAGS2STR (IFF_ECHO, "echo"), +); + +NM_UTILS_ENUM2STR_DEFINE (nm_platform_link_inet6_addrgenmode2str, guint8, + NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_NONE, "none"), + NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_EUI64, "eui64"), + NM_UTILS_ENUM2STR (NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY, "stable-privacy"), +); + +NM_UTILS_FLAGS2STR_DEFINE (nm_platform_addr_flags2str, unsigned, + NM_UTILS_FLAGS2STR (IFA_F_SECONDARY, "secondary"), + NM_UTILS_FLAGS2STR (IFA_F_NODAD, "nodad"), + NM_UTILS_FLAGS2STR (IFA_F_OPTIMISTIC, "optimistic"), + NM_UTILS_FLAGS2STR (IFA_F_HOMEADDRESS, "homeaddress"), + NM_UTILS_FLAGS2STR (IFA_F_DEPRECATED, "deprecated"), + NM_UTILS_FLAGS2STR (IFA_F_TENTATIVE, "tentative"), + NM_UTILS_FLAGS2STR (IFA_F_PERMANENT, "permanent"), + NM_UTILS_FLAGS2STR (IFA_F_MANAGETEMPADDR, "mngtmpaddr"), + NM_UTILS_FLAGS2STR (IFA_F_NOPREFIXROUTE, "noprefixroute"), +); + +NM_UTILS_ENUM2STR_DEFINE (nm_platform_route_scope2str, int, + NM_UTILS_ENUM2STR (RT_SCOPE_NOWHERE, "nowhere"), + NM_UTILS_ENUM2STR (RT_SCOPE_HOST, "host"), + NM_UTILS_ENUM2STR (RT_SCOPE_LINK, "link"), + NM_UTILS_ENUM2STR (RT_SCOPE_SITE, "site"), + NM_UTILS_ENUM2STR (RT_SCOPE_UNIVERSE, "global"), +); /** * nm_platform_ip6_address_to_string: * @route: pointer to NMPlatformIP6Address address structure + * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used. + * @len: the size of the @buf. If @buf is %NULL, this argument is ignored. * * A method for converting an address struct into a string representation. * * Example output: "2001:db8:0:f101::1/64 lft 4294967295 pref 4294967295 time 16922666 on dev em1" * - * Returns: a string representation of the address. The returned string - * is an internal buffer, so do not keep or free the returned string. - * Also, this function is not thread safe. + * Returns: a string representation of the address. */ const char * -nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address) +nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *buf, gsize len) { +#define S_FLAGS_PREFIX " flags " char s_flags[256]; char s_address[INET6_ADDRSTRLEN]; char s_peer[INET6_ADDRSTRLEN]; char str_lft[30], str_pref[30], str_time[50]; char str_dev[TO_STRING_DEV_BUF_SIZE]; - char *str_flags; char *str_peer = NULL; const char *str_lft_p, *str_pref_p, *str_time_p; gint32 now = nm_utils_get_monotonic_timestamp_s (); - g_return_val_if_fail (address, "(unknown)"); + if (!nm_utils_to_string_buffer_init_null (address, &buf, &len)) + return buf; inet_ntop (AF_INET6, &address->address, s_address, sizeof (s_address)); @@ -2550,9 +3503,11 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address) _to_string_dev (NULL, address->ifindex, str_dev, sizeof (str_dev)); - nm_platform_addr_flags2str (address->flags, s_flags, sizeof (s_flags)); - - str_flags = s_flags[0] ? g_strconcat (" flags ", s_flags, NULL) : NULL; + nm_platform_addr_flags2str (address->flags, &s_flags[STRLEN (S_FLAGS_PREFIX)], sizeof (s_flags) - STRLEN (S_FLAGS_PREFIX)); + if (s_flags[STRLEN (S_FLAGS_PREFIX)] == '\0') + s_flags[0] = '\0'; + else + memcpy (s_flags, S_FLAGS_PREFIX, STRLEN (S_FLAGS_PREFIX)); str_lft_p = _lifetime_to_string (address->timestamp, address->lifetime ? address->lifetime : NM_PLATFORM_LIFETIME_PERMANENT, @@ -2564,45 +3519,46 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address) now, str_pref, sizeof (str_pref)) ); str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time)); - g_snprintf (_nm_platform_to_string_buffer, sizeof (_nm_platform_to_string_buffer), "%s/%d lft %s pref %s%s%s%s%s src %s", + g_snprintf (buf, len, + "%s/%d lft %s pref %s%s%s%s%s src %s", s_address, address->plen, str_lft_p, str_pref_p, str_time_p, str_peer ? str_peer : "", str_dev, - str_flags ? str_flags : "", + s_flags, source_to_string (address->source)); - g_free (str_flags); g_free (str_peer); - return _nm_platform_to_string_buffer; + return buf; } /** * nm_platform_ip4_route_to_string: * @route: pointer to NMPlatformIP4Route route structure + * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used. + * @len: the size of the @buf. If @buf is %NULL, this argument is ignored. * * A method for converting a route struct into a string representation. * * Example output: "192.168.1.0/24 via 0.0.0.0 dev em1 metric 0 mss 0" * - * Returns: a string representation of the route. The returned string - * is an internal buffer, so do not keep or free the returned string. - * Also, this function is not thread safe. + * Returns: a string representation of the route. */ const char * -nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route) +nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsize len) { char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN]; char s_pref_src[INET_ADDRSTRLEN]; char str_dev[TO_STRING_DEV_BUF_SIZE]; char str_scope[30]; - g_return_val_if_fail (route, "(unknown)"); + if (!nm_utils_to_string_buffer_init_null (route, &buf, &len)) + return buf; inet_ntop (AF_INET, &route->network, s_network, sizeof(s_network)); inet_ntop (AF_INET, &route->gateway, s_gateway, sizeof(s_gateway)); _to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev)); - g_snprintf (_nm_platform_to_string_buffer, sizeof (_nm_platform_to_string_buffer), + g_snprintf (buf, len, "%s/%d" " via %s" "%s" @@ -2619,38 +3575,39 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route) route->mss, source_to_string (route->source), route->scope_inv ? " scope " : "", - route->scope_inv ? (rtnl_scope2str (nm_platform_route_scope_inv (route->scope_inv), str_scope, sizeof (str_scope))) : "", + route->scope_inv ? (nm_platform_route_scope2str (nm_platform_route_scope_inv (route->scope_inv), str_scope, sizeof (str_scope))) : "", route->pref_src ? " pref-src " : "", route->pref_src ? inet_ntop (AF_INET, &route->pref_src, s_pref_src, sizeof(s_pref_src)) : ""); - return _nm_platform_to_string_buffer; + return buf; } /** * nm_platform_ip6_route_to_string: * @route: pointer to NMPlatformIP6Route route structure + * @buf: (allow-none): an optional buffer. If %NULL, a static buffer is used. + * @len: the size of the @buf. If @buf is %NULL, this argument is ignored. * * A method for converting a route struct into a string representation. * * Example output: "ff02::fb/128 via :: dev em1 metric 0" * - * Returns: a string representation of the route. The returned string - * is an internal buffer, so do not keep or free the returned string. - * Also, this function is not thread safe. + * Returns: a string representation of the route. */ const char * -nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route) +nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsize len) { char s_network[INET6_ADDRSTRLEN], s_gateway[INET6_ADDRSTRLEN]; char str_dev[TO_STRING_DEV_BUF_SIZE]; - g_return_val_if_fail (route, "(unknown)"); + if (!nm_utils_to_string_buffer_init_null (route, &buf, &len)) + return buf; inet_ntop (AF_INET6, &route->network, s_network, sizeof(s_network)); inet_ntop (AF_INET6, &route->gateway, s_gateway, sizeof(s_gateway)); _to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev)); - g_snprintf (_nm_platform_to_string_buffer, sizeof (_nm_platform_to_string_buffer), + g_snprintf (buf, len, "%s/%d" " via %s" "%s" @@ -2664,10 +3621,10 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route) route->metric, route->mss, source_to_string (route->source)); - return _nm_platform_to_string_buffer; + return buf; } -#define _CMP_POINTER(a, b) \ +#define _CMP_SELF(a, b) \ G_STMT_START { \ if ((a) == (b)) \ return 0; \ @@ -2677,6 +3634,19 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route) return 1; \ } G_STMT_END +#define _CMP_DIRECT(a, b) \ + G_STMT_START { \ + if ((a) != (b)) \ + return ((a) < (b)) ? -1 : 1; \ + } G_STMT_END + +#define _CMP_DIRECT_MEMCMP(a, b, size) \ + G_STMT_START { \ + int c = memcmp ((a), (b), (size)); \ + if (c != 0) \ + return c < 0 ? -1 : 1; \ + } G_STMT_END + #define _CMP_FIELD(a, b, field) \ G_STMT_START { \ if (((a)->field) != ((b)->field)) \ @@ -2732,13 +3702,12 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route) int nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b) { - _CMP_POINTER (a, b); + _CMP_SELF (a, b); _CMP_FIELD (a, b, ifindex); _CMP_FIELD (a, b, type); _CMP_FIELD_STR (a, b, name); _CMP_FIELD (a, b, master); _CMP_FIELD (a, b, parent); - _CMP_FIELD (a, b, vlan_id); _CMP_FIELD (a, b, flags); _CMP_FIELD (a, b, connected); _CMP_FIELD (a, b, mtu); @@ -2757,14 +3726,126 @@ nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b) } int +nm_platform_lnk_gre_cmp (const NMPlatformLnkGre *a, const NMPlatformLnkGre *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, parent_ifindex); + _CMP_FIELD (a, b, input_flags); + _CMP_FIELD (a, b, output_flags); + _CMP_FIELD (a, b, input_key); + _CMP_FIELD (a, b, output_key); + _CMP_FIELD (a, b, local); + _CMP_FIELD (a, b, remote); + _CMP_FIELD (a, b, ttl); + _CMP_FIELD (a, b, tos); + _CMP_FIELD_BOOL (a, b, path_mtu_discovery); + return 0; +} + +int +nm_platform_lnk_infiniband_cmp (const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, p_key); + _CMP_FIELD_STR_INTERNED (a, b, mode); + return 0; +} + +int +nm_platform_lnk_ip6tnl_cmp (const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, parent_ifindex); + _CMP_FIELD_MEMCMP (a, b, local); + _CMP_FIELD_MEMCMP (a, b, remote); + _CMP_FIELD (a, b, ttl); + _CMP_FIELD (a, b, tclass); + _CMP_FIELD (a, b, encap_limit); + _CMP_FIELD (a, b, flow_label); + _CMP_FIELD (a, b, proto); + return 0; +} + +int +nm_platform_lnk_ipip_cmp (const NMPlatformLnkIpIp *a, const NMPlatformLnkIpIp *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, parent_ifindex); + _CMP_FIELD (a, b, local); + _CMP_FIELD (a, b, remote); + _CMP_FIELD (a, b, ttl); + _CMP_FIELD (a, b, tos); + _CMP_FIELD_BOOL (a, b, path_mtu_discovery); + return 0; +} + +int +nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatformLnkMacvlan *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, mode); + _CMP_FIELD_BOOL (a, b, no_promisc); + return 0; +} + +int +nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, parent_ifindex); + _CMP_FIELD (a, b, local); + _CMP_FIELD (a, b, remote); + _CMP_FIELD (a, b, ttl); + _CMP_FIELD (a, b, tos); + _CMP_FIELD_BOOL (a, b, path_mtu_discovery); + _CMP_FIELD (a, b, flags); + _CMP_FIELD (a, b, proto); + return 0; +} + +int +nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, id); + _CMP_FIELD (a, b, flags); + return 0; +} + +int +nm_platform_lnk_vxlan_cmp (const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b) +{ + _CMP_SELF (a, b); + _CMP_FIELD (a, b, parent_ifindex); + _CMP_FIELD (a, b, id); + _CMP_FIELD (a, b, group); + _CMP_FIELD (a, b, local); + _CMP_FIELD_MEMCMP (a, b, group6); + _CMP_FIELD_MEMCMP (a, b, local6); + _CMP_FIELD (a, b, tos); + _CMP_FIELD (a, b, ttl); + _CMP_FIELD_BOOL (a, b, learning); + _CMP_FIELD (a, b, ageing); + _CMP_FIELD (a, b, limit); + _CMP_FIELD (a, b, dst_port); + _CMP_FIELD (a, b, src_port_min); + _CMP_FIELD (a, b, src_port_max); + _CMP_FIELD_BOOL (a, b, proxy); + _CMP_FIELD_BOOL (a, b, rsc); + _CMP_FIELD_BOOL (a, b, l2miss); + _CMP_FIELD_BOOL (a, b, l3miss); + return 0; +} + +int nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b) { - _CMP_POINTER (a, b); + _CMP_SELF (a, b); _CMP_FIELD (a, b, ifindex); _CMP_FIELD (a, b, source); _CMP_FIELD (a, b, address); - _CMP_FIELD (a, b, peer_address); _CMP_FIELD (a, b, plen); + _CMP_FIELD (a, b, peer_address); _CMP_FIELD (a, b, timestamp); _CMP_FIELD (a, b, lifetime); _CMP_FIELD (a, b, preferred); @@ -2775,11 +3856,17 @@ nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4A int nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b) { - _CMP_POINTER (a, b); + const struct in6_addr *p_a, *p_b; + + _CMP_SELF (a, b); _CMP_FIELD (a, b, ifindex); _CMP_FIELD (a, b, source); _CMP_FIELD_MEMCMP (a, b, address); - _CMP_FIELD_MEMCMP (a, b, peer_address); + + p_a = nm_platform_ip6_address_get_peer (a); + p_b = nm_platform_ip6_address_get_peer (b); + _CMP_DIRECT_MEMCMP (p_a, p_b, sizeof (*p_a)); + _CMP_FIELD (a, b, plen); _CMP_FIELD (a, b, timestamp); _CMP_FIELD (a, b, lifetime); @@ -2791,7 +3878,7 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b) { - _CMP_POINTER (a, b); + _CMP_SELF (a, b); _CMP_FIELD (a, b, ifindex); _CMP_FIELD (a, b, source); _CMP_FIELD (a, b, network); @@ -2807,7 +3894,7 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b) { - _CMP_POINTER (a, b); + _CMP_SELF (a, b); _CMP_FIELD (a, b, ifindex); _CMP_FIELD (a, b, source); _CMP_FIELD_MEMCMP (a, b, network); @@ -2818,9 +3905,6 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route return 0; } -#undef _CMP_FIELD -#undef _CMP_FIELD_MEMCMP - /** * nm_platform_ip_address_cmp_expiry: * @a: a NMPlatformIPAddress to compare @@ -2839,7 +3923,7 @@ nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatfor { gint64 ta = 0, tb = 0; - _CMP_POINTER (a, b); + _CMP_SELF (a, b); if (a->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || a->lifetime == 0) ta = G_MAXINT64; @@ -2872,8 +3956,6 @@ nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatfor return ta < tb ? -1 : 1; } -#undef _CMP_POINTER - const char * nm_platform_signal_change_type_to_string (NMPlatformSignalChangeType change_type) { @@ -2893,31 +3975,31 @@ static void log_link (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformLink *device, NMPlatformSignalChangeType change_type, gpointer user_data) { - _LOGD ("signal: link %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_link_to_string (device)); + _LOGD ("signal: link %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_link_to_string (device, NULL, 0)); } static void log_ip4_address (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformIP4Address *address, NMPlatformSignalChangeType change_type, gpointer user_data) { - _LOGD ("signal: address 4 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip4_address_to_string (address)); + _LOGD ("signal: address 4 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip4_address_to_string (address, NULL, 0)); } static void log_ip6_address (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformIP6Address *address, NMPlatformSignalChangeType change_type, gpointer user_data) { - _LOGD ("signal: address 6 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip6_address_to_string (address)); + _LOGD ("signal: address 6 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip6_address_to_string (address, NULL, 0)); } static void log_ip4_route (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformIP4Route *route, NMPlatformSignalChangeType change_type, gpointer user_data) { - _LOGD ("signal: route 4 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip4_route_to_string (route)); + _LOGD ("signal: route 4 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip4_route_to_string (route, NULL, 0)); } static void log_ip6_route (NMPlatform *self, NMPObjectType obj_type, int ifindex, NMPlatformIP6Route *route, NMPlatformSignalChangeType change_type, gpointer user_data) { - _LOGD ("signal: route 6 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip6_route_to_string (route)); + _LOGD ("signal: route 6 %7s: %s", nm_platform_signal_change_type_to_string (change_type), nm_platform_ip6_route_to_string (route, NULL, 0)); } /******************************************************************/ @@ -2994,7 +4076,7 @@ const NMPlatformVTableRoute nm_platform_vtable_route_v4 = { .addr_family = AF_INET, .sizeof_route = sizeof (NMPlatformIP4Route), .route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b)) nm_platform_ip4_route_cmp, - .route_to_string = (const char *(*) (const NMPlatformIPXRoute *route)) nm_platform_ip4_route_to_string, + .route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip4_route_to_string, .route_get_all = nm_platform_ip4_route_get_all, .route_add = _vtr_v4_route_add, .route_delete = _vtr_v4_route_delete, @@ -3007,7 +4089,7 @@ const NMPlatformVTableRoute nm_platform_vtable_route_v6 = { .addr_family = AF_INET6, .sizeof_route = sizeof (NMPlatformIP6Route), .route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b)) nm_platform_ip6_route_cmp, - .route_to_string = (const char *(*) (const NMPlatformIPXRoute *route)) nm_platform_ip6_route_to_string, + .route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip6_route_to_string, .route_get_all = nm_platform_ip6_route_get_all, .route_add = _vtr_v6_route_add, .route_delete = _vtr_v6_route_delete, @@ -3051,14 +4133,6 @@ nm_platform_init (NMPlatform *object) { } -#define SIGNAL(signal_id, method) signals[signal_id] = \ - g_signal_new_class_handler (NM_PLATFORM_ ## signal_id, \ - G_OBJECT_CLASS_TYPE (object_class), \ - G_SIGNAL_RUN_FIRST, \ - G_CALLBACK (method), \ - NULL, NULL, NULL, \ - G_TYPE_NONE, 5, NM_TYPE_POBJECT_TYPE, G_TYPE_INT, G_TYPE_POINTER, NM_TYPE_PLATFORM_SIGNAL_CHANGE_TYPE, NM_TYPE_PLATFORM_REASON); - static void nm_platform_class_init (NMPlatformClass *platform_class) { @@ -3069,6 +4143,8 @@ nm_platform_class_init (NMPlatformClass *platform_class) object_class->set_property = set_property; object_class->constructed = constructed; + platform_class->wifi_set_powersave = wifi_set_powersave; + g_object_class_install_property (object_class, PROP_REGISTER_SINGLETON, g_param_spec_boolean (NM_PLATFORM_REGISTER_SINGLETON, "", "", @@ -3077,10 +4153,21 @@ nm_platform_class_init (NMPlatformClass *platform_class) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); +#define SIGNAL(signal, signal_id, method) \ + G_STMT_START { \ + signals[signal] = \ + g_signal_new_class_handler (""signal_id"", \ + G_OBJECT_CLASS_TYPE (object_class), \ + G_SIGNAL_RUN_FIRST, \ + G_CALLBACK (method), \ + NULL, NULL, NULL, \ + G_TYPE_NONE, 4, NM_TYPE_POBJECT_TYPE, G_TYPE_INT, G_TYPE_POINTER, NM_TYPE_PLATFORM_SIGNAL_CHANGE_TYPE); \ + } G_STMT_END + /* Signals */ - SIGNAL (SIGNAL_LINK_CHANGED, log_link) - SIGNAL (SIGNAL_IP4_ADDRESS_CHANGED, log_ip4_address) - SIGNAL (SIGNAL_IP6_ADDRESS_CHANGED, log_ip6_address) - SIGNAL (SIGNAL_IP4_ROUTE_CHANGED, log_ip4_route) - SIGNAL (SIGNAL_IP6_ROUTE_CHANGED, log_ip6_route) + SIGNAL (NM_PLATFORM_SIGNAL_ID_LINK, NM_PLATFORM_SIGNAL_LINK_CHANGED, log_link); + SIGNAL (NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, log_ip4_address); + SIGNAL (NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, log_ip6_address); + SIGNAL (NM_PLATFORM_SIGNAL_ID_IP4_ROUTE, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, log_ip4_route); + SIGNAL (NM_PLATFORM_SIGNAL_ID_IP6_ROUTE, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, log_ip6_route); } |