diff options
Diffstat (limited to 'src/devices')
34 files changed, 1108 insertions, 597 deletions
diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c index a3fa4901..67085752 100644 --- a/src/devices/adsl/nm-atm-manager.c +++ b/src/devices/adsl/nm-atm-manager.c @@ -117,7 +117,7 @@ adsl_add (NMAtmManager *self, GUdevDevice *udev_device) nm_log_dbg (LOGD_HW, "(%s): found ATM device", ifname); atm_index_path = g_strdup_printf ("/sys/class/atm/%s/atmindex", - ASSERT_VALID_PATH_COMPONENT (ifname)); + NM_ASSERT_VALID_PATH_COMPONENT (ifname)); atm_index = (int) nm_platform_sysctl_get_int_checked (NM_PLATFORM_GET, atm_index_path, 10, 0, G_MAXINT, diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c index e7a91e0a..ebb7a319 100644 --- a/src/devices/adsl/nm-device-adsl.c +++ b/src/devices/adsl/nm-device-adsl.c @@ -125,7 +125,8 @@ complete_connection (NMDevice *device, if (s_adsl && !nm_setting_verify (NM_SETTING (s_adsl), NULL, error)) return FALSE; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_ADSL_SETTING_NAME, existing_connections, NULL, @@ -535,7 +536,7 @@ carrier_update_cb (gpointer user_data) char *path; path = g_strdup_printf ("/sys/class/atm/%s/carrier", - ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (NM_DEVICE (self)))); + NM_ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (NM_DEVICE (self)))); carrier = (int) nm_platform_sysctl_get_int_checked (NM_PLATFORM_GET, path, 10, 0, 1, -1); g_free (path); diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index 71226813..a009746d 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -246,9 +246,8 @@ pan_connection_check_create (NMBluezDevice *self) priv->pan_connection = added; nm_log_dbg (LOGD_BT, "bluez[%s] added new Bluetooth connection for NAP device: '%s' (%s)", priv->path, id, uuid); } else { - nm_log_warn (LOGD_BT, "bluez[%s] couldn't add new Bluetooth connection for NAP device: '%s' (%s): %d / %s", - priv->path, id, uuid, error ? error->code : -1, - (error && error->message) ? error->message : "(unknown)"); + nm_log_warn (LOGD_BT, "bluez[%s] couldn't add new Bluetooth connection for NAP device: '%s' (%s): %s", + priv->path, id, uuid, error->message); g_clear_error (&error); } diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c index f66b5abe..766ecc0a 100644 --- a/src/devices/bluetooth/nm-bluez-manager.c +++ b/src/devices/bluetooth/nm-bluez-manager.c @@ -38,6 +38,16 @@ #include "nm-platform.h" #include "nm-dbus-compat.h" +#define _NMLOG_DOMAIN LOGD_BT +#define _NMLOG_PREFIX_NAME "bluez" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), _NMLOG_DOMAIN, \ + "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END + typedef struct { int bluez_version; @@ -146,12 +156,12 @@ manager_bdaddr_added_cb (NMBluez4Manager *bluez_mgr, if (!device) return; - nm_log_info (LOGD_BT, "BT device %s (%s) added (%s%s%s)", - name, - bdaddr, - has_dun ? "DUN" : "", - has_dun && has_nap ? " " : "", - has_nap ? "NAP" : ""); + _LOGI ("BT device %s (%s) added (%s%s%s)", + name, + bdaddr, + has_dun ? "DUN" : "", + has_dun && has_nap ? " " : "", + has_nap ? "NAP" : ""); g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, device); g_object_unref (device); } @@ -163,7 +173,7 @@ setup_version_number (NMBluezManager *self, int bluez_version) g_return_if_fail (!priv->bluez_version); - nm_log_info (LOGD_BT, "use BlueZ version %d", bluez_version); + _LOGI ("use BlueZ version %d", bluez_version); priv->bluez_version = bluez_version; @@ -235,7 +245,7 @@ check_bluez_and_try_setup_final_step (NMBluezManager *self, int bluez_version, c setup_bluez5 (self); break; default: - nm_log_dbg (LOGD_BT, "detecting BlueZ version failed: %s", reason); + _LOGD ("detecting BlueZ version failed: %s", reason); /* cancel current attempts to detect the version. */ cleanup_checking (self, FALSE); diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c index deeebcb6..9d8fd210 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.c +++ b/src/devices/bluetooth/nm-bluez4-adapter.c @@ -203,7 +203,7 @@ get_properties_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) properties = g_variant_get_child_value (ret, 0); - g_variant_lookup (properties, "Address", "s", &priv->address); + (void) g_variant_lookup (properties, "Address", "s", &priv->address); if (g_variant_lookup (properties, "Devices", "^ao", &devices)) { for (i = 0; devices[i]; i++) device_created (priv->proxy, devices[i], self); diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c index e44e87d8..66d171bf 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.c +++ b/src/devices/bluetooth/nm-bluez5-manager.c @@ -213,6 +213,7 @@ get_managed_objects_cb (GDBusProxy *proxy, G_VARIANT_TYPE_DICTIONARY)) { device_added (proxy, path, self); } + g_variant_unref (ifaces); } g_variant_unref (variant); @@ -231,8 +232,7 @@ on_proxy_acquired (GObject *object, priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); if (!priv->proxy) { - nm_log_warn (LOGD_BT, "Couldn't acquire object manager proxy: %s", - error && error->message ? error->message : "(unknown)"); + nm_log_warn (LOGD_BT, "Couldn't acquire object manager proxy: %s", error->message); g_clear_error (&error); return; } diff --git a/src/devices/bluetooth/nm-bluez5-manager.h b/src/devices/bluetooth/nm-bluez5-manager.h index ae5512f8..1c531090 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.h +++ b/src/devices/bluetooth/nm-bluez5-manager.h @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager -- Network link manager * * This program is free software; you can redistribute it and/or modify diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index e151b795..eef4ed0a 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -20,12 +20,13 @@ #include "nm-default.h" +#include "nm-device-bt.h" + #include <stdio.h> #include <string.h> #include "nm-bluez-common.h" #include "nm-bluez-device.h" -#include "nm-device-bt.h" #include "nm-device-private.h" #include "ppp-manager/nm-ppp-manager.h" #include "nm-setting-connection.h" @@ -39,6 +40,7 @@ #include "nm-utils.h" #include "nm-bt-error.h" #include "nm-bt-enum-types.h" +#include "nm-platform.h" #include "nmdbus-device-bt.h" @@ -315,7 +317,8 @@ complete_connection (NMDevice *device, return FALSE; } - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_BLUETOOTH_SETTING_NAME, existing_connections, preferred, @@ -497,8 +500,8 @@ modem_ip4_config_result (NMModem *modem, if (error) { _LOGW (LOGD_MB | LOGD_IP4 | LOGD_BT, - "retrieving IP4 configuration failed: (%d) %s", - error->code, error->message ? error->message : "(unknown)"); + "retrieving IP4 configuration failed: %s", + error->message); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } else @@ -728,8 +731,7 @@ bluez_connect_cb (GObject *object, res, &error); if (!device) { - _LOGW (LOGD_BT, "Error connecting with bluez: %s", - error && error->message ? error->message : "(unknown)"); + _LOGW (LOGD_BT, "Error connecting with bluez: %s", error->message); g_clear_error (&error); nm_device_state_changed (NM_DEVICE (self), diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index cef104e6..b88b2511 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -97,7 +97,8 @@ complete_connection (NMDevice *device, { NMSettingBond *s_bond; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_BOND_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index cc72b003..c35d2863 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -103,7 +103,8 @@ complete_connection (NMDevice *device, { NMSettingBridge *s_bridge; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_BRIDGE_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 2fb84276..6225ae7b 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -158,7 +158,7 @@ _update_s390_subchannels (NMDeviceEthernet *self) dev = (GUdevDevice *) nm_platform_link_get_udev_device (NM_PLATFORM_GET, ifindex); if (!dev) { _LOGW (LOGD_DEVICE | LOGD_HW, "failed to find device %d '%s' with udev", - ifindex, str_if_set (nm_device_get_iface (NM_DEVICE (self)), "(null)")); + ifindex, nm_device_get_iface (NM_DEVICE (self)) ?: "(null)"); goto out; } g_object_ref (dev); @@ -177,7 +177,7 @@ _update_s390_subchannels (NMDeviceEthernet *self) dir = g_dir_open (parent_path, 0, &error); if (!dir) { _LOGW (LOGD_DEVICE | LOGD_HW, "failed to open directory '%s': %s", - parent_path, error && error->message ? error->message : "(unknown)"); + parent_path, error->message); g_clear_error (&error); goto out; } @@ -597,13 +597,13 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, if (!success) { _LOGE (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) couldn't send security configuration to the supplicant: %s", - error ? error->message : "<BUG>"); + error->message); g_clear_error (&error); } } else { _LOGE (LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) couldn't build security configuration: %s", - error ? error->message : "<BUG>"); + error->message); g_clear_error (&error); } @@ -721,7 +721,7 @@ supplicant_connection_timeout_cb (gpointer user_data) NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self); NMActRequest *req; - NMConnection *connection; + NMSettingsConnection *connection; guint64 timestamp = 0; gboolean new_secrets = TRUE; @@ -737,14 +737,14 @@ supplicant_connection_timeout_cb (gpointer user_data) req = nm_device_get_act_request (device); g_assert (req); - connection = nm_act_request_get_applied_connection (req); + connection = nm_act_request_get_settings_connection (req); g_assert (connection); /* Ask for new secrets only if we've never activated this connection * before. If we've connected before, don't bother the user with dialogs, * just retry or fail, and if we never connect the user can fix the * password somewhere else. */ - if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), ×tamp)) + if (nm_settings_connection_get_timestamp (connection, ×tamp)) new_secrets = !timestamp; if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE) @@ -1187,7 +1187,7 @@ wake_on_lan_enable (NMDevice *device) } wol = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; found: - return nmp_utils_ethtool_set_wake_on_lan (nm_device_get_iface (device), wol, password); + return nm_platform_ethtool_set_wake_on_lan (NM_PLATFORM_GET, nm_device_get_iface (device), wol, password); } /****************************************************************/ @@ -1388,7 +1388,8 @@ complete_connection (NMDevice *device, /* Default to an ethernet-only connection, but if a PPPoE setting was given * then PPPoE should be our connection type. */ - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, s_pppoe ? NM_SETTING_PPPOE_SETTING_NAME : NM_SETTING_WIRED_SETTING_NAME, existing_connections, NULL, @@ -1498,6 +1499,11 @@ update_connection (NMDevice *device, NMConnection *connection) nm_connection_add_setting (connection, (NMSetting *) s_wired); } + g_object_set (nm_connection_get_setting_connection (connection), + NM_SETTING_CONNECTION_TYPE, nm_connection_get_setting_pppoe (connection) + ? NM_SETTING_PPPOE_SETTING_NAME + : NM_SETTING_WIRED_SETTING_NAME, NULL); + /* If the device reports a permanent address, use that for the MAC address * and the current MAC, if different, is the cloned MAC. */ @@ -1533,7 +1539,7 @@ get_link_speed (NMDevice *device) NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); guint32 speed; - if (!nmp_utils_ethtool_get_link_speed (nm_device_get_iface (device), &speed)) + if (!nm_platform_ethtool_get_link_speed (NM_PLATFORM_GET, nm_device_get_iface (device), &speed)) return; if (priv->speed == speed) return; diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c index bd0ec002..5ce4333f 100644 --- a/src/devices/nm-device-factory.c +++ b/src/devices/nm-device-factory.c @@ -355,7 +355,7 @@ read_device_factory_paths (void) if (!dir) { nm_log_warn (LOGD_HW, "device plugin: failed to open directory %s: %s", NMPLUGINDIR, - (error && error->message) ? error->message : "(unknown)"); + error->message); g_clear_error (&error); return NULL; } @@ -499,7 +499,7 @@ nm_device_factory_manager_load_factories (NMDeviceFactoryManagerFactoryFunc call factory = create_func (&error); if (!factory) { nm_log_warn (LOGD_HW, "(%s): failed to initialize device factory: %s", - item, error ? error->message : "unknown"); + item, NM_G_ERROR_MSG (error)); g_clear_error (&error); g_module_close (plugin); continue; diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index 79bcb57c..a27af314 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -85,7 +85,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) transport_mode = nm_setting_infiniband_get_transport_mode (s_infiniband); mode_path = g_strdup_printf ("/sys/class/net/%s/mode", - ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (dev))); + NM_ASSERT_VALID_PATH_COMPONENT (nm_device_get_iface (dev))); if (!g_file_test (mode_path, G_FILE_TEST_EXISTS)) { g_free (mode_path); @@ -166,7 +166,8 @@ complete_connection (NMDevice *device, const char *setting_mac; const char *hw_address; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_INFINIBAND_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 0ba813eb..089b1035 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -338,7 +338,8 @@ complete_connection (NMDevice *device, { NMSettingIPTunnel *s_ip_tunnel; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_IP_TUNNEL_SETTING_NAME, existing_connections, NULL, @@ -788,6 +789,12 @@ ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) nm_ip4_config_set_mtu (config, mtu, NM_IP_CONFIG_SOURCE_USER); } +static NMDeviceCapabilities +get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_IS_SOFTWARE; +} + static void unrealize_notify (NMDevice *device) { @@ -876,6 +883,7 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) device_class->update_connection = update_connection; device_class->check_connection_compatible = check_connection_compatible; device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; device_class->ip4_config_pre_commit = ip4_config_pre_commit; device_class->realize_start_notify = realize_start_notify; device_class->unrealize_notify = unrealize_notify; diff --git a/src/devices/nm-device-logging.h b/src/devices/nm-device-logging.h index 6255d6f3..1be17073 100644 --- a/src/devices/nm-device-logging.h +++ b/src/devices/nm-device-logging.h @@ -34,9 +34,9 @@ _nm_device_log_self_to_device (t *self) \ #undef _NMLOG_ENABLED #define _NMLOG_ENABLED(level, domain) ( nm_logging_enabled ((level), (domain)) ) #define _NMLOG(level, domain, ...) \ - nm_log_obj ((level), (domain), (self), \ + nm_log_obj ((level), (domain), (self), "device", \ "(%s): " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - (self) ? str_if_set (nm_device_get_iface (_nm_device_log_self_to_device (self)), "(null)") : "(none)" \ + (self) ? (nm_device_get_iface (_nm_device_log_self_to_device (self)) ?: "(null)") : "(none)" \ _NM_UTILS_MACRO_REST(__VA_ARGS__)) #endif /* __NETWORKMANAGER_DEVICE_LOGGING_H__ */ diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index 2dc9d4f6..cd02cb8e 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -420,7 +420,8 @@ complete_connection (NMDevice *device, { NMSettingMacvlan *s_macvlan; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_MACVLAN_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index a8ae3edc..eac2fb82 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -121,7 +121,8 @@ complete_connection (NMDevice *device, { NMSettingTun *s_tun; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_TUN_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index e6e3708b..4d606e9d 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -439,7 +439,8 @@ complete_connection (NMDevice *device, { NMSettingVlan *s_vlan; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_VLAN_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index 79942458..d308d47a 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -365,7 +365,8 @@ complete_connection (NMDevice *device, { NMSettingVxlan *s_vxlan; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_VXLAN_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index cdd3f7cb..529b3cd8 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -70,13 +70,6 @@ _LOG_DECLARE_SELF (NMDevice); #include "nmdbus-device.h" -static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data); -static gboolean ip_config_valid (NMDeviceState state); -static NMActStageReturn dhcp4_start (NMDevice *self, NMConnection *connection, NMDeviceStateReason *reason); -static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason); -static void nm_device_start_ip_check (NMDevice *self); -static void realize_start_setup (NMDevice *self, const NMPlatformLink *plink); - G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT) #define NM_DEVICE_GET_PRIVATE(o) ((o)->priv) @@ -414,6 +407,12 @@ static void _set_state_full (NMDevice *self, static gboolean queued_ip4_config_change (gpointer user_data); static gboolean queued_ip6_config_change (gpointer user_data); +static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data); +static gboolean ip_config_valid (NMDeviceState state); +static NMActStageReturn dhcp4_start (NMDevice *self, NMConnection *connection, NMDeviceStateReason *reason); +static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason); +static void nm_device_start_ip_check (NMDevice *self); +static void realize_start_setup (NMDevice *self, const NMPlatformLink *plink); /***********************************************************/ @@ -1236,8 +1235,7 @@ update_dynamic_ip_setup (NMDevice *self) nm_lldp_listener_stop (priv->lldp_listener); addr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &addr_length); - if (!nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), - nm_device_get_iface (self), addr, addr_length, &error)) { + if (!nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error)) { _LOGD (LOGD_DEVICE, "LLDP listener %p could not be restarted: %s", priv->lldp_listener, error->message); g_clear_error (&error); @@ -2883,7 +2881,7 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) &error)) { _LOGE (LOGD_DEVICE, "master device '%s' failed to update slave connection: %s", - nm_device_get_iface (master), error ? error->message : "(unknown error)"); + nm_device_get_iface (master), error->message); g_error_free (error); g_object_unref (connection); return NULL; @@ -3164,7 +3162,7 @@ recheck_available (gpointer user_data) } if (new_state > NM_DEVICE_STATE_UNKNOWN) { - _LOGD (LOGD_DEVICE, "device is %savailable, %s %s", + _LOGD (LOGD_DEVICE, "is %savailable, %s %s", now_available ? "" : "not ", new_state == NM_DEVICE_STATE_UNAVAILABLE ? "no change required for" : "will transition to", state_to_string (new_state == NM_DEVICE_STATE_UNAVAILABLE ? state : new_state)); @@ -3565,8 +3563,7 @@ activate_stage2_device_config (NMDevice *self) addr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &addr_length); - if (nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), - nm_device_get_iface (self), addr, addr_length, &error)) + if (nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error)) _LOGD (LOGD_DEVICE, "LLDP listener %p started", priv->lldp_listener); else { _LOGD (LOGD_DEVICE, "LLDP listener %p could not be started: %s", @@ -4675,10 +4672,7 @@ reserve_shared_ip (NMDevice *self, NMSettingIPConfig *s_ip4, NMPlatformIP4Addres } } nm_platform_ip4_address_set_addr (address, start + count, 24); - - g_hash_table_insert (shared_ips, - GUINT_TO_POINTER (address->address), - GUINT_TO_POINTER (TRUE)); + g_hash_table_add (shared_ips, GUINT_TO_POINTER (address->address)); } return TRUE; @@ -5852,7 +5846,8 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection)); g_assert (s_ip6); - priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), + priv->rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET, + nm_device_get_ip_ifindex (self), nm_device_get_ip_iface (self), nm_connection_get_uuid (connection), nm_setting_ip6_config_get_addr_gen_mode (s_ip6), @@ -6631,7 +6626,7 @@ start_sharing (NMDevice *self, NMIP4Config *config) if (!nm_dnsmasq_manager_start (priv->dnsmasq_manager, config, &error)) { _LOGE (LOGD_SHARING, "share: (%s) failed to start dnsmasq: %s", - ip_iface, (error && error->message) ? error->message : "(unknown)"); + ip_iface, error->message); g_error_free (error); nm_act_request_set_shared (req, FALSE); return FALSE; @@ -7145,6 +7140,7 @@ nm_device_reactivate_ip4_config (NMDevice *self, if (priv->ip4_state != IP_NONE) { g_clear_object (&priv->con_ip4_config); + g_clear_object (&priv->ext_ip4_config); priv->con_ip4_config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); nm_ip4_config_merge_setting (priv->con_ip4_config, s_ip4_new, @@ -7175,6 +7171,7 @@ nm_device_reactivate_ip6_config (NMDevice *self, if (priv->ip6_state != IP_NONE) { g_clear_object (&priv->con_ip6_config); + g_clear_object (&priv->ext_ip6_config); priv->con_ip6_config = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); nm_ip6_config_merge_setting (priv->con_ip6_config, s_ip6_new, @@ -7374,7 +7371,10 @@ impl_device_reapply (NMDevice *self, if (settings && g_variant_n_children (settings)) { /* New settings specified inline. */ - connection = nm_simple_connection_new_from_dbus (settings, &error); + connection = _nm_simple_connection_new_from_dbus (settings, + NM_SETTING_PARSE_FLAGS_STRICT + | NM_SETTING_PARSE_FLAGS_NORMALIZE, + &error); if (!connection) { g_prefix_error (&error, "The settings specified are invalid: "); nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message); @@ -7740,7 +7740,7 @@ nm_device_queue_activation (NMDevice *self, NMActRequest *req) must_queue = _carrier_wait_check_act_request_must_queue (self, req); - if (!priv->act_request && !must_queue) { + if (!priv->act_request && !must_queue && nm_device_is_real (self)) { /* Just activate immediately */ if (!_device_activate (self, req)) g_assert_not_reached (); @@ -7926,9 +7926,10 @@ _replace_vpn_config_in_list (GSList **plist, GObject *old, GObject *new) { GSList *old_link; - /* Below, assert that we have an @old instance to replace and that - * @new is not yet tracked. But still, behave correctly in any - * case. */ + /* Below, assert that @new is not yet tracked, but still behave + * correctly in any case. Don't complain for missing @old since + * it could have been removed when the parent device became + * unmanaged. */ if ( old && (old_link = g_slist_find (*plist, old))) { @@ -7936,7 +7937,7 @@ _replace_vpn_config_in_list (GSList **plist, GObject *old, GObject *new) if (new) old_link->data = g_object_ref (new); else - *plist = g_slist_remove_link (*plist, old_link); + *plist = g_slist_delete_link (*plist, old_link); g_object_unref (old); } return TRUE; @@ -7947,12 +7948,9 @@ _replace_vpn_config_in_list (GSList **plist, GObject *old, GObject *new) *plist = g_slist_append (*plist, g_object_ref (new)); else g_return_val_if_reached (TRUE); - g_return_val_if_fail (!old, TRUE); return TRUE; } - /* return FALSE if both @old and @new are unset. */ - g_return_val_if_fail (!old, FALSE); return FALSE; } @@ -8434,7 +8432,7 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - _LOGD (LOGD_HW, "bringing up device."); + _LOGD (LOGD_HW, "bringing up device"); if (NM_DEVICE_GET_CLASS (self)->bring_up) { if (!NM_DEVICE_GET_CLASS (self)->bring_up (self, no_firmware)) @@ -8508,7 +8506,7 @@ nm_device_take_down (NMDevice *self, gboolean block) g_return_if_fail (NM_IS_DEVICE (self)); - _LOGD (LOGD_HW, "taking down device."); + _LOGD (LOGD_HW, "taking down device"); if (NM_DEVICE_GET_CLASS (self)->take_down) { if (!NM_DEVICE_GET_CLASS (self)->take_down (self)) @@ -9668,14 +9666,13 @@ nm_device_recheck_available_connections (NMDevice *self) connection = NM_CONNECTION (iter->data); if (nm_device_check_connection_available (self, - connection, - NM_DEVICE_CHECK_CON_AVAILABLE_NONE, - NULL)) { + connection, + NM_DEVICE_CHECK_CON_AVAILABLE_NONE, + NULL)) { if (available_connections_add (self, connection)) changed = TRUE; - } else { - if (prune_list && g_hash_table_remove (prune_list, connection)) - changed = TRUE; + if (prune_list) + g_hash_table_remove (prune_list, connection); } } @@ -9697,39 +9694,55 @@ nm_device_recheck_available_connections (NMDevice *self) } /** - * nm_device_get_available_connections: + * nm_device_get_best_connection: * @self: the #NMDevice * @specific_object: a specific object path if any + * @error: reason why no connection was returned * - * Returns a list of connections available to activate on the device, taking - * into account any device-specific details given by @specific_object (like - * WiFi access point path). + * Returns a connection that's most suitable for user-initiated activation + * of a device, optionally with a given specific object. * - * Returns: caller-owned #GPtrArray of #NMConnections + * Returns: the #NMSettingsConnection or %NULL (setting an @error) */ -GPtrArray * -nm_device_get_available_connections (NMDevice *self, const char *specific_object) +NMSettingsConnection * +nm_device_get_best_connection (NMDevice *self, + const char *specific_object, + GError **error) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMSettingsConnection *connection = NULL; + NMSettingsConnection *candidate; + guint64 best_timestamp = 0; GHashTableIter iter; - guint num_available; - NMConnection *connection = NULL; - GPtrArray *array = NULL; - num_available = g_hash_table_size (priv->available_connections); - if (num_available > 0) { - array = g_ptr_array_sized_new (num_available); - g_hash_table_iter_init (&iter, priv->available_connections); - while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL)) { - /* If a specific object is given, only include connections that are - * compatible with it. - */ - if ( !specific_object /* << Optimization: we know that the connection is available without @specific_object. */ - || nm_device_check_connection_available (self, connection, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, specific_object)) - g_ptr_array_add (array, connection); + g_hash_table_iter_init (&iter, priv->available_connections); + while (g_hash_table_iter_next (&iter, (gpointer) &candidate, NULL)) { + guint64 candidate_timestamp = 0; + + /* If a specific object is given, only include connections that are + * compatible with it. + */ + if ( specific_object /* << Optimization: we know that the connection is available without @specific_object. */ + && !nm_device_check_connection_available (self, + NM_CONNECTION (candidate), + _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, + specific_object)) + continue; + + nm_settings_connection_get_timestamp (candidate, &candidate_timestamp); + if (!connection || (candidate_timestamp > best_timestamp)) { + connection = candidate; + best_timestamp = candidate_timestamp; } } - return array; + + if (!connection) { + g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION, + "The device '%s' has no connections available for activation.", + nm_device_get_iface (self)); + } + + return connection; } static void @@ -9838,12 +9851,15 @@ nm_device_add_pending_action (NMDevice *self, const char *action, gboolean asser gboolean nm_device_remove_pending_action (NMDevice *self, const char *action, gboolean assert_is_pending) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevicePrivate *priv; GSList *iter, *next; guint count = 0; + g_return_val_if_fail (self, FALSE); g_return_val_if_fail (action, FALSE); + priv = NM_DEVICE_GET_PRIVATE (self); + for (iter = priv->pending_actions; iter; iter = next) { next = iter->next; if (!strcmp (action, iter->data)) { @@ -10352,7 +10368,7 @@ _set_state_full (NMDevice *self, if ( (priv->state == state) && ( state != NM_DEVICE_STATE_UNAVAILABLE || !priv->firmware_missing)) { - _LOGD (LOGD_DEVICE, "device state change: %s -> %s (reason '%s') [%d %d %d]%s", + _LOGD (LOGD_DEVICE, "state change: %s -> %s (reason '%s') [%d %d %d]%s", state_to_string (old_state), state_to_string (state), reason_to_string (reason), @@ -10363,7 +10379,7 @@ _set_state_full (NMDevice *self, return; } - _LOGI (LOGD_DEVICE, "device state change: %s -> %s (reason '%s') [%d %d %d]", + _LOGI (LOGD_DEVICE, "state change: %s -> %s (reason '%s') [%d %d %d]", state_to_string (old_state), state_to_string (state), reason_to_string (reason), @@ -10389,7 +10405,8 @@ _set_state_full (NMDevice *self, if (state <= NM_DEVICE_STATE_UNAVAILABLE) { if (available_connections_del_all (self)) available_connections_notify (self); - _clear_queued_act_request (priv); + if (old_state > NM_DEVICE_STATE_UNAVAILABLE) + _clear_queued_act_request (priv); } /* Update the available connections list when a device first becomes available */ diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 9b9edda4..bd657e68 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -529,8 +529,9 @@ gboolean nm_device_add_pending_action (NMDevice *device, const char *action, gboolean nm_device_remove_pending_action (NMDevice *device, const char *action, gboolean assert_is_pending); gboolean nm_device_has_pending_action (NMDevice *device); -GPtrArray *nm_device_get_available_connections (NMDevice *device, - const char *specific_object); +NMSettingsConnection *nm_device_get_best_connection (NMDevice *device, + const char *specific_object, + GError **error); gboolean nm_device_check_connection_available (NMDevice *device, NMConnection *connection, diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c index 81827817..e678dc67 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/devices/nm-lldp-listener.c @@ -20,33 +20,71 @@ #include "nm-default.h" +#include "nm-lldp-listener.h" + #include <net/ethernet.h> +#include <errno.h> -#include "sd-lldp.h" -#include "lldp.h" -#include "nm-lldp-listener.h" #include "nm-platform.h" #include "nm-utils.h" +#include "sd-lldp.h" + +#include "nm-sd-adapt.h" +#include "lldp.h" + #define MAX_NEIGHBORS 4096 -#define MIN_UPDATE_INTERVAL 2 +#define MIN_UPDATE_INTERVAL_NS (2 * NM_UTILS_NS_PER_SECOND) + +#define LLDP_MAC_NEAREST_BRIDGE ((const struct ether_addr *) ((uint8_t[ETH_ALEN]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e })) +#define LLDP_MAC_NEAREST_NON_TPMR_BRIDGE ((const struct ether_addr *) ((uint8_t[ETH_ALEN]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 })) +#define LLDP_MAC_NEAREST_CUSTOMER_BRIDGE ((const struct ether_addr *) ((uint8_t[ETH_ALEN]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 })) + +typedef enum { + LLDP_ATTR_TYPE_NONE, + LLDP_ATTR_TYPE_UINT32, + LLDP_ATTR_TYPE_STRING, +} LldpAttrType; + +typedef enum { + /* the order of the enum values determines the order of the fields in + * the variant. */ + LLDP_ATTR_ID_PORT_DESCRIPTION, + LLDP_ATTR_ID_SYSTEM_NAME, + LLDP_ATTR_ID_SYSTEM_DESCRIPTION, + LLDP_ATTR_ID_SYSTEM_CAPABILITIES, + LLDP_ATTR_ID_IEEE_802_1_PVID, + LLDP_ATTR_ID_IEEE_802_1_PPVID, + LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, + LLDP_ATTR_ID_IEEE_802_1_VID, + LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, + _LLDP_PROP_ID_COUNT, +} LldpAttrId; + +typedef struct { + LldpAttrType attr_type; + union { + guint32 v_uint32; + char *v_string; + }; +} LldpAttrData; typedef struct { char *iface; int ifindex; sd_lldp *lldp_handle; GHashTable *lldp_neighbors; - guint timer; - guint num_pending_events; + + /* the timestamp in nsec until which we delay updates. */ + gint64 ratelimit_next; + guint ratelimit_id; + GVariant *variant; } NMLldpListenerPrivate; -enum { - PROP_0, +NM_GOBJECT_PROPERTIES_DEFINE (NMLldpListener, PROP_NEIGHBORS, - - LAST_PROP -}; +); G_DEFINE_TYPE (NMLldpListener, nm_lldp_listener, G_TYPE_OBJECT) @@ -58,12 +96,14 @@ typedef struct { char *chassis_id; char *port_id; - int dest; + struct ether_addr destination_address; + + bool valid:1; - GHashTable *tlvs; -} LLDPNeighbor; + LldpAttrData attrs[_LLDP_PROP_ID_COUNT]; -static void process_lldp_neighbors (NMLldpListener *self); + GVariant *variant; +} LldpNeighbor; /*****************************************************************************/ @@ -89,43 +129,139 @@ static void process_lldp_neighbors (NMLldpListener *self); } \ } G_STMT_END \ +#define LOG_NEIGH_FMT "CHASSIS=%s%s%s PORT=%s%s%s" +#define LOG_NEIGH_ARG(neigh) NM_PRINT_FMT_QUOTE_STRING ((neigh)->chassis_id), NM_PRINT_FMT_QUOTE_STRING ((neigh)->port_id) + /*****************************************************************************/ +static gboolean +ether_addr_equal (const struct ether_addr *a1, const struct ether_addr *a2) +{ + nm_assert (a1); + nm_assert (a2); + + G_STATIC_ASSERT_EXPR (sizeof (*a1) == ETH_ALEN); + return memcmp (a1, a2, ETH_ALEN) == 0; +} + +static guint32 +_access_uint8 (const void *data) +{ + return *((const guint8 *) data); +} + +static guint32 +_access_uint16 (const void *data) +{ + guint16 v; + + memcpy (&v, data, sizeof (v)); + return ntohs (v); +} + +/*****************************************************************************/ + +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_lldp_attr_id_to_name, LldpAttrId, + NM_UTILS_LOOKUP_DEFAULT_WARN (NULL), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_PORT_DESCRIPTION, NM_LLDP_ATTR_PORT_DESCRIPTION), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_SYSTEM_NAME, NM_LLDP_ATTR_SYSTEM_NAME), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_SYSTEM_DESCRIPTION, NM_LLDP_ATTR_SYSTEM_DESCRIPTION), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_SYSTEM_CAPABILITIES, NM_LLDP_ATTR_SYSTEM_CAPABILITIES), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_PVID, NM_LLDP_ATTR_IEEE_802_1_PVID), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID, NM_LLDP_ATTR_IEEE_802_1_PPVID), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_VID, NM_LLDP_ATTR_IEEE_802_1_VID), + NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME), + NM_UTILS_LOOKUP_ITEM_IGNORE (_LLDP_PROP_ID_COUNT), +); + +_NM_UTILS_LOOKUP_DEFINE (static, _lldp_attr_id_to_type, LldpAttrId, LldpAttrType, + NM_UTILS_LOOKUP_DEFAULT_WARN (LLDP_ATTR_TYPE_NONE), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_PORT_DESCRIPTION, LLDP_ATTR_TYPE_STRING), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_SYSTEM_NAME, LLDP_ATTR_TYPE_STRING), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_SYSTEM_DESCRIPTION, LLDP_ATTR_TYPE_STRING), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_SYSTEM_CAPABILITIES, LLDP_ATTR_TYPE_UINT32), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_PVID, LLDP_ATTR_TYPE_UINT32), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID, LLDP_ATTR_TYPE_UINT32), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, LLDP_ATTR_TYPE_UINT32), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_VID, LLDP_ATTR_TYPE_UINT32), + NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, LLDP_ATTR_TYPE_STRING), + NM_UTILS_LOOKUP_ITEM_IGNORE (_LLDP_PROP_ID_COUNT), +); + static void -gvalue_destroy (gpointer data) +_lldp_attr_set_str (LldpAttrData *pdata, LldpAttrId attr_id, const char *v_string) { - GValue *value = (GValue *) data; + nm_assert (pdata); + nm_assert (_lldp_attr_id_to_type (attr_id) == LLDP_ATTR_TYPE_STRING); + + pdata = &pdata[attr_id]; - g_value_unset (value); - g_slice_free (GValue, value); + /* we ignore duplicate fields silently. */ + if (pdata->attr_type != LLDP_ATTR_TYPE_NONE) + return; + pdata->attr_type = LLDP_ATTR_TYPE_STRING; + pdata->v_string = g_strdup (v_string ?: ""); } -static GValue * -gvalue_new_nstr (const char *str, guint16 len) +static void +_lldp_attr_set_str_ptr (LldpAttrData *pdata, LldpAttrId attr_id, const void *str, gsize len) { - GValue *value; + const char *s = str; + const char *tmp; + gsize len0 = len; + gs_free char *str_free = NULL; + + nm_assert (pdata); + nm_assert (_lldp_attr_id_to_type (attr_id) == LLDP_ATTR_TYPE_STRING); + + pdata = &pdata[attr_id]; + + /* we ignore duplicate fields silently. */ + if (pdata->attr_type != LLDP_ATTR_TYPE_NONE) + return; + + pdata->attr_type = LLDP_ATTR_TYPE_STRING; - value = g_slice_new0 (GValue); - g_value_init (value, G_TYPE_STRING); - g_value_take_string (value, strndup (str, len)); - return value; + /* truncate at first NUL, including removing trailing NULs*/ + tmp = memchr (s, '\0', len); + if (tmp) + len = tmp - s; + + if (!len) { + pdata->v_string = g_strdup (""); + return; + } + + if (len0 <= len || s[len] != '\0') { + /* hmpf, g_strescape needs a trailing NUL. Need to clone */ + s = str_free = g_strndup (s, len); + } + + pdata->v_string = g_strescape (s, NULL); } -static GValue * -gvalue_new_uint (guint val) +static void +_lldp_attr_set_uint32 (LldpAttrData *pdata, LldpAttrId attr_id, guint32 v_uint32) { - GValue *value; + nm_assert (pdata); + nm_assert (_lldp_attr_id_to_type (attr_id) == LLDP_ATTR_TYPE_UINT32); + + pdata = &pdata[attr_id]; - value = g_slice_new0 (GValue); - g_value_init (value, G_TYPE_UINT); - g_value_set_uint (value, val); - return value; + /* we ignore duplicate fields silently. */ + if (pdata->attr_type != LLDP_ATTR_TYPE_NONE) + return; + pdata->attr_type = LLDP_ATTR_TYPE_UINT32; + pdata->v_uint32 = v_uint32; } +/*****************************************************************************/ + static guint lldp_neighbor_id_hash (gconstpointer ptr) { - const LLDPNeighbor *neigh = ptr; + const LldpNeighbor *neigh = ptr; guint hash; hash = 23423423u + ((guint) (neigh->chassis_id ? g_str_hash (neigh->chassis_id) : 12321u)); @@ -135,303 +271,453 @@ lldp_neighbor_id_hash (gconstpointer ptr) return hash; } +static int +lldp_neighbor_id_cmp (gconstpointer a, gconstpointer b) +{ + const LldpNeighbor *x = a, *y = b; + int c; + + if (x->chassis_id_type != y->chassis_id_type) + return x->chassis_id_type < y->chassis_id_type ? -1 : 1; + if (x->port_id_type != y->port_id_type) + return x->port_id_type < y->port_id_type ? -1 : 1; + c = g_strcmp0 (x->chassis_id, y->chassis_id); + if (c == 0) + c = g_strcmp0 (x->port_id, y->port_id); + return c < 0 ? -1 : (c > 0 ? 1 : 0); +} + static gboolean lldp_neighbor_id_equal (gconstpointer a, gconstpointer b) { - const LLDPNeighbor *x = a, *y = b; - - return x->chassis_id_type == y->chassis_id_type && - x->port_id_type == y->port_id_type && - !g_strcmp0 (x->chassis_id, y->chassis_id) && - !g_strcmp0 (x->port_id, y->port_id); + return lldp_neighbor_id_cmp (a, b) == 0; } static void -lldp_neighbor_free (LLDPNeighbor *neighbor) +lldp_neighbor_free (LldpNeighbor *neighbor) { + LldpAttrId attr_id; + if (neighbor) { g_free (neighbor->chassis_id); g_free (neighbor->port_id); - g_hash_table_unref (neighbor->tlvs); - g_slice_free (LLDPNeighbor, neighbor); + for (attr_id = 0; attr_id < _LLDP_PROP_ID_COUNT; attr_id++) { + if (neighbor->attrs[attr_id].attr_type == LLDP_ATTR_TYPE_STRING) + g_free (neighbor->attrs[attr_id].v_string); + } + g_clear_pointer (&neighbor->variant, g_variant_unref); + g_slice_free (LldpNeighbor, neighbor); } } static void -lldp_neighbor_freep (LLDPNeighbor **ptr) +lldp_neighbor_freep (LldpNeighbor **ptr) { lldp_neighbor_free (*ptr); } static gboolean -lldp_neighbor_equal (LLDPNeighbor *a, LLDPNeighbor *b) +lldp_neighbor_equal (LldpNeighbor *a, LldpNeighbor *b) { - GHashTableIter iter; - gpointer k, v; + LldpAttrId attr_id; - g_return_val_if_fail (a && a->tlvs, FALSE); - g_return_val_if_fail (b && b->tlvs, FALSE); + nm_assert (a); + nm_assert (b); if ( a->chassis_id_type != b->chassis_id_type || a->port_id_type != b->port_id_type - || a->dest != b->dest - || g_strcmp0 (a->chassis_id, b->chassis_id) - || g_strcmp0 (a->port_id, b->port_id)) - return FALSE; - - if (g_hash_table_size (a->tlvs) != g_hash_table_size (b->tlvs)) + || ether_addr_equal (&a->destination_address, &b->destination_address) + || !nm_streq0 (a->chassis_id, b->chassis_id) + || !nm_streq0 (a->port_id, b->port_id)) return FALSE; - g_hash_table_iter_init (&iter, a->tlvs); - while (g_hash_table_iter_next (&iter, &k, &v)) { - GValue *value_a, *value_b; - - value_a = v; - value_b = g_hash_table_lookup (b->tlvs, k); - - if (!value_b) + for (attr_id = 0; attr_id < _LLDP_PROP_ID_COUNT; attr_id++) { + if (a->attrs[attr_id].attr_type != b->attrs[attr_id].attr_type) return FALSE; - - g_return_val_if_fail (G_VALUE_TYPE (value_a) == G_VALUE_TYPE (value_b), FALSE); - - if (G_VALUE_HOLDS_STRING (value_a)) { - if (g_strcmp0 (g_value_get_string (value_a), g_value_get_string (value_b))) + switch (a->attrs[attr_id].attr_type) { + case LLDP_ATTR_TYPE_UINT32: + if (a->attrs[attr_id].v_uint32 != b->attrs[attr_id].v_uint32) return FALSE; - } else if (G_VALUE_HOLDS_UINT (value_a)) { - if (g_value_get_uint (value_a) != g_value_get_uint (value_b)) + break; + case LLDP_ATTR_TYPE_STRING: + if (!nm_streq (a->attrs[attr_id].v_string, b->attrs[attr_id].v_string)) return FALSE; - } else - g_return_val_if_reached (FALSE); + break; + default: + nm_assert (a->attrs[attr_id].attr_type == LLDP_ATTR_TYPE_NONE); + break; + } } return TRUE; } -static gboolean -lldp_hash_table_equal (GHashTable *a, GHashTable *b) +static LldpNeighbor * +lldp_neighbor_new (sd_lldp_neighbor *neighbor_sd, GError **error) { - GHashTableIter iter; - gpointer val; - - g_return_val_if_fail (a, FALSE); - g_return_val_if_fail (b, FALSE); + nm_auto (lldp_neighbor_freep) LldpNeighbor *neigh = NULL; + uint8_t chassis_id_type, port_id_type; + uint16_t data16; + uint8_t *data8; + const void *chassis_id, *port_id; + gsize chassis_id_len, port_id_len, len; + const char *str; + int r; + + r = sd_lldp_neighbor_get_chassis_id (neighbor_sd, &chassis_id_type, + &chassis_id, &chassis_id_len); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading chassis-id: %s", g_strerror (-r)); + return NULL; + } + if (chassis_id_len < 1) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "empty chassis-id"); + return NULL; + } - if (g_hash_table_size (a) != g_hash_table_size (b)) - return FALSE; + r = sd_lldp_neighbor_get_port_id (neighbor_sd, &port_id_type, + &port_id, &port_id_len); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading port-id: %s", g_strerror (-r)); + return NULL; + } + if (port_id_len < 1) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "empty port-id"); + return NULL; + } - g_hash_table_iter_init (&iter, a); - while (g_hash_table_iter_next (&iter, NULL, &val)) { - LLDPNeighbor *neigh_a, *neigh_b; + neigh = g_slice_new0 (LldpNeighbor); + neigh->chassis_id_type = chassis_id_type; + neigh->port_id_type = port_id_type; - neigh_a = val; - neigh_b = g_hash_table_lookup (b, val); + r = sd_lldp_neighbor_get_destination_address (neighbor_sd, &neigh->destination_address); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed getting destination address: %s", g_strerror (-r)); + goto out; + } - if (!neigh_b) - return FALSE; + switch (chassis_id_type) { + case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: + case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: + case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: + case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: + neigh->chassis_id = g_strndup ((const char *) chassis_id, chassis_id_len); + break; + case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: + neigh->chassis_id = nm_utils_hwaddr_ntoa (chassis_id, chassis_id_len); + break; + default: + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "unsupported chassis-id type %d", chassis_id_type); + goto out; + } - if (!lldp_neighbor_equal (neigh_a, neigh_b)) - return FALSE; + switch (port_id_type) { + case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: + case LLDP_PORT_SUBTYPE_INTERFACE_NAME: + case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: + case LLDP_PORT_SUBTYPE_PORT_COMPONENT: + neigh->port_id = strndup ((char *) port_id, port_id_len); + break; + case LLDP_PORT_SUBTYPE_MAC_ADDRESS: + neigh->port_id = nm_utils_hwaddr_ntoa (port_id, port_id_len); + break; + default: + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "unsupported port-id type %d", port_id_type); + goto out; } - return TRUE; -} + if (sd_lldp_neighbor_get_port_description (neighbor_sd, &str) == 0) + _lldp_attr_set_str (neigh->attrs, LLDP_ATTR_ID_PORT_DESCRIPTION, str); -static gboolean -lldp_timeout (gpointer user_data) -{ - NMLldpListener *self = user_data; - NMLldpListenerPrivate *priv; + if (sd_lldp_neighbor_get_system_name (neighbor_sd, &str) == 0) + _lldp_attr_set_str (neigh->attrs, LLDP_ATTR_ID_SYSTEM_NAME, str); - g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), G_SOURCE_REMOVE); + if (sd_lldp_neighbor_get_system_description (neighbor_sd, &str) == 0) + _lldp_attr_set_str (neigh->attrs, LLDP_ATTR_ID_SYSTEM_DESCRIPTION, str); - priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + if (sd_lldp_neighbor_get_system_capabilities (neighbor_sd, &data16) == 0) + _lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_SYSTEM_CAPABILITIES, data16); - priv->timer = 0; + r = sd_lldp_neighbor_tlv_rewind (neighbor_sd); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading tlv (rewind): %s", g_strerror (-r)); + goto out; + } + do { + guint8 oui[3]; + guint8 subtype; + + r = sd_lldp_neighbor_tlv_get_oui (neighbor_sd, oui, &subtype); + if (r < 0) { + if (r == -ENXIO) + continue; + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading tlv: %s", g_strerror (-r)); + goto out; + } - if (priv->num_pending_events) - process_lldp_neighbors (self); + if (!( memcmp (oui, LLDP_OUI_802_1, sizeof (oui)) == 0 + && NM_IN_SET (subtype, + LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID, + LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID, + LLDP_OUI_802_1_SUBTYPE_VLAN_NAME))) + continue; + + if (sd_lldp_neighbor_tlv_get_raw (neighbor_sd, (void *) &data8, &len) < 0) + continue; + + /* skip over leading TLV, OUI and subtype */ +#ifdef WITH_MORE_ASSERTS + { + guint8 check_hdr[] = { + 0xfe | (((len - 2) >> 8) & 0x01), ((len - 2) & 0xFF), + oui[0], oui[1], oui[2], + subtype + }; + + nm_assert (len > 2 + 3 +1); + nm_assert (memcmp (data8, check_hdr, sizeof check_hdr) == 0); + } +#endif + if (len <= 6) + continue; + data8 += 6; + len -= 6; + + /*if (memcmp (oui, LLDP_OUI_802_1, sizeof (oui)) == 0)*/ + { + switch (subtype) { + case LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID: + if (len != 2) + continue; + _lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_PVID, + _access_uint16 (data8)); + break; + case LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID: + if (len != 3) + continue; + _lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, + _access_uint8 (&data8[0])); + _lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_PPVID, + _access_uint16 (&data8[1])); + break; + case LLDP_OUI_802_1_SUBTYPE_VLAN_NAME: { + int l; + + if (len <= 3) + continue; + + l = data8[2]; + if (len != 3 + l) + continue; + + _lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_VID, + _access_uint16 (&data8[0])); + _lldp_attr_set_str_ptr (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, + &data8[3], len); + break; + } + default: + g_assert_not_reached (); + } + } + } while (sd_lldp_neighbor_tlv_next (neighbor_sd) > 0); - return G_SOURCE_REMOVE; + neigh->valid = TRUE; + +out: + return nm_unauto (&neigh); } -static void -process_lldp_neighbors (NMLldpListener *self) +static GVariant * +lldp_neighbor_to_variant (LldpNeighbor *neigh) { - NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - nm_auto_free sd_lldp_packet **packets = NULL; - GHashTable *hash; - int num, i; - - g_return_if_fail (priv->lldp_handle); - - num = sd_lldp_get_packets (priv->lldp_handle, &packets); - if (num < 0) { - _LOGD ("process: error %d retrieving neighbor packets for %s", - num, priv->iface); - return; + GVariantBuilder builder; + const char *dest_str; + LldpAttrId attr_id; + + if (neigh->variant) + return neigh->variant; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + + g_variant_builder_add (&builder, "{sv}", + NM_LLDP_ATTR_CHASSIS_ID_TYPE, + g_variant_new_uint32 (neigh->chassis_id_type)); + g_variant_builder_add (&builder, "{sv}", + NM_LLDP_ATTR_CHASSIS_ID, + g_variant_new_string (neigh->chassis_id)); + g_variant_builder_add (&builder, "{sv}", + NM_LLDP_ATTR_PORT_ID_TYPE, + g_variant_new_uint32 (neigh->port_id_type)); + g_variant_builder_add (&builder, "{sv}", + NM_LLDP_ATTR_PORT_ID, + g_variant_new_string (neigh->port_id)); + + if (ether_addr_equal (&neigh->destination_address, LLDP_MAC_NEAREST_BRIDGE)) + dest_str = NM_LLDP_DEST_NEAREST_BRIDGE; + else if (ether_addr_equal (&neigh->destination_address, LLDP_MAC_NEAREST_NON_TPMR_BRIDGE)) + dest_str = NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE; + else if (ether_addr_equal (&neigh->destination_address, LLDP_MAC_NEAREST_CUSTOMER_BRIDGE)) + dest_str = NM_LLDP_DEST_NEAREST_CUSTOMER_BRIDGE; + else + dest_str = NULL; + if (dest_str) { + g_variant_builder_add (&builder, "{sv}", + NM_LLDP_ATTR_DESTINATION, + g_variant_new_string (dest_str)); } - hash = g_hash_table_new_full (lldp_neighbor_id_hash, lldp_neighbor_id_equal, - (GDestroyNotify) lldp_neighbor_free, NULL); - - for (i = 0; packets && i < num; i++) { - nm_auto (lldp_neighbor_freep) LLDPNeighbor *neigh = NULL; - uint8_t chassis_id_type, port_id_type, *chassis_id, *port_id, data8; - uint16_t chassis_id_len, port_id_len, len, data16; - GValue *value; - char *str; - int r; - - if (i >= MAX_NEIGHBORS) - goto next_packet; - - r = sd_lldp_packet_read_chassis_id (packets[i], &chassis_id_type, - &chassis_id, &chassis_id_len); - if (r < 0) - goto next_packet; - - r = sd_lldp_packet_read_port_id (packets[i], &port_id_type, - &port_id, &port_id_len); - if (r < 0) - goto next_packet; - - neigh = g_slice_new0 (LLDPNeighbor); - neigh->tlvs = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy); - neigh->chassis_id_type = chassis_id_type; - neigh->port_id_type = port_id_type; - sd_lldp_packet_get_destination_type (packets[i], &neigh->dest); - - if (chassis_id_len < 1) - goto next_packet; - - switch (chassis_id_type) { - case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: - case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: - case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: - case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: - neigh->chassis_id = g_strndup ((const char *) chassis_id, chassis_id_len); - break; - case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: - neigh->chassis_id = nm_utils_hwaddr_ntoa (chassis_id, chassis_id_len); - break; - default: - _LOGD ("process: unsupported chassis ID type %d", chassis_id_type); - goto next_packet; - } - - if (port_id_len < 1) - goto next_packet; + for (attr_id = 0; attr_id < _LLDP_PROP_ID_COUNT; attr_id++) { + const LldpAttrData *data = &neigh->attrs[attr_id]; - switch (port_id_type) { - case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: - case LLDP_PORT_SUBTYPE_INTERFACE_NAME: - case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: - case LLDP_PORT_SUBTYPE_PORT_COMPONENT: - neigh->port_id = strndup ((char *) port_id, port_id_len); + nm_assert (NM_IN_SET (data->attr_type, _lldp_attr_id_to_type (attr_id), LLDP_ATTR_TYPE_NONE)); + switch (data->attr_type) { + case LLDP_ATTR_TYPE_UINT32: + g_variant_builder_add (&builder, "{sv}", + _lldp_attr_id_to_name (attr_id), + g_variant_new_uint32 (data->v_uint32)); break; - case LLDP_PORT_SUBTYPE_MAC_ADDRESS: - neigh->port_id = nm_utils_hwaddr_ntoa (port_id, port_id_len); + case LLDP_ATTR_TYPE_STRING: + g_variant_builder_add (&builder, "{sv}", + _lldp_attr_id_to_name (attr_id), + g_variant_new_string (data->v_string)); break; default: - _LOGD ("process: unsupported port ID type %d", port_id_type); - goto next_packet; - } - - if (sd_lldp_packet_read_port_description (packets[i], &str, &len) == 0) { - value = gvalue_new_nstr (str, len); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_PORT_DESCRIPTION, value); - } - - if (sd_lldp_packet_read_system_name (packets[i], &str, &len) == 0) { - value = gvalue_new_nstr (str, len); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_NAME, value); - } - - if (sd_lldp_packet_read_system_description (packets[i], &str, &len) == 0) { - value = gvalue_new_nstr (str, len); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, value); - } - - if (sd_lldp_packet_read_system_capability (packets[i], &data16) == 0) { - value = gvalue_new_uint (data16); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_CAPABILITIES, value); - } - - if (sd_lldp_packet_read_port_vlan_id (packets[i], &data16) == 0) { - value = gvalue_new_uint (data16); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PVID, value); + break; } + } - if (sd_lldp_packet_read_port_protocol_vlan_id (packets[i], &data8, &data16) == 0) { - value = gvalue_new_uint (data16); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID, value); + return (neigh->variant = g_variant_ref_sink (g_variant_builder_end (&builder))); +} - value = gvalue_new_uint (data8); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS, value); - } +/*****************************************************************************/ - if (sd_lldp_packet_read_vlan_name (packets[i], &data16, &str, &len) == 0) { - value = gvalue_new_uint (data16); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VID, value); +static void +data_changed_notify (NMLldpListener *self, NMLldpListenerPrivate *priv) +{ + nm_clear_g_variant (&priv->variant); + _notify (self, PROP_NEIGHBORS); +} - value = gvalue_new_nstr (str, len); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME, value); - } +static gboolean +data_changed_timeout (gpointer user_data) +{ + NMLldpListener *self = user_data; + NMLldpListenerPrivate *priv; - _LOGD ("process: new neigh: CHASSIS='%s' PORT='%s'", - neigh->chassis_id, neigh->port_id); + g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), G_SOURCE_REMOVE); - g_hash_table_add (hash, neigh); - neigh = NULL; -next_packet: - sd_lldp_packet_unref (packets[i]); - } + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - if (lldp_hash_table_equal (priv->lldp_neighbors, hash)) { - g_hash_table_destroy (hash); - } else { - g_hash_table_destroy (priv->lldp_neighbors); - priv->lldp_neighbors = hash; - nm_clear_g_variant (&priv->variant); - g_object_notify (G_OBJECT (self), NM_LLDP_LISTENER_NEIGHBORS); - } + priv->ratelimit_id = 0; + priv->ratelimit_next = nm_utils_get_monotonic_timestamp_ns() + MIN_UPDATE_INTERVAL_NS; + data_changed_notify (self, priv); + return G_SOURCE_REMOVE; +} - /* Since the processing of the neighbor list is potentially - * expensive when there are many neighbors, coalesce multiple - * events arriving in short time. - */ - priv->timer = g_timeout_add_seconds (MIN_UPDATE_INTERVAL, lldp_timeout, self); - priv->num_pending_events = 0; +static void +data_changed_schedule (NMLldpListener *self) +{ + NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + gint64 now; + + now = nm_utils_get_monotonic_timestamp_ns (); + if (now >= priv->ratelimit_next) { + nm_clear_g_source (&priv->ratelimit_id); + priv->ratelimit_next = now + MIN_UPDATE_INTERVAL_NS; + data_changed_notify (self, priv); + } else if (!priv->ratelimit_id) + priv->ratelimit_id = g_timeout_add (NM_UTILS_NS_TO_MSEC_CEIL (priv->ratelimit_next - now), data_changed_timeout, self); } static void -lldp_event_handler (sd_lldp *lldp, int event, void *userdata) +process_lldp_neighbor (NMLldpListener *self, sd_lldp_neighbor *neighbor_sd, gboolean neighbor_valid) { - NMLldpListener *self = userdata; NMLldpListenerPrivate *priv; + nm_auto (lldp_neighbor_freep) LldpNeighbor *neigh = NULL; + LldpNeighbor *neigh_old; + gs_free_error GError *parse_error = NULL; + GError **p_parse_error; + gboolean changed = FALSE; g_return_if_fail (NM_IS_LLDP_LISTENER (self)); priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - if (priv->timer > 0) { - priv->num_pending_events++; + g_return_if_fail (priv->lldp_handle); + g_return_if_fail (neighbor_sd); + + p_parse_error = _LOGT_ENABLED () ? &parse_error : NULL; + + neigh = lldp_neighbor_new (neighbor_sd, p_parse_error); + if (!neigh) { + _LOGT ("process: failed to parse neighbor: %s", parse_error->message); + return; + } + + if (!neigh->valid) + neighbor_valid = FALSE; + + neigh_old = g_hash_table_lookup (priv->lldp_neighbors, neigh); + if (neigh_old) { + if (!neighbor_valid) { + _LOGT ("process: %s neigh: "LOG_NEIGH_FMT"%s%s%s", + "remove", LOG_NEIGH_ARG (neigh), + NM_PRINT_FMT_QUOTED (parse_error, " (failed to parse: ", parse_error->message, ")", "")); + + g_hash_table_remove (priv->lldp_neighbors, neigh_old); + changed = TRUE; + goto done; + } else if (lldp_neighbor_equal (neigh_old, neigh)) + return; + } else if (!neighbor_valid) { + if (parse_error) + _LOGT ("process: failed to parse neighbor: %s", parse_error->message); + return; + } + + /* ensure that we have at most MAX_NEIGHBORS entires */ + if ( !neigh_old /* only matters in the "add" case. */ + && (g_hash_table_size (priv->lldp_neighbors) + 1 > MAX_NEIGHBORS)) { + _LOGT ("process: ignore neighbor due to overall limit of %d", MAX_NEIGHBORS); return; } - process_lldp_neighbors (self); + _LOGD ("process: %s neigh: "LOG_NEIGH_FMT, + neigh_old ? "update" : "new", + LOG_NEIGH_ARG (neigh)); + + changed = TRUE; + g_hash_table_add (priv->lldp_neighbors, nm_unauto (&neigh)); + +done: + if (changed) + data_changed_schedule (self); +} + +static void +lldp_event_handler (sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) +{ + process_lldp_neighbor (userdata, n, event != SD_LLDP_EVENT_REMOVED); } gboolean -nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface, - const guint8 *mac, guint mac_len, GError **error) +nm_lldp_listener_start (NMLldpListener *self, int ifindex, GError **error) { NMLldpListenerPrivate *priv; int ret; g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), FALSE); g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (iface, FALSE); g_return_val_if_fail (!error || !*error, FALSE); priv = NM_LLDP_LISTENER_GET_PRIVATE (self); @@ -442,43 +728,38 @@ nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface, return FALSE; } - if (!mac || mac_len != ETH_ALEN) { + ret = sd_lldp_new (&priv->lldp_handle, ifindex); + if (ret < 0) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, - "unsupported device"); + "initialization failed"); return FALSE; } - ret = sd_lldp_new (ifindex, iface, (struct ether_addr *) mac, &priv->lldp_handle); - if (ret) { + ret = sd_lldp_set_callback (priv->lldp_handle, lldp_event_handler, self); + if (ret < 0) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, - "initialization failed"); - return FALSE; + "set callback failed"); + goto err; } + priv->ifindex = ifindex; + ret = sd_lldp_attach_event (priv->lldp_handle, NULL, 0); - if (ret) { + if (ret < 0) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "attach event failed"); goto err_free; } - ret = sd_lldp_set_callback (priv->lldp_handle, lldp_event_handler, self); - if (ret) { - g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, - "set callback failed"); - goto err; - } - ret = sd_lldp_start (priv->lldp_handle); - if (ret) { + if (ret < 0) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "start failed"); goto err; } - priv->ifindex = ifindex; - priv->iface = strdup (iface); _LOGD ("start"); + return TRUE; err: @@ -486,6 +767,7 @@ err: err_free: sd_lldp_unref (priv->lldp_handle); priv->lldp_handle = NULL; + priv->ifindex = 0; return FALSE; } @@ -494,6 +776,7 @@ nm_lldp_listener_stop (NMLldpListener *self) { NMLldpListenerPrivate *priv; guint size; + gboolean changed = FALSE; g_return_if_fail (NM_IS_LLDP_LISTENER (self)); priv = NM_LLDP_LISTENER_GET_PRIVATE (self); @@ -503,19 +786,20 @@ nm_lldp_listener_stop (NMLldpListener *self) sd_lldp_stop (priv->lldp_handle); sd_lldp_detach_event (priv->lldp_handle); sd_lldp_unref (priv->lldp_handle); - g_clear_pointer (&priv->iface, g_free); priv->lldp_handle = NULL; size = g_hash_table_size (priv->lldp_neighbors); g_hash_table_remove_all (priv->lldp_neighbors); - if (size) { - nm_clear_g_variant (&priv->variant); - g_object_notify (G_OBJECT (self), NM_LLDP_LISTENER_NEIGHBORS); - } + if (size || priv->ratelimit_id) + changed = TRUE; } - nm_clear_g_source (&priv->timer); + nm_clear_g_source (&priv->ratelimit_id); + priv->ratelimit_next = 0; priv->ifindex = 0; + + if (changed) + data_changed_notify (self, priv); } gboolean @@ -532,78 +816,23 @@ nm_lldp_listener_is_running (NMLldpListener *self) GVariant * nm_lldp_listener_get_neighbors (NMLldpListener *self) { - GVariantBuilder array_builder, neigh_builder; - GHashTableIter iter; NMLldpListenerPrivate *priv; - LLDPNeighbor *neigh; - char *dest_str = NULL; + GVariantBuilder array_builder; + GList *neighbors, *iter; - priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - - if (priv->variant) - goto out; - - g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); - g_hash_table_iter_init (&iter, priv->lldp_neighbors); - - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &neigh)) { - GHashTableIter val_iter; - gpointer key, val; - - g_variant_builder_init (&neigh_builder, G_VARIANT_TYPE ("a{sv}")); - - g_variant_builder_add (&neigh_builder, "{sv}", - NM_LLDP_ATTR_CHASSIS_ID_TYPE, - g_variant_new_uint32 (neigh->chassis_id_type)); - g_variant_builder_add (&neigh_builder, "{sv}", - NM_LLDP_ATTR_CHASSIS_ID, - g_variant_new_string (neigh->chassis_id)); - g_variant_builder_add (&neigh_builder, "{sv}", - NM_LLDP_ATTR_PORT_ID_TYPE, - g_variant_new_uint32 (neigh->port_id_type)); - g_variant_builder_add (&neigh_builder, "{sv}", - NM_LLDP_ATTR_PORT_ID, - g_variant_new_string (neigh->port_id)); - - switch (neigh->dest) { - case SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE: - dest_str = NM_LLDP_DEST_NEAREST_BRIDGE; - break; - case SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE: - dest_str = NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE; - break; - case SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE: - dest_str = NM_LLDP_DEST_NEAREST_CUSTOMER_BRIDGE; - break; - } - - if (dest_str) { - g_variant_builder_add (&neigh_builder, "{sv}", - NM_LLDP_ATTR_DESTINATION, - g_variant_new_string (dest_str)); - } + g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), FALSE); - g_hash_table_iter_init (&val_iter, neigh->tlvs); - while (g_hash_table_iter_next (&val_iter, &key, &val)) { - GValue *item = val; - - if (G_VALUE_HOLDS_STRING (item)) { - g_variant_builder_add (&neigh_builder, "{sv}", - key, - g_variant_new_string (g_value_get_string (item))); - } else if (G_VALUE_HOLDS_UINT (item)) { - g_variant_builder_add (&neigh_builder, "{sv}", - key, - g_variant_new_uint32 (g_value_get_uint (item))); - } - } + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); - g_variant_builder_add (&array_builder, "a{sv}", &neigh_builder); + if (!priv->variant) { + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); + neighbors = g_hash_table_get_keys (priv->lldp_neighbors); + neighbors = g_list_sort (neighbors, lldp_neighbor_id_cmp); + for (iter = neighbors; iter; iter = iter->next) + g_variant_builder_add_value (&array_builder, lldp_neighbor_to_variant (iter->data)); + g_list_free (neighbors); + priv->variant = g_variant_ref_sink (g_variant_builder_end (&array_builder)); } - - priv->variant = g_variant_ref_sink (g_variant_builder_end (&array_builder)); - -out: return priv->variant; } @@ -676,12 +905,13 @@ nm_lldp_listener_class_init (NMLldpListenerClass *klass) object_class->finalize = finalize; object_class->get_property = get_property; - g_object_class_install_property - (object_class, PROP_NEIGHBORS, - g_param_spec_variant (NM_LLDP_LISTENER_NEIGHBORS, "", "", - G_VARIANT_TYPE ("aa{sv}"), - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_NEIGHBORS] = + g_param_spec_variant (NM_LLDP_LISTENER_NEIGHBORS, "", "", + G_VARIANT_TYPE ("aa{sv}"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); } diff --git a/src/devices/nm-lldp-listener.h b/src/devices/nm-lldp-listener.h index 10c43e7c..df02fd63 100644 --- a/src/devices/nm-lldp-listener.h +++ b/src/devices/nm-lldp-listener.h @@ -42,8 +42,7 @@ typedef struct { GType nm_lldp_listener_get_type (void); NMLldpListener *nm_lldp_listener_new (void); -gboolean nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface, - const guint8 *mac, guint mac_len, GError **error); +gboolean nm_lldp_listener_start (NMLldpListener *self, int ifindex, GError **error); void nm_lldp_listener_stop (NMLldpListener *self); gboolean nm_lldp_listener_is_running (NMLldpListener *self); diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index c3d48b41..60842c18 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -107,7 +107,8 @@ complete_connection (NMDevice *device, { NMSettingTeam *s_team; - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_TEAM_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/tests/test-arping.c b/src/devices/tests/test-arping.c index 36e17631..72d28a7a 100644 --- a/src/devices/tests/test-arping.c +++ b/src/devices/tests/test-arping.c @@ -41,8 +41,8 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data) { /* create veth pair. */ nmtstp_run_command_check ("ip link add dev %s type veth peer name %s", IFACE_VETH0, IFACE_VETH1); - fixture->ifindex0 = nmtstp_assert_wait_for_link (IFACE_VETH0, NM_LINK_TYPE_VETH, 100)->ifindex; - fixture->ifindex1 = nmtstp_assert_wait_for_link (IFACE_VETH1, NM_LINK_TYPE_VETH, 100)->ifindex; + fixture->ifindex0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_VETH0, NM_LINK_TYPE_VETH, 100)->ifindex; + fixture->ifindex1 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_VETH1, NM_LINK_TYPE_VETH, 100)->ifindex; g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex0, NULL)); g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex1, NULL)); @@ -80,7 +80,7 @@ test_arping_common (test_fixture *fixture, TestInfo *info) for (i = 0; info->peer_addresses[i]; i++) { nmtstp_ip4_address_add (FALSE, fixture->ifindex1, info->peer_addresses[i], - 24, 0, 3600, 1800, NULL); + 24, 0, 3600, 1800, 0, NULL); } loop = g_main_loop_new (NULL, FALSE); diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index dfae58b1..85c3b510 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -27,18 +27,327 @@ #include <sys/types.h> #include "nm-lldp-listener.h" +#include "nm-sd.h" + +#include "nm-sd-adapt.h" +#include "lldp.h" + #include "test-common.h" +#include "nm-test-utils.h" + +/*****************************************************************************/ + +static GVariant * +get_lldp_neighbor (GVariant *neighbors, + int chassis_id_type, + const char *chassis_id, + int port_id_type, + const char *port_id) +{ + GVariantIter iter; + GVariant *variant; + GVariant *result = NULL; + + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + + g_assert (chassis_id_type >= -1 && chassis_id_type <= G_MAXUINT8); + g_assert (port_id_type >= -1 && port_id_type <= G_MAXUINT8); + + g_variant_iter_init (&iter, neighbors); + while (g_variant_iter_next (&iter, "@a{sv}", &variant)) { + gs_unref_variant GVariant *v_chassis_id_type = NULL; + gs_unref_variant GVariant *v_chassis_id = NULL; + gs_unref_variant GVariant *v_port_id_type = NULL; + gs_unref_variant GVariant *v_port_id = NULL; + + v_chassis_id_type = g_variant_lookup_value (variant, NM_LLDP_ATTR_CHASSIS_ID_TYPE, G_VARIANT_TYPE_UINT32); + g_assert (v_chassis_id_type); + + v_chassis_id = g_variant_lookup_value (variant, NM_LLDP_ATTR_CHASSIS_ID, G_VARIANT_TYPE_STRING); + g_assert (v_chassis_id); + + v_port_id_type = g_variant_lookup_value (variant, NM_LLDP_ATTR_PORT_ID_TYPE, G_VARIANT_TYPE_UINT32); + g_assert (v_port_id_type); + + v_port_id = g_variant_lookup_value (variant, NM_LLDP_ATTR_PORT_ID, G_VARIANT_TYPE_STRING); + g_assert (v_port_id); + + if ( nm_streq (g_variant_get_string (v_chassis_id, NULL), chassis_id) + && nm_streq (g_variant_get_string (v_port_id, NULL), port_id) + && NM_IN_SET (chassis_id_type, -1, g_variant_get_uint32 (v_chassis_id_type)) + && NM_IN_SET (port_id_type, -1, g_variant_get_uint32 (v_port_id_type))) { + g_assert (!result); + result = variant; + } else + g_variant_unref (variant); + } + + return result; +} + typedef struct { int ifindex; int fd; guint8 mac[ETH_ALEN]; -} test_fixture; +} TestRecvFixture; + +typedef struct { + gsize frame_len; + const uint8_t *frame; +} TestRecvFrame; +#define TEST_RECV_FRAME_DEFINE(name, ...) \ + static const guint8 _##name##_v[] = { __VA_ARGS__ }; \ + static const TestRecvFrame name = { \ + .frame_len = sizeof (_##name##_v), \ + .frame = _##name##_v, \ + } + +typedef struct { + guint expected_num_called; + gsize frames_len; + const TestRecvFrame *frames[10]; + void (*check) (GMainLoop *loop, NMLldpListener *listener); +} TestRecvData; +#define TEST_RECV_DATA_DEFINE(name, _expected_num_called, _check, ...) \ + static const TestRecvData name = { \ + .expected_num_called = _expected_num_called, \ + .check = _check, \ + .frames_len = NM_NARG (__VA_ARGS__), \ + .frames = { __VA_ARGS__ }, \ + } #define TEST_IFNAME "nm-tap-test0" +TEST_RECV_FRAME_DEFINE (_test_recv_data0_frame0, + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ + 0x03, 0x04, 0x05, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + /* LLDP optional TLVs */ + 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ + 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ + 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ + 0x00, 0x00 /* End Of LLDPDU */ +); + +static void +_test_recv_data0_check (GMainLoop *loop, NMLldpListener *listener) +{ + GVariant *neighbors, *attr; + gs_unref_variant GVariant *neighbor = NULL; + + neighbors = nm_lldp_listener_get_neighbors (listener); + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + g_assert_cmpint (g_variant_n_children (neighbors), ==, 1); + + neighbor = get_lldp_neighbor (neighbors, + LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS, "00:01:02:03:04:05", + LLDP_PORT_SUBTYPE_INTERFACE_NAME, "1/3"); + g_assert (neighbor); + g_assert_cmpint (g_variant_n_children (neighbor), ==, 4 + 4); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_PORT_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Port"); + nm_clear_g_variant (&attr); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_NAME, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "SYS"); + nm_clear_g_variant (&attr); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_DESTINATION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE); + nm_clear_g_variant (&attr); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "foo"); + nm_clear_g_variant (&attr); +} + +TEST_RECV_DATA_DEFINE (_test_recv_data0, 1, _test_recv_data0_check, &_test_recv_data0_frame0); +TEST_RECV_DATA_DEFINE (_test_recv_data0_twice, 1, _test_recv_data0_check, &_test_recv_data0_frame0, &_test_recv_data0_frame0); + + +TEST_RECV_FRAME_DEFINE (_test_recv_data1_frame0, + /* lldp.detailed.pcap from + * https://wiki.wireshark.org/SampleCaptures#Link_Layer_Discovery_Protocol_.28LLDP.29 */ + + /* ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, /* destination mac */ + 0x00, 0x01, 0x30, 0xf9, 0xad, 0xa0, /* source mac */ + 0x88, 0xcc, /* ethernet type */ + + 0x02, 0x07, 0x04, 0x00, 0x01, 0x30, /* Chassis Subtype */ + 0xf9, 0xad, 0xa0, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x31, /* Port Subtype */ + 0x06, 0x02, 0x00, 0x78, /* Time To Live */ + 0x08, 0x17, 0x53, 0x75, 0x6d, 0x6d, /* Port Description */ + 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, + 0x34, 0x38, 0x2d, 0x50, 0x6f, 0x72, + 0x74, 0x20, 0x31, 0x30, 0x30, 0x31, + 0x00, + 0x0a, 0x0d, 0x53, 0x75, 0x6d, 0x6d, /* System Name */ + 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, + 0x34, 0x38, 0x00, + 0x0c, 0x4c, 0x53, 0x75, 0x6d, 0x6d, /* System Description */ + 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, + 0x34, 0x38, 0x20, 0x2d, 0x20, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x37, 0x2e, 0x34, 0x65, 0x2e, + 0x31, 0x20, 0x28, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x20, 0x35, 0x29, 0x20, + 0x62, 0x79, 0x20, 0x52, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x5f, 0x4d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, + 0x30, 0x35, 0x2f, 0x32, 0x37, 0x2f, + 0x30, 0x35, 0x20, 0x30, 0x34, 0x3a, + 0x35, 0x33, 0x3a, 0x31, 0x31, 0x00, + 0x0e, 0x04, 0x00, 0x14, 0x00, 0x14, /* Capabilities */ + 0x10, 0x0e, 0x07, 0x06, 0x00, 0x01, /* Management Address */ + 0x30, 0xf9, 0xad, 0xa0, 0x02, 0x00, + 0x00, 0x03, 0xe9, 0x00, + 0xfe, 0x07, 0x00, 0x12, 0x0f, 0x02, /* IEEE 802.3 - Power Via MDI */ + 0x07, 0x01, 0x00, + 0xfe, 0x09, 0x00, 0x12, 0x0f, 0x01, /* IEEE 802.3 - MAC/PHY Configuration/Status */ + 0x03, 0x6c, 0x00, 0x00, 0x10, + 0xfe, 0x09, 0x00, 0x12, 0x0f, 0x03, /* IEEE 802.3 - Link Aggregation */ + 0x01, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x06, 0x00, 0x12, 0x0f, 0x04, /* IEEE 802.3 - Maximum Frame Size */ + 0x05, 0xf2, + 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x01, /* IEEE 802.1 - Port VLAN ID */ + 0x01, 0xe8, + 0xfe, 0x07, 0x00, 0x80, 0xc2, 0x02, /* IEEE 802.1 - Port and Protocol VLAN ID */ + 0x01, 0x00, 0x00, + 0xfe, 0x17, 0x00, 0x80, 0xc2, 0x03, /* IEEE 802.1 - VLAN Name */ + 0x01, 0xe8, 0x10, 0x76, 0x32, 0x2d, + 0x30, 0x34, 0x38, 0x38, 0x2d, 0x30, + 0x33, 0x2d, 0x30, 0x35, 0x30, 0x35, + 0x00, + 0xfe, 0x05, 0x00, 0x80, 0xc2, 0x04, /* IEEE 802.1 - Protocol Identity */ + 0x00, + 0x00, 0x00 /* End of LLDPDU */ +); + static void -fixture_setup (test_fixture *fixture, gconstpointer user_data) +_test_recv_data1_check (GMainLoop *loop, NMLldpListener *listener) +{ + GVariant *neighbors, *attr; + gs_unref_variant GVariant *neighbor = NULL; + + neighbors = nm_lldp_listener_get_neighbors (listener); + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + g_assert_cmpint (g_variant_n_children (neighbors), ==, 1); + + neighbor = get_lldp_neighbor (neighbors, + LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS, "00:01:30:F9:AD:A0", + LLDP_PORT_SUBTYPE_INTERFACE_NAME, "1/1"); + g_assert (neighbor); + g_assert_cmpint (g_variant_n_children (neighbor), ==, 4 + 10); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_DESTINATION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, NM_LLDP_DEST_NEAREST_BRIDGE); + nm_clear_g_variant (&attr); + + /* unsupported: Time To Live */ + + /* Port Description */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_PORT_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Summit300-48-Port 1001"); + nm_clear_g_variant (&attr); + + /* System Name */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_NAME, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Summit300-48"); + nm_clear_g_variant (&attr); + + /* System Description */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Summit300-48 - Version 7.4e.1 (Build 5) by Release_Master 05/27/05 04:53:11"); + nm_clear_g_variant (&attr); + + /* Capabilities */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_CAPABILITIES, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 20); + nm_clear_g_variant (&attr); + + /* unsupported: Management Address */ + /* unsupported: IEEE 802.3 - Power Via MDI */ + /* unsupported: IEEE 802.3 - MAC/PHY Configuration/Status */ + /* unsupported: IEEE 802.3 - Link Aggregation */ + /* unsupported: IEEE 802.3 - Maximum Frame Size*/ + + /* IEEE 802.1 - Port VLAN ID */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_PVID, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 488); + nm_clear_g_variant (&attr); + + /* IEEE 802.1 - Port and Protocol VLAN ID */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_PPVID, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 0); + nm_clear_g_variant (&attr); + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 1); + nm_clear_g_variant (&attr); + + /* IEEE 802.1 - VLAN Name */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "v2-0488-03-0505"); + nm_clear_g_variant (&attr); + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_VID, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 488); + nm_clear_g_variant (&attr); + + /* unsupported: IEEE 802.1 - Protocol Identity */ +} + +TEST_RECV_DATA_DEFINE (_test_recv_data1, 1, _test_recv_data1_check, &_test_recv_data1_frame0); + +TEST_RECV_FRAME_DEFINE (_test_recv_data2_frame0_ttl1, + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ + 0x03, 0x04, 0x05, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ + 0x06, 0x02, 0x00, 0x01, /* TTL: 1 seconds */ + /* LLDP optional TLVs */ + 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ + 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ + 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ + 0x00, 0x00 /* End Of LLDPDU */ +); + +static void +_test_recv_data2_ttl1_check (GMainLoop *loop, NMLldpListener *listener) +{ + gulong notify_id; + GVariant *neighbors; + + _test_recv_data0_check (loop, listener); + + /* wait for signal. */ + notify_id = g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, + nmtst_main_loop_quit_on_notify, loop); + if (!nmtst_main_loop_run (loop, 5000)) + g_assert_not_reached (); + nm_clear_g_signal_handler (listener, ¬ify_id); + + neighbors = nm_lldp_listener_get_neighbors (listener); + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + g_assert_cmpint (g_variant_n_children (neighbors), ==, 0); +} + +TEST_RECV_DATA_DEFINE (_test_recv_data2_ttl1, 1, _test_recv_data2_ttl1_check, &_test_recv_data2_frame0_ttl1); + +static void +_test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) { const NMPlatformLink *link; struct ifreq ifr = { }; @@ -48,7 +357,7 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data) g_assert (fd >= 0); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - strncpy (ifr.ifr_name, TEST_IFNAME, IFNAMSIZ); + nm_utils_ifname_cpy (ifr.ifr_name, TEST_IFNAME); g_assert (ioctl (fd, TUNSETIFF, &ifr) >= 0); /* Bring the interface up */ @@ -58,9 +367,7 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data) g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); close (s); - nm_platform_process_events (NM_PLATFORM_GET); - link = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, TEST_IFNAME); - g_assert (link); + link = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TAP, 100); fixture->ifindex = link->ifindex; fixture->fd = fd; memcpy (fixture->mac, link->addr.data, ETH_ALEN); @@ -68,149 +375,66 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data) typedef struct { int num_called; -} TestInfo; - -static gboolean -loop_quit (gpointer user_data) -{ - g_main_loop_quit ((GMainLoop *) user_data); - return G_SOURCE_REMOVE; -} +} TestRecvCallbackInfo; static void lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec, gpointer user_data) { - TestInfo *info = user_data; + TestRecvCallbackInfo *info = user_data; info->num_called++; } -static GVariant * -get_lldp_neighbor_attribute (GVariant *neighbors, - const char *chassis, const char *port, - const char *name) -{ - GVariantIter iter, attrs_iter; - GVariant *variant, *attr_variant; - const char *attr_name; - - g_return_val_if_fail (g_variant_is_of_type (neighbors, - G_VARIANT_TYPE ("aa{sv}")), - NULL); - g_variant_iter_init (&iter, neighbors); - - while (g_variant_iter_next (&iter, "@a{sv}", &variant)) { - gs_unref_variant GVariant *chassis_v = NULL; - gs_unref_variant GVariant *port_v = NULL; - gs_unref_variant GVariant *attr_v = NULL; - - g_variant_iter_init (&attrs_iter, variant); - while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_variant)) { - if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_CHASSIS_ID)) { - g_assert (!chassis_v); - chassis_v = attr_variant; - } else if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_PORT_ID)) { - g_assert (!port_v); - port_v = attr_variant; - } else if (!g_strcmp0 (attr_name, name)) { - g_assert (!attr_v); - attr_v = attr_variant; - } else - g_variant_unref (attr_variant); - } - - g_variant_unref (variant); - - if ( chassis_v - && port_v - && g_variant_is_of_type (chassis_v, G_VARIANT_TYPE_STRING) - && g_variant_is_of_type (port_v, G_VARIANT_TYPE_STRING) - && !g_strcmp0 (chassis, g_variant_get_string (chassis_v, NULL)) - && !g_strcmp0 (port, g_variant_get_string (port_v, NULL))) - return g_variant_ref (attr_v); - } - - /* neighbor not found */ - return NULL; -} - static void -test_receive_frame (test_fixture *fixture, gconstpointer user_data) +test_recv (TestRecvFixture *fixture, gconstpointer user_data) { + const TestRecvData *data = user_data; gs_unref_object NMLldpListener *listener = NULL; GMainLoop *loop; - TestInfo info = { }; - GVariant *neighbors, *attr; - uint8_t frame[] = { - /* Ethernet header */ - 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ - 0x88, 0xcc, /* Ethertype */ - /* LLDP mandatory TLVs */ - 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ - 0x03, 0x04, 0x05, - 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ - 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ - /* LLDP optional TLVs */ - 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ - 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ - 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ - 0x00, 0x00 /* End Of LLDPDU */ - }; + TestRecvCallbackInfo info = { }; + gsize i_frames; + gulong notify_id; + GError *error = NULL; + guint sd_id; listener = nm_lldp_listener_new (); g_assert (listener != NULL); - g_assert (nm_lldp_listener_start (listener, fixture->ifindex, TEST_IFNAME, fixture->mac, ETH_ALEN, NULL)); + g_assert (nm_lldp_listener_start (listener, fixture->ifindex, &error)); + g_assert_no_error (error); - g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, - (GCallback) lldp_neighbors_changed, &info); + notify_id = g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, + (GCallback) lldp_neighbors_changed, &info); loop = g_main_loop_new (NULL, FALSE); - g_timeout_add_seconds (1, loop_quit, loop); + sd_id = nm_sd_event_attach_default (); + + for (i_frames = 0; i_frames < data->frames_len; i_frames++) { + const TestRecvFrame *f = data->frames[i_frames]; - g_assert (write (fixture->fd, frame, sizeof (frame)) == sizeof (frame)); - g_assert (write (fixture->fd, frame, sizeof (frame)) == sizeof (frame)); + g_assert (write (fixture->fd, f->frame, f->frame_len) == f->frame_len); + } - g_main_loop_run (loop); + if (nmtst_main_loop_run (loop, 500)) + g_assert_not_reached (); - g_assert_cmpint (info.num_called, ==, 1); - neighbors = nm_lldp_listener_get_neighbors (listener); - g_assert (neighbors != NULL); - - /* Check port description */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_PORT_DESCRIPTION); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "Port"); - nm_clear_g_variant (&attr); + g_assert_cmpint (info.num_called, ==, data->expected_num_called); - /* Check system name */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_SYSTEM_NAME); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "SYS"); - nm_clear_g_variant (&attr); + nm_clear_g_signal_handler (listener, ¬ify_id); - /* Check destination */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_DESTINATION); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, - NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE); - nm_clear_g_variant (&attr); + data->check (loop, listener); + nm_clear_g_source (&sd_id); g_clear_pointer (&loop, g_main_loop_unref); } static void -fixture_teardown (test_fixture *fixture, gconstpointer user_data) +_test_recv_fixture_teardown (TestRecvFixture *fixture, gconstpointer user_data) { nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex); } +/*****************************************************************************/ + void init_tests (int *argc, char ***argv) { @@ -220,6 +444,10 @@ init_tests (int *argc, char ***argv) void setup_tests (void) { - g_test_add ("/lldp/receive_frame", test_fixture, NULL, fixture_setup, - test_receive_frame, fixture_teardown); +#define _TEST_ADD_RECV(testpath, testdata) \ + g_test_add (testpath, TestRecvFixture, testdata, _test_recv_fixture_setup, test_recv, _test_recv_fixture_teardown) + _TEST_ADD_RECV ("/lldp/recv/0", &_test_recv_data0); + _TEST_ADD_RECV ("/lldp/recv/0_twice", &_test_recv_data0_twice); + _TEST_ADD_RECV ("/lldp/recv/1", &_test_recv_data1); + _TEST_ADD_RECV ("/lldp/recv/2_ttl1", &_test_recv_data2_ttl1); } diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index 11da011e..6fbc63a1 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -138,7 +138,8 @@ complete_connection (NMDevice *device, } - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_OLPC_MESH_SETTING_NAME, existing_connections, NULL, diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index da2a0f4a..95a89eab 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -845,7 +845,8 @@ complete_connection (NMDevice *device, str_ssid = nm_utils_ssid_to_utf8 (ssid->data, ssid->len); - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_WIRELESS_SETTING_NAME, existing_connections, str_ssid, @@ -2491,7 +2492,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) if (config == NULL) { _LOGE (LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) couldn't build wireless configuration: %s", - error ? error->message : "<BUG>"); + error->message); g_clear_error (&error); *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; goto out; @@ -2506,7 +2507,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) if (!nm_supplicant_interface_set_config (priv->sup_iface, config, &error)) { _LOGE (LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) couldn't send wireless configuration to the supplicant: %s", - error ? error->message : "<BUG>"); + error->message); g_clear_error (&error); *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; goto out; diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index 307825c6..a0c25709 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -741,7 +741,7 @@ nm_ap_dump (NMAccessPoint *self, nm_log_dbg (LOGD_WIFI_SCAN, "%s[%s%c] %-32s[%s%u %3u%% %c W:%04X R:%04X] [%3u] %s%s", prefix, - str_if_set (priv->address, "(none)"), + priv->address ?: "(none)", mode_to_char (self), priv->ssid ? nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len) : "(none)", chan > 99 ? "" : (chan > 9 ? " " : " "), diff --git a/src/devices/wifi/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c index 01990bee..838368c4 100644 --- a/src/devices/wifi/tests/test-wifi-ap-utils.c +++ b/src/devices/wifi/tests/test-wifi-ap-utils.c @@ -37,7 +37,7 @@ if (expected) { \ if (!success) { \ g_assert (error != NULL); \ - g_warning ("Failed to complete connection: (%d) %s", error->code, error->message); \ + g_warning ("Failed to complete connection: %s", error->message); \ } \ g_assert (success == TRUE); \ g_assert (error == NULL); \ diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index e9c4f02e..a8361c49 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -157,8 +157,8 @@ modem_ip4_config_result (NMModem *modem, g_return_if_fail (nm_device_activate_ip4_state_in_conf (device) == TRUE); if (error) { - _LOGW (LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: (%d) %s", - error->code, error->message ? error->message : "(unknown)"); + _LOGW (LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: %s", + error->message); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } else { @@ -184,8 +184,7 @@ modem_ip6_config_result (NMModem *modem, g_return_if_fail (nm_device_activate_ip6_state_in_conf (device) == TRUE); if (error) { - _LOGW (LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: (%d) %s", - error->code, error->message ? error->message : "(unknown)"); + _LOGW (LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: %s", error->message); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); return; diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 6343416c..769e6a27 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -464,7 +464,7 @@ connect_context_step (NMModemBroadband *self) nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': %s", nm_modem_get_uid (NM_MODEM (self)), nm_connection_get_id (ctx->connection), - error ? error->message : "unknown error"); + error->message); g_clear_error (&error); g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); @@ -647,7 +647,8 @@ complete_connection (NMModem *_self, if (!nm_setting_gsm_get_number (s_gsm)) g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL); - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_GSM_SETTING_NAME, existing_connections, NULL, @@ -670,7 +671,8 @@ complete_connection (NMModem *_self, if (!nm_setting_cdma_get_number (s_cdma)) g_object_set (G_OBJECT (s_cdma), NM_SETTING_CDMA_NUMBER, "#777", NULL); - nm_utils_complete_generic (connection, + nm_utils_complete_generic (NM_PLATFORM_GET, + connection, NM_SETTING_CDMA_SETTING_NAME, existing_connections, NULL, @@ -734,7 +736,7 @@ set_power_state_low_ready (MMModem *modem, /* Log but ignore errors; not all modems support low power state */ nm_log_dbg (LOGD_MB, "(%s): failed to set modem low power state: %s", nm_modem_get_uid (NM_MODEM (self)), - error && error->message ? error->message : "(unknown)"); + NM_G_ERROR_MSG (error)); g_clear_error (&error); } @@ -759,7 +761,7 @@ modem_disable_ready (MMModem *modem_iface, } else { nm_log_warn (LOGD_MB, "(%s): failed to disable modem: %s", nm_modem_get_uid (NM_MODEM (self)), - error && error->message ? error->message : "(unknown)"); + NM_G_ERROR_MSG (error)); nm_modem_set_prev_state (NM_MODEM (self), "disable failed"); g_clear_error (&error); } @@ -778,7 +780,7 @@ modem_enable_ready (MMModem *modem_iface, if (!mm_modem_enable_finish (modem_iface, res, &error)) { nm_log_warn (LOGD_MB, "(%s) failed to enable modem: %s", nm_modem_get_uid (NM_MODEM (self)), - error && error->message ? error->message : "(unknown)"); + NM_G_ERROR_MSG (error)); nm_modem_set_prev_state (NM_MODEM (self), "enable failed"); g_clear_error (&error); } @@ -1259,7 +1261,7 @@ get_sim_ready (MMModem *modem, } else { nm_log_warn (LOGD_MB, "(%s): failed to retrieve SIM object: %s", nm_modem_get_uid (NM_MODEM (self)), - error && error->message ? error->message : "(unknown)"); + NM_G_ERROR_MSG (error)); } g_clear_error (&error); g_object_unref (self); diff --git a/src/devices/wwan/nm-modem-manager.c b/src/devices/wwan/nm-modem-manager.c index 79082c41..e26321b0 100644 --- a/src/devices/wwan/nm-modem-manager.c +++ b/src/devices/wwan/nm-modem-manager.c @@ -145,7 +145,7 @@ modem_object_added (MMManager *modem_manager, handle_new_modem (self, modem); else { nm_log_warn (LOGD_MB, "failed to create modem: %s", - error ? error->message : "(unknown)"); + error->message); } g_clear_error (&error); } diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index c1736ecf..2a8a9d1e 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -545,10 +545,9 @@ ppp_stage3_ip_config_start (NMModem *self, ret = NM_ACT_STAGE_RETURN_POSTPONE; } else { - nm_log_err (LOGD_PPP, "(%s): error starting PPP: (%d) %s", + nm_log_err (LOGD_PPP, "(%s): error starting PPP: %s", nm_modem_get_uid (self), - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); + error->message); g_error_free (error); nm_exported_object_clear_and_unexport (&priv->ppp_manager); |