diff options
Diffstat (limited to 'src')
71 files changed, 2101 insertions, 801 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 4f842494..63741dc3 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -2169,15 +2169,15 @@ nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection /**************************************************************************/ static gint64 monotonic_timestamp_offset_sec; +static int monotonic_timestamp_clock_mode = 0; static void monotonic_timestamp_get (struct timespec *tp) { - static int clock_mode = 0; - gboolean first_time = FALSE; + int clock_mode = 0; int err = 0; - switch (clock_mode) { + switch (monotonic_timestamp_clock_mode) { case 0: /* the clock is not yet initialized (first run) */ err = clock_gettime (CLOCK_BOOTTIME, tp); @@ -2186,7 +2186,6 @@ monotonic_timestamp_get (struct timespec *tp) err = clock_gettime (CLOCK_MONOTONIC, tp); } else clock_mode = 1; - first_time = TRUE; break; case 1: /* default, return CLOCK_BOOTTIME */ @@ -2202,7 +2201,7 @@ monotonic_timestamp_get (struct timespec *tp) g_assert (err == 0); (void)err; g_assert (tp->tv_nsec >= 0 && tp->tv_nsec < NM_UTILS_NS_PER_SECOND); - if (G_LIKELY (!first_time)) + if (G_LIKELY (clock_mode == 0)) return; /* Calculate an offset for the time stamp. @@ -2219,6 +2218,7 @@ monotonic_timestamp_get (struct timespec *tp) * wraps (~68 years). **/ monotonic_timestamp_offset_sec = (- ((gint64) tp->tv_sec)) + 1; + monotonic_timestamp_clock_mode = clock_mode; if (nm_logging_enabled (LOGL_DEBUG, LOGD_CORE)) { time_t now = time (NULL); @@ -2532,11 +2532,15 @@ nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, if (print_header) { GError *err_verify = NULL; + const char *path = nm_connection_get_path (connection); - if (diff_base) - nm_log (level, domain, "%sconnection '%s' (%p/%s < %p/%s):", prefix, name, connection, G_OBJECT_TYPE_NAME (connection), diff_base, G_OBJECT_TYPE_NAME (diff_base)); - else - nm_log (level, domain, "%sconnection '%s' (%p/%s):", prefix, name, connection, G_OBJECT_TYPE_NAME (connection)); + if (diff_base) { + nm_log (level, domain, "%sconnection '%s' (%p/%s < %p/%s)%s%s%s:", prefix, name, connection, G_OBJECT_TYPE_NAME (connection), diff_base, G_OBJECT_TYPE_NAME (diff_base), + NM_PRINT_FMT_QUOTED (path, " [", path, "]", "")); + } else { + nm_log (level, domain, "%sconnection '%s' (%p/%s):%s%s%s", prefix, name, connection, G_OBJECT_TYPE_NAME (connection), + NM_PRINT_FMT_QUOTED (path, " [", path, "]", "")); + } print_header = FALSE; if (!nm_connection_verify (connection, &err_verify)) { @@ -2583,6 +2587,49 @@ out: g_array_free (sorted_hashes, TRUE); } +/** + * nm_utils_monotonic_timestamp_as_boottime: + * @timestamp: the monotonic-timestamp that should be converted into CLOCK_BOOTTIME. + * @timestamp_ns_per_tick: How many nano seconds make one unit of @timestamp? E.g. if + * @timestamp is in unit seconds, pass %NM_UTILS_NS_PER_SECOND; @timestamp in nano + * seconds, pass 1; @timestamp in milli seconds, pass %NM_UTILS_NS_PER_SECOND/1000; etc. + * + * Returns: the monotonic-timestamp as CLOCK_BOOTTIME, as returned by clock_gettime(). + * The unit is the same as the passed in @timestamp basd on @timestamp_ns_per_tick. + * E.g. if you passed @timestamp in as seconds, it will return boottime in seconds. + * If @timestamp is a non-positive, it returns -1. Note that a (valid) monotonic-timestamp + * is always positive. + * + * On older kernels that don't support CLOCK_BOOTTIME, the returned time is instead CLOCK_MONOTONIC. + **/ +gint64 +nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ns_per_tick) +{ + gint64 offset; + + /* only support ns-per-tick being a multiple of 10. */ + g_return_val_if_fail (timestamp_ns_per_tick == 1 + || (timestamp_ns_per_tick > 0 && + timestamp_ns_per_tick <= NM_UTILS_NS_PER_SECOND && + timestamp_ns_per_tick % 10 == 0), + -1); + + /* Check that the timestamp is in a valid range. */ + g_return_val_if_fail (timestamp >= 0, -1); + + /* if the caller didn't yet ever fetch a monotonic-timestamp, he cannot pass any meaningful + * value (because he has no idea what these timestamps would be). That would be a bug. */ + g_return_val_if_fail (monotonic_timestamp_clock_mode != 0, -1); + + /* calculate the offset of monotonic-timestamp to boottime. offset_s is <= 1. */ + offset = monotonic_timestamp_offset_sec * (NM_UTILS_NS_PER_SECOND / timestamp_ns_per_tick); + + /* check for overflow. */ + g_return_val_if_fail (offset > 0 || timestamp < G_MAXINT64 + offset, G_MAXINT64); + + return timestamp - offset; +} + #define IPV6_PROPERTY_DIR "/proc/sys/net/ipv6/conf/" #define IPV4_PROPERTY_DIR "/proc/sys/net/ipv4/conf/" @@ -2638,28 +2685,35 @@ nm_utils_ip4_property_path (const char *ifname, const char *property) return _get_property_path (ifname, property, FALSE); } -const char * -ASSERT_VALID_PATH_COMPONENT (const char *name) +gboolean +nm_utils_is_valid_path_component (const char *name) { const char *n; if (name == NULL || name[0] == '\0') - goto fail; + return FALSE; if (name[0] == '.') { if (name[1] == '\0') - goto fail; + return FALSE; if (name[1] == '.' && name[2] == '\0') - goto fail; + return FALSE; } n = name; do { if (*n == '/') - goto fail; + return FALSE; } while (*(++n) != '\0'); - return name; -fail: + return TRUE; +} + +const char * +ASSERT_VALID_PATH_COMPONENT (const char *name) +{ + if (G_LIKELY (nm_utils_is_valid_path_component (name))) + return name; + nm_log_err (LOGD_CORE, "Failed asserting path component: %s%s%s", NM_PRINT_FMT_QUOTED (name, "\"", name, "\"", "(null)")); g_error ("FATAL: Failed asserting path component: %s%s%s", diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 1864547f..70f62d47 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -161,7 +161,9 @@ gint64 nm_utils_get_monotonic_timestamp_ns (void); gint64 nm_utils_get_monotonic_timestamp_us (void); gint64 nm_utils_get_monotonic_timestamp_ms (void); gint32 nm_utils_get_monotonic_timestamp_s (void); +gint64 nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ticks_per_ns); +gboolean nm_utils_is_valid_path_component (const char *name); const char *ASSERT_VALID_PATH_COMPONENT (const char *name); const char *nm_utils_ip6_property_path (const char *ifname, const char *property); const char *nm_utils_ip4_property_path (const char *ifname, const char *property); diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index af2cb8f2..beb86e11 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -53,6 +53,7 @@ #include "nm-device-factory.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" +#include "gsystem-local-alloc.h" #include "nm-device-ethernet-glue.h" @@ -66,6 +67,7 @@ G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE) #define WIRED_SECRETS_TRIES "wired-secrets-tries" #define PPPOE_RECONNECT_DELAY 7 +#define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */ static NMSetting *device_get_setting (NMDevice *device, GType setting_type); @@ -1174,6 +1176,40 @@ dcb_carrier_changed (NMDevice *device, GParamSpec *pspec, gpointer unused) /****************************************************************/ +static gboolean +wake_on_lan_enable (NMDevice *device) +{ + NMSettingWiredWakeOnLan wol; + NMSettingWired *s_wired; + const char *password = NULL; + gs_free char *value = NULL; + + s_wired = (NMSettingWired *) device_get_setting (device, NM_TYPE_SETTING_WIRED); + if (s_wired) { + wol = nm_setting_wired_get_wake_on_lan (s_wired); + password = nm_setting_wired_get_wake_on_lan_password (s_wired); + if (wol != NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT) + goto found; + } + + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "ethernet.wake-on-lan", + device); + if (value) { + wol = _nm_utils_ascii_str_to_int64 (value, 10, + NM_SETTING_WIRED_WAKE_ON_LAN_NONE, + NM_SETTING_WIRED_WAKE_ON_LAN_ALL, + NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT); + if (wol != NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT) + goto found; + } + wol = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; +found: + return nmp_utils_ethtool_set_wake_on_lan (nm_device_get_iface (device), wol, password); +} + +/****************************************************************/ + static NMActStageReturn act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) { @@ -1206,6 +1242,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) } } + wake_on_lan_enable (device); + /* DCB and FCoE setup */ s_dcb = (NMSettingDcb *) device_get_setting (device, NM_TYPE_SETTING_DCB); if (s_dcb) { @@ -1231,6 +1269,28 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) ret = NM_ACT_STAGE_RETURN_POSTPONE; } + /* PPPoE setup */ + if (nm_connection_is_type (nm_device_get_connection (device), + NM_SETTING_PPPOE_SETTING_NAME)) { + NMSettingPpp *s_ppp; + + s_ppp = (NMSettingPpp *) device_get_setting (device, NM_TYPE_SETTING_PPP); + if (s_ppp) { + guint32 mtu = 0, mru = 0, mxu; + + mtu = nm_setting_ppp_get_mtu (s_ppp); + mru = nm_setting_ppp_get_mru (s_ppp); + mxu = mru > mtu ? mru : mtu; + if (mxu) { + _LOGD (LOGD_PPP, "set MTU to %u (PPP interface MRU %u, MTU %u)", + mxu + PPPOE_ENCAP_OVERHEAD, mru, mtu); + nm_platform_link_set_mtu (NM_PLATFORM_GET, + nm_device_get_ifindex (device), + mxu + PPPOE_ENCAP_OVERHEAD); + } + } + } + return ret; } diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index 2e2483c0..2d519f61 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -313,7 +313,7 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, NM_DEVICE_PLATFORM_DEVICE, plink, NM_DEVICE_TYPE_DESC, "InfiniBand", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND, - NM_DEVICE_INFINIBAND_IS_PARTITION, (plink->parent > 0), + NM_DEVICE_INFINIBAND_IS_PARTITION, (plink->parent > 0 || plink->parent == NM_PLATFORM_LINK_OTHER_NETNS), NULL); } diff --git a/src/devices/nm-device-logging.h b/src/devices/nm-device-logging.h index acca32e5..f3b76ee8 100644 --- a/src/devices/nm-device-logging.h +++ b/src/devices/nm-device-logging.h @@ -31,16 +31,12 @@ _nm_device_log_self_to_device (t *self) \ return (NMDevice *) self; \ } -#define _LOG(level, domain, ...) \ +#undef _NMLOG_ENABLED +#define _NMLOG_ENABLED(level, domain) ( nm_logging_enabled ((level), (domain)) ) +#define _NMLOG(level, domain, ...) \ nm_log_obj ((level), (domain), (self), \ "(%s): " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ (self) ? str_if_set (nm_device_get_iface (_nm_device_log_self_to_device (self)), "(null)") : "(none)" \ _NM_UTILS_MACRO_REST(__VA_ARGS__)) -#define _LOGT(domain, ...) _LOG (LOGL_TRACE, domain, __VA_ARGS__) -#define _LOGD(domain, ...) _LOG (LOGL_DEBUG, domain, __VA_ARGS__) -#define _LOGI(domain, ...) _LOG (LOGL_INFO, domain, __VA_ARGS__) -#define _LOGW(domain, ...) _LOG (LOGL_WARN, domain, __VA_ARGS__) -#define _LOGE(domain, ...) _LOG (LOGL_ERR, domain, __VA_ARGS__) - #endif /* __NETWORKMANAGER_DEVICE_LOGGING_H__ */ diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index 0bfe3fe9..2a815cfd 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -114,7 +114,10 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_PARENT: - parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); + if (priv->props.parent_ifindex > 0) + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); + else + parent = NULL; g_value_set_boxed (value, parent ? nm_device_get_path (parent) : "/"); break; case PROP_MODE: diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 158e7de5..e523e6bb 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -181,7 +181,8 @@ component_added (NMDevice *device, GObject *component) return FALSE; } - if (nm_device_get_ifindex (added_device) != parent_ifindex) + if ( parent_ifindex <= 0 + || nm_device_get_ifindex (added_device) != parent_ifindex) return FALSE; nm_device_vlan_set_parent (self, added_device, FALSE); @@ -356,23 +357,28 @@ update_connection (NMDevice *device, NMConnection *connection) if (vlan_id != nm_setting_vlan_get_id (s_vlan)) g_object_set (s_vlan, NM_SETTING_VLAN_ID, priv->vlan_id, NULL); - parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); - g_assert (parent); + if (parent_ifindex != NM_PLATFORM_LINK_OTHER_NETNS) + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); + else + parent = NULL; nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent, FALSE); /* Update parent in the connection; default to parent's interface name */ - new_parent = nm_device_get_iface (parent); - setting_parent = nm_setting_vlan_get_parent (s_vlan); - if (setting_parent && nm_utils_is_uuid (setting_parent)) { - NMConnection *parent_connection; - - /* Don't change a parent specified by UUID if it's still valid */ - parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); - if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) - new_parent = NULL; - } - if (new_parent) - g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, new_parent, NULL); + if (parent) { + new_parent = nm_device_get_iface (parent); + setting_parent = nm_setting_vlan_get_parent (s_vlan); + if (setting_parent && nm_utils_is_uuid (setting_parent)) { + NMConnection *parent_connection; + + /* Don't change a parent specified by UUID if it's still valid */ + parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); + if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) + new_parent = NULL; + } + if (new_parent) + g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, new_parent, NULL); + } else + g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, NULL, NULL); } static NMActStageReturn @@ -628,7 +634,10 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, "VLAN parent ifindex unknown"); return NULL; } - parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); + if (parent_ifindex > 0) + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); + else + parent = NULL; device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN, NM_DEVICE_PLATFORM_DEVICE, plink, diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index c5d4c203..58895821 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -75,6 +75,10 @@ _LOG_DECLARE_SELF (NMDevice); static void impl_device_disconnect (NMDevice *self, DBusGMethodInvocation *context); static void impl_device_delete (NMDevice *self, DBusGMethodInvocation *context); static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data); +static gboolean ip_config_valid (NMDeviceState state); +static void nm_device_update_metered (NMDevice *self); +static NMActStageReturn dhcp4_start (NMDevice *self, NMConnection *connection, NMDeviceStateReason *reason); +static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason); #include "nm-device-glue.h" @@ -128,6 +132,7 @@ enum { PROP_MASTER, PROP_HW_ADDRESS, PROP_HAS_PENDING_ACTION, + PROP_METERED, LAST_PROP }; @@ -269,18 +274,20 @@ typedef struct { struct { gboolean v4_has; gboolean v4_is_assumed; - gboolean v4_configure_first_time; NMPlatformIP4Route v4; gboolean v6_has; gboolean v6_is_assumed; - gboolean v6_configure_first_time; NMPlatformIP6Route v6; } default_route; + gboolean v4_commit_first_time; + gboolean v6_commit_first_time; + /* DHCPv4 tracking */ NMDhcpClient * dhcp4_client; gulong dhcp4_state_sigid; NMDhcp4Config * dhcp4_config; + guint dhcp4_restart_id; NMIP4Config * vpn4_config; /* routes added by a VPN which uses this device */ guint arp_round2_id; @@ -325,6 +332,9 @@ typedef struct { NMDhcp6Config * dhcp6_config; /* IP6 config from DHCP */ NMIP6Config * dhcp6_ip6_config; + /* Event ID of the current IP6 config from DHCP */ + char * dhcp6_event_id; + guint dhcp6_restart_id; /* allow autoconnect feature */ gboolean autoconnect; @@ -338,6 +348,8 @@ typedef struct { gboolean is_master; GSList * slaves; /* list of SlaveInfo */ + NMMetered metered; + NMConnectionProvider *con_provider; } NMDevicePrivate; @@ -687,6 +699,21 @@ nm_device_get_device_type (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->type; } +/** + * nm_device_get_metered: + * @setting: the #NMDevice + * + * Returns: the #NMDevice:metered property of the device. + * + * Since: 1.0.6 + **/ +NMMetered +nm_device_get_metered (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), NM_METERED_UNKNOWN); + + return NM_DEVICE_GET_PRIVATE (self)->metered; +} /** * nm_device_get_priority(): @@ -735,14 +762,14 @@ nm_device_get_priority (NMDevice *self) return 400; case NM_DEVICE_TYPE_BRIDGE: return 425; - case NM_DEVICE_TYPE_MODEM: - return 450; - case NM_DEVICE_TYPE_BT: - return 550; case NM_DEVICE_TYPE_WIFI: return 600; case NM_DEVICE_TYPE_OLPC_MESH: return 650; + case NM_DEVICE_TYPE_MODEM: + return 700; + case NM_DEVICE_TYPE_BT: + return 750; case NM_DEVICE_TYPE_GENERIC: return 950; case NM_DEVICE_TYPE_UNKNOWN: @@ -3181,6 +3208,8 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + nm_clear_g_source (&priv->dhcp4_restart_id); + if (priv->dhcp4_client) { /* Stop any ongoing DHCP transaction on this device */ if (priv->dhcp4_state_sigid) { @@ -3218,6 +3247,8 @@ ip4_config_merge_and_apply (NMDevice *self, guint32 gateway; gboolean connection_has_default_route, connection_is_never_default; gboolean routes_full_sync; + gboolean ignore_auto_routes = FALSE; + gboolean ignore_auto_dns = FALSE; /* Merge all the configs into the composite config */ if (config) { @@ -3225,44 +3256,45 @@ ip4_config_merge_and_apply (NMDevice *self, priv->dev_ip4_config = g_object_ref (config); } + /* Apply ignore-auto-routes and ignore-auto-dns settings */ + connection = nm_device_get_connection (self); + if (connection) { + NMSettingIPConfig *s_ip4 = nm_connection_get_setting_ip4_config (connection); + + if (s_ip4) { + ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip4); + ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip4); + } + } + composite = nm_ip4_config_new (); if (commit) ensure_con_ip4_config (self); - if (priv->dev_ip4_config) - nm_ip4_config_merge (composite, priv->dev_ip4_config); + if (priv->dev_ip4_config) { + nm_ip4_config_merge (composite, priv->dev_ip4_config, + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0)); + } if (priv->vpn4_config) - nm_ip4_config_merge (composite, priv->vpn4_config); + nm_ip4_config_merge (composite, priv->vpn4_config, NM_IP_CONFIG_MERGE_DEFAULT); if (priv->ext_ip4_config) - nm_ip4_config_merge (composite, priv->ext_ip4_config); + nm_ip4_config_merge (composite, priv->ext_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT); /* Merge WWAN config *last* to ensure modem-given settings overwrite * any external stuff set by pppd or other scripts. */ - if (priv->wwan_ip4_config) - nm_ip4_config_merge (composite, priv->wwan_ip4_config); - - /* Apply ignore-auto-routes and ignore-auto-dns settings */ - connection = nm_device_get_connection (self); - if (connection) { - NMSettingIPConfig *s_ip4 = nm_connection_get_setting_ip4_config (connection); - - if (s_ip4) { - if (nm_setting_ip_config_get_ignore_auto_routes (s_ip4)) - nm_ip4_config_reset_routes (composite); - if (nm_setting_ip_config_get_ignore_auto_dns (s_ip4)) { - nm_ip4_config_reset_nameservers (composite); - nm_ip4_config_reset_domains (composite); - nm_ip4_config_reset_searches (composite); - } - } + if (priv->wwan_ip4_config) { + nm_ip4_config_merge (composite, priv->wwan_ip4_config, + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0)); } /* Merge user overrides into the composite config. For assumed connections, * con_ip4_config is empty. */ if (priv->con_ip4_config) - nm_ip4_config_merge (composite, priv->con_ip4_config); + nm_ip4_config_merge (composite, priv->con_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT); /* Add the default route. @@ -3282,21 +3314,26 @@ ip4_config_merge_and_apply (NMDevice *self, priv->default_route.v4_has = FALSE; priv->default_route.v4_is_assumed = TRUE; - routes_full_sync = commit - && priv->default_route.v4_configure_first_time - && !nm_device_uses_assumed_connection (self); - if (!commit) { /* during a non-commit event, we always pickup whatever is configured. */ goto END_ADD_DEFAULT_ROUTE; } + if (nm_device_uses_generated_assumed_connection (self)) { + /* a generate-assumed-connection always detects the default route from platform */ + goto END_ADD_DEFAULT_ROUTE; + } + + /* At this point, we treat assumed and non-assumed connections alike. + * For assumed connections we do that because we still manage RA and DHCP + * leases for them, so we must extend/update the default route on commits. + */ + connection_has_default_route = nm_default_route_manager_ip4_connection_has_default_route (nm_default_route_manager_get (), connection, &connection_is_never_default); - if ( !priv->default_route.v4_configure_first_time - && !nm_device_uses_assumed_connection (self) + if ( !priv->v4_commit_first_time && connection_is_never_default) { /* If the connection is explicitly configured as never-default, we enforce the (absense of the) * default-route only once. That allows the user to configure a connection as never-default, @@ -3304,14 +3341,8 @@ ip4_config_merge_and_apply (NMDevice *self, goto END_ADD_DEFAULT_ROUTE; } - /* At this point, we treat assumed and non-assumed connections alike. - * For assumed connections we do that because we still manage RA and DHCP - * leases for them, so we must extend/update the default route on commits. - */ - /* we are about to commit (for a non-assumed connection). Enforce whatever we have * configured. */ - priv->default_route.v4_configure_first_time = FALSE; priv->default_route.v4_is_assumed = FALSE; if (!connection_has_default_route) @@ -3323,7 +3354,7 @@ ip4_config_merge_and_apply (NMDevice *self, } gateway = nm_ip4_config_get_gateway (composite); - if ( !gateway + if ( !nm_ip4_config_has_gateway (composite) && nm_device_get_device_type (self) != NM_DEVICE_TYPE_MODEM) goto END_ADD_DEFAULT_ROUTE; @@ -3365,8 +3396,15 @@ END_ADD_DEFAULT_ROUTE: NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite); } + routes_full_sync = commit + && priv->v4_commit_first_time + && !nm_device_uses_assumed_connection (self); + success = nm_device_set_ip4_config (self, composite, default_route_metric, commit, routes_full_sync, out_reason); g_object_unref (composite); + + if (commit) + priv->v4_commit_first_time = FALSE; return success; } @@ -3391,12 +3429,44 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config) } } +static gboolean +dhcp4_restart_cb (gpointer user_data) +{ + NMDevice *self = user_data; + NMDevicePrivate *priv; + NMDeviceStateReason reason; + NMConnection *connection; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + priv = NM_DEVICE_GET_PRIVATE (self); + priv->dhcp4_restart_id = 0; + connection = nm_device_get_connection (self); + + if (dhcp4_start (self, connection, &reason) == NM_ACT_STAGE_RETURN_FAILURE) + priv->dhcp4_restart_id = g_timeout_add_seconds (120, dhcp4_restart_cb, self); + + return FALSE; +} + static void dhcp4_fail (NMDevice *self, gboolean timeout) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); dhcp4_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE); + + /* Don't fail if there are static addresses configured on + * the device, instead retry after some time. + */ + if ( priv->ip4_state == IP_DONE + && priv->con_ip4_config + && nm_ip4_config_get_num_addresses (priv->con_ip4_config) > 0) { + _LOGI (LOGD_DHCP4, "Scheduling DHCPv4 restart because device has IP addresses"); + priv->dhcp4_restart_id = g_timeout_add_seconds (120, dhcp4_restart_cb, self); + return; + } + if (timeout || (priv->ip4_state == IP_CONF)) nm_device_activate_schedule_ip4_config_timeout (self); else if (priv->ip4_state == IP_DONE) @@ -3426,6 +3496,7 @@ dhcp4_state_changed (NMDhcpClient *client, NMDhcpState state, NMIP4Config *ip4_config, GHashTable *options, + const char *event_id, gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); @@ -3450,8 +3521,10 @@ dhcp4_state_changed (NMDhcpClient *client, if (priv->ip4_state == IP_CONF) nm_device_activate_schedule_ip4_config_result (self, ip4_config); - else if (priv->ip4_state == IP_DONE) + else if (priv->ip4_state == IP_DONE) { dhcp4_lease_change (self, ip4_config); + nm_device_update_metered (self); + } break; case NM_DHCP_STATE_TIMEOUT: dhcp4_fail (self, TRUE); @@ -3802,6 +3875,9 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_NONE; g_clear_object (&priv->dhcp6_ip6_config); + g_clear_pointer (&priv->dhcp6_event_id, g_free); + + nm_clear_g_source (&priv->dhcp6_restart_id); if (priv->dhcp6_client) { if (priv->dhcp6_state_sigid) { @@ -3837,6 +3913,19 @@ ip6_config_merge_and_apply (NMDevice *self, const struct in6_addr *gateway; gboolean connection_has_default_route, connection_is_never_default; gboolean routes_full_sync; + gboolean ignore_auto_routes = FALSE; + gboolean ignore_auto_dns = FALSE; + + /* Apply ignore-auto-routes and ignore-auto-dns settings */ + connection = nm_device_get_connection (self); + if (connection) { + NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection); + + if (s_ip6) { + ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip6); + ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip6); + } + } /* If no config was passed in, create a new one */ composite = nm_ip6_config_new (); @@ -3845,41 +3934,34 @@ ip6_config_merge_and_apply (NMDevice *self, ensure_con_ip6_config (self); /* Merge all the IP configs into the composite config */ - if (priv->ac_ip6_config) - nm_ip6_config_merge (composite, priv->ac_ip6_config); - if (priv->dhcp6_ip6_config) - nm_ip6_config_merge (composite, priv->dhcp6_ip6_config); + if (priv->ac_ip6_config) { + nm_ip6_config_merge (composite, priv->ac_ip6_config, + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0)); + } + if (priv->dhcp6_ip6_config) { + nm_ip6_config_merge (composite, priv->dhcp6_ip6_config, + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0)); + } if (priv->vpn6_config) - nm_ip6_config_merge (composite, priv->vpn6_config); + nm_ip6_config_merge (composite, priv->vpn6_config, NM_IP_CONFIG_MERGE_DEFAULT); if (priv->ext_ip6_config) - nm_ip6_config_merge (composite, priv->ext_ip6_config); + nm_ip6_config_merge (composite, priv->ext_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT); /* Merge WWAN config *last* to ensure modem-given settings overwrite * any external stuff set by pppd or other scripts. */ - if (priv->wwan_ip6_config) - nm_ip6_config_merge (composite, priv->wwan_ip6_config); - - /* Apply ignore-auto-routes and ignore-auto-dns settings */ - connection = nm_device_get_connection (self); - if (connection) { - NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection); - - if (s_ip6) { - if (nm_setting_ip_config_get_ignore_auto_routes (s_ip6)) - nm_ip6_config_reset_routes (composite); - if (nm_setting_ip_config_get_ignore_auto_dns (s_ip6)) { - nm_ip6_config_reset_nameservers (composite); - nm_ip6_config_reset_domains (composite); - nm_ip6_config_reset_searches (composite); - } - } + if (priv->wwan_ip6_config) { + nm_ip6_config_merge (composite, priv->wwan_ip6_config, + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0)); } /* Merge user overrides into the composite config. For assumed connections, * con_ip6_config is empty. */ if (priv->con_ip6_config) - nm_ip6_config_merge (composite, priv->con_ip6_config); + nm_ip6_config_merge (composite, priv->con_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT); /* Add the default route. * @@ -3898,21 +3980,26 @@ ip6_config_merge_and_apply (NMDevice *self, priv->default_route.v6_has = FALSE; priv->default_route.v6_is_assumed = TRUE; - routes_full_sync = commit - && priv->default_route.v6_configure_first_time - && !nm_device_uses_assumed_connection (self); - if (!commit) { /* during a non-commit event, we always pickup whatever is configured. */ goto END_ADD_DEFAULT_ROUTE; } + if (nm_device_uses_generated_assumed_connection (self)) { + /* a generate-assumed-connection always detects the default route from platform */ + goto END_ADD_DEFAULT_ROUTE; + } + + /* At this point, we treat assumed and non-assumed connections alike. + * For assumed connections we do that because we still manage RA and DHCP + * leases for them, so we must extend/update the default route on commits. + */ + connection_has_default_route = nm_default_route_manager_ip6_connection_has_default_route (nm_default_route_manager_get (), connection, &connection_is_never_default); - if ( !priv->default_route.v6_configure_first_time - && !nm_device_uses_assumed_connection (self) + if ( !priv->v6_commit_first_time && connection_is_never_default) { /* If the connection is explicitly configured as never-default, we enforce the (absence of the) * default-route only once. That allows the user to configure a connection as never-default, @@ -3920,14 +4007,8 @@ ip6_config_merge_and_apply (NMDevice *self, goto END_ADD_DEFAULT_ROUTE; } - /* At this point, we treat assumed and non-assumed connections alike. - * For assumed connections we do that because we still manage RA and DHCP - * leases for them, so we must extend/update the default route on commits. - */ - /* we are about to commit (for a non-assumed connection). Enforce whatever we have * configured. */ - priv->default_route.v6_configure_first_time = FALSE; priv->default_route.v6_is_assumed = FALSE; if (!connection_has_default_route) @@ -3984,8 +4065,14 @@ END_ADD_DEFAULT_ROUTE: NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit (self, composite); } + routes_full_sync = commit + && priv->v6_commit_first_time + && !nm_device_uses_assumed_connection (self); + success = nm_device_set_ip6_config (self, composite, commit, routes_full_sync, out_reason); g_object_unref (composite); + if (commit) + priv->v6_commit_first_time = FALSE; return success; } @@ -4017,6 +4104,24 @@ dhcp6_lease_change (NMDevice *self) } } +static gboolean +dhcp6_restart_cb (gpointer user_data) +{ + NMDevice *self = user_data; + NMDevicePrivate *priv; + NMDeviceStateReason reason; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + priv = NM_DEVICE_GET_PRIVATE (self); + priv->dhcp6_restart_id = 0; + + if (!dhcp6_start (self, FALSE, &reason)) + priv->dhcp6_restart_id = g_timeout_add_seconds (120, dhcp6_restart_cb, self); + + return FALSE; +} + static void dhcp6_fail (NMDevice *self, gboolean timeout) { @@ -4025,6 +4130,17 @@ dhcp6_fail (NMDevice *self, gboolean timeout) dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE); if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_MANAGED) { + /* Don't fail if there are static addresses configured on + * the device, instead retry after some time. + */ + if ( priv->ip6_state == IP_DONE + && priv->con_ip6_config + && nm_ip6_config_get_num_addresses (priv->con_ip6_config)) { + _LOGI (LOGD_DHCP6, "Scheduling DHCPv6 restart because device has IP addresses"); + priv->dhcp6_restart_id = g_timeout_add_seconds (120, dhcp6_restart_cb, self); + return; + } + if (timeout || (priv->ip6_state == IP_CONF)) nm_device_activate_schedule_ip6_config_timeout (self); else if (priv->ip6_state == IP_DONE) @@ -4074,10 +4190,12 @@ dhcp6_state_changed (NMDhcpClient *client, NMDhcpState state, NMIP6Config *ip6_config, GHashTable *options, + const char *event_id, gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + guint i; g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == TRUE); g_return_if_fail (!ip6_config || NM_IS_IP6_CONFIG (ip6_config)); @@ -4086,10 +4204,27 @@ dhcp6_state_changed (NMDhcpClient *client, switch (state) { case NM_DHCP_STATE_BOUND: - g_clear_object (&priv->dhcp6_ip6_config); - if (ip6_config) { - priv->dhcp6_ip6_config = g_object_ref (ip6_config); - dhcp6_update_config (self, priv->dhcp6_config, options); + /* If the server sends multiple IPv6 addresses, we receive a state + * changed event for each of them. Use the event ID to merge IPv6 + * addresses from the same transaction into a single configuration. + */ + if ( ip6_config + && event_id + && priv->dhcp6_event_id + && !strcmp (event_id, priv->dhcp6_event_id)) { + for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) { + nm_ip6_config_add_address (priv->dhcp6_ip6_config, + nm_ip6_config_get_address (ip6_config, i)); + } + } else { + g_clear_object (&priv->dhcp6_ip6_config); + g_clear_pointer (&priv->dhcp6_event_id, g_free); + if (ip6_config) { + priv->dhcp6_ip6_config = g_object_ref (ip6_config); + priv->dhcp6_event_id = g_strdup (event_id); + dhcp6_update_config (self, priv->dhcp6_config, options); + g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG); + } } if (priv->ip6_state == IP_CONF) { @@ -4182,6 +4317,7 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason) g_warn_if_fail (priv->dhcp6_ip6_config == NULL); g_clear_object (&priv->dhcp6_ip6_config); + g_clear_pointer (&priv->dhcp6_event_id, g_free); connection = nm_device_get_connection (self); g_assert (connection); @@ -4437,7 +4573,7 @@ static void nm_device_set_mtu (NMDevice *self, guint32 mtu) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - int ifindex = nm_device_get_ifindex (self); + int ifindex = nm_device_get_ip_ifindex (self); if (mtu) priv->mtu = mtu; @@ -4446,7 +4582,7 @@ nm_device_set_mtu (NMDevice *self, guint32 mtu) if (priv->ip6_mtu) nm_device_ipv6_set_mtu (self, priv->ip6_mtu); - if (priv->mtu != nm_platform_link_get_mtu (NM_PLATFORM_GET, ifindex)) + if (priv->mtu && priv->mtu != nm_platform_link_get_mtu (NM_PLATFORM_GET, ifindex)) nm_platform_link_set_mtu (NM_PLATFORM_GET, ifindex, priv->mtu); } @@ -4459,20 +4595,20 @@ nm_device_ipv6_set_mtu (NMDevice *self, guint32 mtu) priv->ip6_mtu = mtu ?: plat_mtu; - if (priv->ip6_mtu && priv->mtu < priv->ip6_mtu) { - _LOGW (LOGD_DEVICE | LOGD_IP6, "Lowering IPv6 MTU (%d) to match device MTU (%d)", + if (priv->ip6_mtu && priv->mtu && priv->mtu < priv->ip6_mtu) { + _LOGI (LOGD_DEVICE | LOGD_IP6, "Lowering IPv6 MTU (%d) to match device MTU (%d)", priv->ip6_mtu, priv->mtu); priv->ip6_mtu = priv->mtu; } - if (priv->ip6_mtu < 1280) { - _LOGW (LOGD_DEVICE | LOGD_IP6, "IPv6 MTU (%d) smaller than 1280, adjusting", + if (priv->ip6_mtu && priv->ip6_mtu < 1280) { + _LOGI (LOGD_DEVICE | LOGD_IP6, "IPv6 MTU (%d) smaller than 1280, adjusting", priv->ip6_mtu); priv->ip6_mtu = 1280; } - if (priv->mtu < priv->ip6_mtu) { - _LOGW (LOGD_DEVICE | LOGD_IP6, "Raising device MTU (%d) to match IPv6 MTU (%d)", + if (priv->ip6_mtu && priv->mtu && priv->mtu < priv->ip6_mtu) { + _LOGI (LOGD_DEVICE | LOGD_IP6, "Raising device MTU (%d) to match IPv6 MTU (%d)", priv->mtu, priv->ip6_mtu); nm_device_set_mtu (self, priv->ip6_mtu); } @@ -5010,11 +5146,6 @@ act_stage3_ip6_config_start (NMDevice *self, ret = NM_ACT_STAGE_RETURN_POSTPONE; } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) { ret = linklocal6_start (self); - if (ret == NM_ACT_STAGE_RETURN_FINISH) { - /* New blank config; LL address is already in priv->ext_ip6_config */ - *out_config = nm_ip6_config_new (); - g_assert (*out_config); - } } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) { priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_MANAGED; if (!dhcp6_start (self, TRUE, reason)) { @@ -5903,26 +6034,19 @@ static void _update_ip4_address (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - struct ifreq req; - guint32 new_address; - int fd; - - g_return_if_fail (self != NULL); + guint32 addr; - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - _LOGE (LOGD_IP4, "couldn't open control socket."); - return; - } + g_return_if_fail (NM_IS_DEVICE (self)); - memset (&req, 0, sizeof (struct ifreq)); - strncpy (req.ifr_name, nm_device_get_ip_iface (self), IFNAMSIZ); - if (ioctl (fd, SIOCGIFADDR, &req) == 0) { - new_address = ((struct sockaddr_in *)(&req.ifr_addr))->sin_addr.s_addr; - if (new_address != priv->ip4_address) - priv->ip4_address = new_address; + if ( priv->ip4_config + && ip_config_valid (priv->state) + && nm_ip4_config_get_num_addresses (priv->ip4_config)) { + addr = nm_ip4_config_get_address (priv->ip4_config, 0)->address; + if (addr != priv->ip4_address) { + priv->ip4_address = addr; + g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_ADDRESS); + } } - close (fd); } gboolean @@ -7497,6 +7621,59 @@ nm_device_set_dhcp_anycast_address (NMDevice *self, const char *addr) priv->dhcp_anycast_address = g_strdup (addr); } +static void +nm_device_update_metered (NMDevice *self) +{ +#define NM_METERED_INVALID ((NMMetered) -1) + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMSettingConnection *setting; + NMMetered conn_value, value = NM_METERED_INVALID; + NMConnection *connection = NULL; + NMDeviceState state; + + g_return_if_fail (NM_IS_DEVICE (self)); + + state = nm_device_get_state (self); + if ( state <= NM_DEVICE_STATE_DISCONNECTED + || state > NM_DEVICE_STATE_ACTIVATED) + value = NM_METERED_UNKNOWN; + + if (value == NM_METERED_INVALID) { + connection = nm_device_get_connection (self); + if (connection) { + setting = nm_connection_get_setting_connection (connection); + if (setting) { + conn_value = nm_setting_connection_get_metered (setting); + if (conn_value != NM_METERED_UNKNOWN) + value = conn_value; + } + } + } + + /* Try to guess a value using the metered flag in IP configuration */ + if (value == NM_METERED_INVALID) { + if ( priv->ip4_config + && priv->ip4_state == IP_DONE + && nm_ip4_config_get_metered (priv->ip4_config)) + value = NM_METERED_GUESS_YES; + } + + /* Otherwise look at connection type */ + if (value == NM_METERED_INVALID) { + if ( nm_connection_is_type (connection, NM_SETTING_GSM_SETTING_NAME) + || nm_connection_is_type (connection, NM_SETTING_CDMA_SETTING_NAME)) + value = NM_METERED_GUESS_YES; + else + value = NM_METERED_GUESS_NO; + } + + if (value != priv->metered) { + _LOGD (LOGD_DEVICE, "set metered value %d", value); + priv->metered = value; + g_object_notify (G_OBJECT (self), NM_DEVICE_METERED); + } +} + /** * nm_device_check_connection_available(): * @self: the #NMDevice @@ -7856,10 +8033,11 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) priv->default_route.v4_has = FALSE; priv->default_route.v4_is_assumed = TRUE; - priv->default_route.v4_configure_first_time = TRUE; priv->default_route.v6_has = FALSE; priv->default_route.v6_is_assumed = TRUE; - priv->default_route.v6_configure_first_time = TRUE; + + priv->v4_commit_first_time = TRUE; + priv->v6_commit_first_time = TRUE; nm_default_route_manager_ip4_update_default_route (nm_default_route_manager_get (), self); nm_default_route_manager_ip6_update_default_route (nm_default_route_manager_get (), self); @@ -7943,9 +8121,11 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean nm_device_master_release_slaves (self); /* slave: mark no longer enslaved */ - g_clear_object (&priv->master); - priv->enslaved = FALSE; - g_object_notify (G_OBJECT (self), NM_DEVICE_MASTER); + if (nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex) <= 0) { + g_clear_object (&priv->master); + priv->enslaved = FALSE; + g_object_notify (G_OBJECT (self), NM_DEVICE_MASTER); + } /* Take out any entries in the routing table and any IP address the device had. */ ifindex = nm_device_get_ip_ifindex (self); @@ -7954,6 +8134,7 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean nm_platform_address_flush (NM_PLATFORM_GET, ifindex); } + nm_device_update_metered (self); _cleanup_generic_post (self, cleanup_type); } @@ -8426,6 +8607,7 @@ _set_state_full (NMDevice *self, break; case NM_DEVICE_STATE_ACTIVATED: _LOGI (LOGD_DEVICE, "Activation: successful, device activated."); + nm_device_update_metered (self); nm_dispatcher_call (DISPATCHER_ACTION_UP, nm_act_request_get_connection (req), self, NULL, NULL, NULL); break; case NM_DEVICE_STATE_FAILED: @@ -8799,9 +8981,10 @@ nm_device_init (NMDevice *self) priv->ip6_saved_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free); priv->default_route.v4_is_assumed = TRUE; - priv->default_route.v4_configure_first_time = TRUE; priv->default_route.v6_is_assumed = TRUE; - priv->default_route.v6_configure_first_time = TRUE; + + priv->v4_commit_first_time = TRUE; + priv->v6_commit_first_time = TRUE; } static GObject* @@ -9298,6 +9481,9 @@ get_property (GObject *object, guint prop_id, case PROP_HAS_PENDING_ACTION: g_value_set_boolean (value, nm_device_has_pending_action (self)); break; + case PROP_METERED: + g_value_set_uint (value, priv->metered); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -9561,6 +9747,20 @@ nm_device_class_init (NMDeviceClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * NMDevice:metered: + * + * Whether the connection is metered. + * + * Since: 1.0.6 + **/ + g_object_class_install_property + (object_class, PROP_METERED, + g_param_spec_uint (NM_DEVICE_METERED, "", "", + 0, G_MAXUINT32, NM_METERED_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + /* Signals */ signals[STATE_CHANGED] = g_signal_new ("state-changed", diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index f1dab9bf..e9d5b948 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -58,6 +58,7 @@ #define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id" #define NM_DEVICE_MTU "mtu" #define NM_DEVICE_HW_ADDRESS "hw-address" +#define NM_DEVICE_METERED "metered" #define NM_DEVICE_TYPE_DESC "type-desc" /* Internal only */ #define NM_DEVICE_RFKILL_TYPE "rfkill-type" /* Internal only */ @@ -74,7 +75,6 @@ #define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate" #define NM_DEVICE_RECHECK_ASSUME "recheck-assume" - G_BEGIN_DECLS #define NM_TYPE_DEVICE (nm_device_get_type ()) @@ -281,6 +281,7 @@ const char * nm_device_get_driver_version (NMDevice *dev); const char * nm_device_get_type_desc (NMDevice *dev); const char * nm_device_get_type_description (NMDevice *dev); NMDeviceType nm_device_get_device_type (NMDevice *dev); +NMMetered nm_device_get_metered (NMDevice *dev); int nm_device_get_priority (NMDevice *dev); guint32 nm_device_get_ip4_route_metric (NMDevice *dev); diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index 23750f35..09b2dd7d 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -40,6 +40,7 @@ #include "nm-enum-types.h" #include "nm-team-enum-types.h" #include "nm-core-internal.h" +#include "nm-ip4-config.h" #include "gsystem-local-alloc.h" #include "nm-device-team-glue.h" @@ -565,6 +566,25 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) } static void +ip4_config_pre_commit (NMDevice *self, NMIP4Config *config) +{ + NMConnection *connection; + NMSettingWired *s_wired; + guint32 mtu; + + connection = nm_device_get_connection (self); + g_assert (connection); + s_wired = nm_connection_get_setting_wired (connection); + + if (s_wired) { + /* MTU override */ + mtu = nm_setting_wired_get_mtu (s_wired); + if (mtu) + nm_ip4_config_set_mtu (config, mtu, NM_IP_CONFIG_SOURCE_USER); + } +} + +static void deactivate (NMDevice *device) { NMDeviceTeam *self = NM_DEVICE_TEAM (device); @@ -813,6 +833,7 @@ nm_device_team_class_init (NMDeviceTeamClass *klass) parent_class->master_update_slave_connection = master_update_slave_connection; parent_class->act_stage1_prepare = act_stage1_prepare; + parent_class->ip4_config_pre_commit = ip4_config_pre_commit; parent_class->deactivate = deactivate; parent_class->enslave_slave = enslave_slave; parent_class->release_slave = release_slave; diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 2e116f87..dde743b1 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -55,6 +55,7 @@ #include "nm-dbus-glib-types.h" #include "nm-wifi-enum-types.h" #include "nm-connection-provider.h" +#include "gsystem-local-alloc.h" static gboolean impl_device_get_access_points (NMDeviceWifi *device, @@ -178,7 +179,7 @@ static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface, static void schedule_scanlist_cull (NMDeviceWifi *self); -static gboolean request_wireless_scan (gpointer user_data); +static void request_wireless_scan (NMDeviceWifi *self, GHashTable *scan_options); static void remove_access_point (NMDeviceWifi *device, NMAccessPoint *ap); @@ -753,7 +754,7 @@ deactivate (NMDevice *device) /* Ensure we trigger a scan after deactivating a Hotspot */ if (old_mode == NM_802_11_MODE_AP) { cancel_pending_scan (self); - request_wireless_scan (self); + request_wireless_scan (self, NULL); } } @@ -1253,6 +1254,7 @@ request_scan_cb (NMDevice *device, { NMDeviceWifi *self = NM_DEVICE_WIFI (device); GError *local = NULL; + gs_unref_hashtable GHashTable *new_scan_options = user_data; if (error) { dbus_g_method_return_error (context, error); @@ -1269,7 +1271,7 @@ request_scan_cb (NMDevice *device, } cancel_pending_scan (self); - request_wireless_scan (self); + request_wireless_scan (self, new_scan_options); dbus_g_method_return (context); } @@ -1316,7 +1318,7 @@ impl_device_request_scan (NMDeviceWifi *self, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, request_scan_cb, - NULL); + options ? g_hash_table_ref (options) : NULL); return; error: @@ -1482,23 +1484,31 @@ build_hidden_probe_list (NMDeviceWifi *self) return ssids; } -static gboolean -request_wireless_scan (gpointer user_data) +static void +request_wireless_scan (NMDeviceWifi *self, GHashTable *scan_options) { - NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); gboolean backoff = FALSE; GPtrArray *ssids = NULL; if (priv->requested_scan) { /* There's already a scan in progress */ - return FALSE; + return; } if (check_scanning_allowed (self)) { _LOGD (LOGD_WIFI_SCAN, "scanning requested"); - ssids = build_hidden_probe_list (self); + if (scan_options && g_hash_table_size (scan_options)) { + GValue *val = g_hash_table_lookup (scan_options, "ssids"); + + if (val && G_VALUE_HOLDS (val, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR)) + ssids = g_ptr_array_ref (g_value_get_boxed (val)); + else + _LOGD (LOGD_WIFI_SCAN, "ignoring invalid scan options"); + } + if (!ssids) + ssids = build_hidden_probe_list (self); if (nm_logging_enabled (LOGL_DEBUG, LOGD_WIFI_SCAN)) { if (ssids) { @@ -1533,9 +1543,14 @@ request_wireless_scan (gpointer user_data) priv->pending_scan_id = 0; schedule_scan (self, backoff); - return FALSE; } +static gboolean +request_wireless_scan_periodic (gpointer user_data) +{ + request_wireless_scan (user_data, NULL); + return FALSE; +} /* * schedule_scan @@ -1563,7 +1578,7 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff) factor = 1; priv->pending_scan_id = g_timeout_add_seconds (next_scan, - request_wireless_scan, + request_wireless_scan_periodic, self); priv->scheduled_scan_time = now + priv->scan_interval; @@ -3072,7 +3087,7 @@ device_state_changed (NMDevice *device, /* Kick off a scan to get latest results */ priv->scan_interval = SCAN_INTERVAL_MIN; cancel_pending_scan (self); - request_wireless_scan (self); + request_wireless_scan (self, NULL); break; default: break; diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index d70dd9a6..1485f4c1 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -79,6 +79,7 @@ enum { PROP_MODE, PROP_MAX_BITRATE, PROP_STRENGTH, + PROP_LAST_SEEN, LAST_PROP }; @@ -195,6 +196,12 @@ get_property (GObject *object, guint prop_id, case PROP_STRENGTH: g_value_set_schar (value, priv->strength); break; + case PROP_LAST_SEEN: + g_value_set_int (value, + priv->last_seen > 0 + ? (gint) nm_utils_monotonic_timestamp_as_boottime (priv->last_seen, NM_UTILS_NS_PER_SECOND) + : -1); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -294,6 +301,13 @@ nm_ap_class_init (NMAccessPointClass *ap_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_LAST_SEEN, + g_param_spec_int (NM_AP_LAST_SEEN, "", "", + -1, G_MAXINT, -1, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), G_TYPE_FROM_CLASS (ap_class), &dbus_glib_nm_access_point_object_info); @@ -1056,7 +1070,7 @@ void nm_ap_set_broadcast (NMAccessPoint *ap, gboolean broadcast) gint32 nm_ap_get_last_seen (const NMAccessPoint *ap) { - g_return_val_if_fail (NM_IS_AP (ap), FALSE); + g_return_val_if_fail (NM_IS_AP (ap), 0); return NM_AP_GET_PRIVATE (ap)->last_seen; } @@ -1064,9 +1078,16 @@ nm_ap_get_last_seen (const NMAccessPoint *ap) void nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen) { + NMAccessPointPrivate *priv; + g_return_if_fail (NM_IS_AP (ap)); - NM_AP_GET_PRIVATE (ap)->last_seen = last_seen; + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->last_seen != last_seen) { + priv->last_seen = last_seen; + g_object_notify (G_OBJECT (ap), NM_AP_LAST_SEEN); + } } gboolean diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h index 8ad9acb7..67d30769 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/devices/wifi/nm-wifi-ap.h @@ -43,6 +43,7 @@ #define NM_AP_MODE "mode" #define NM_AP_MAX_BITRATE "max-bitrate" #define NM_AP_STRENGTH "strength" +#define NM_AP_LAST_SEEN "last-seen" typedef struct { GObject parent; diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c index eb317330..7f5d5a28 100644 --- a/src/dhcp-manager/nm-dhcp-client.c +++ b/src/dhcp-manager/nm-dhcp-client.c @@ -36,6 +36,7 @@ #include "nm-dhcp-client.h" #include "nm-dhcp-utils.h" #include "nm-platform.h" +#include "gsystem-local-alloc.h" typedef struct { char * iface; @@ -284,6 +285,7 @@ nm_dhcp_client_set_state (NMDhcpClient *self, GHashTable *options) { NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + gs_free char *event_id = NULL; if (new_state >= NM_DHCP_STATE_BOUND) timeout_cleanup (self); @@ -308,19 +310,30 @@ nm_dhcp_client_set_state (NMDhcpClient *self, if ((priv->state == new_state) && (new_state != NM_DHCP_STATE_BOUND)) return; + if (priv->ipv6 && new_state == NM_DHCP_STATE_BOUND) { + char *start, *iaid; + + iaid = g_hash_table_lookup (options, "iaid"); + start = g_hash_table_lookup (options, "life_starts"); + if (iaid && start) + event_id = g_strdup_printf ("%s|%s", iaid, start); + } + nm_log_info (priv->ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, - "(%s): DHCPv%c state changed %s -> %s", + "(%s): DHCPv%c state changed %s -> %s%s%s%s", priv->iface, priv->ipv6 ? '6' : '4', state_to_string (priv->state), - state_to_string (new_state)); + state_to_string (new_state), + NM_PRINT_FMT_QUOTED (event_id, ", event ID=\"", event_id, "\"", "")); priv->state = new_state; g_signal_emit (G_OBJECT (self), signals[SIGNAL_STATE_CHANGED], 0, new_state, ip_config, - options); + options, + event_id); } static gboolean @@ -977,6 +990,6 @@ nm_dhcp_client_class_init (NMDhcpClientClass *client_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMDhcpClientClass, state_changed), NULL, NULL, NULL, - G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_OBJECT, G_TYPE_HASH_TABLE); + G_TYPE_NONE, 4, G_TYPE_UINT, G_TYPE_OBJECT, G_TYPE_HASH_TABLE, G_TYPE_STRING); } diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c index f936f45c..20ddefc3 100644 --- a/src/dhcp-manager/nm-dhcp-manager.c +++ b/src/dhcp-manager/nm-dhcp-manager.c @@ -184,6 +184,7 @@ static void client_state_changed (NMDhcpClient *client, NMDhcpState state, GObject *ip_config, GHashTable *options, + const char *event_id, NMDhcpManager *self); static void @@ -204,6 +205,7 @@ client_state_changed (NMDhcpClient *client, NMDhcpState state, GObject *ip_config, GHashTable *options, + const char *event_id, NMDhcpManager *self) { if (state >= NM_DHCP_STATE_TIMEOUT) diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c index 12dc03cc..2bd0d72f 100644 --- a/src/dhcp-manager/nm-dhcp-systemd.c +++ b/src/dhcp-manager/nm-dhcp-systemd.c @@ -224,6 +224,8 @@ lease_to_ip4_config (sd_dhcp_lease *lease, guint16 mtu; int r, num; guint64 end_time; + uint8_t *data; + gboolean metered = FALSE; g_return_val_if_fail (lease != NULL, NULL); @@ -355,6 +357,11 @@ lease_to_ip4_config (sd_dhcp_lease *lease, g_string_free (l, TRUE); } + num = sd_dhcp_lease_get_vendor_specific (lease, &data); + if (num > 0) + metered = !!memmem (data, num, "ANDROID_METERED", STRLEN ("ANDROID_METERED")); + nm_ip4_config_set_metered (ip4_config, metered); + return ip4_config; } diff --git a/src/dhcp-manager/nm-dhcp-utils.c b/src/dhcp-manager/nm-dhcp-utils.c index 8cd4359a..ab7f26d5 100644 --- a/src/dhcp-manager/nm-dhcp-utils.c +++ b/src/dhcp-manager/nm-dhcp-utils.c @@ -575,6 +575,9 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface, g_strfreev (nis); } + str = g_hash_table_lookup (options, "vendor_encapsulated_options"); + nm_ip4_config_set_metered (ip4_config, str && strstr (str, "ANDROID_METERED")); + return ip4_config; error: diff --git a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-lease-internal.h b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-lease-internal.h index 9e184ac4..71f7f143 100644 --- a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-lease-internal.h @@ -72,6 +72,8 @@ struct sd_dhcp_lease { char *root_path; uint8_t *client_id; size_t client_id_len; + uint8_t *vendor_specific; + size_t vendor_specific_size; }; int dhcp_lease_new(sd_dhcp_lease **ret); diff --git a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-protocol.h b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-protocol.h index abca9422..aa37e9b0 100644 --- a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-protocol.h +++ b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-protocol.h @@ -125,6 +125,7 @@ enum { DHCP_OPTION_BROADCAST = 28, DHCP_OPTION_STATIC_ROUTE = 33, DHCP_OPTION_NTP_SERVER = 42, + DHCP_OPTION_VENDOR_SPECIFIC = 43, DHCP_OPTION_REQUESTED_IP_ADDRESS = 50, DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51, DHCP_OPTION_OVERLOAD = 52, diff --git a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp-lease.c b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp-lease.c index 2d13d503..0b5048a6 100644 --- a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp-lease.c @@ -191,6 +191,19 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes return 0; } +int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, uint8_t **data) { + assert_return(lease, -EINVAL); + assert_return(data, -EINVAL); + + if (lease->vendor_specific) { + *data = lease->vendor_specific; + return lease->vendor_specific_size; + } else + return -ENOENT; + + return 0; +} + sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) { if (lease) assert_se(REFCNT_INC(lease->n_ref) >= 2); @@ -286,6 +299,24 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) { return 0; } +static int lease_parse_binary(const uint8_t *option, size_t len, uint8_t **ret) { + assert (option); + assert (ret); + + if (len >= 1) { + uint8_t *data; + + data = memdup(option, len); + if (!data) + return -errno; + + free(*ret); + *ret = data; + } + + return 0; +} + static int lease_parse_in_addrs_aux(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size, size_t mult) { assert(option); assert(ret); @@ -568,6 +599,14 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option, return r; break; + + case DHCP_OPTION_VENDOR_SPECIFIC: + r = lease_parse_binary(option, len, &lease->vendor_specific); + if (r < 0) + return r; + lease->vendor_specific_size = len; + + break; } return 0; @@ -595,6 +634,7 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { const uint8_t *client_id; size_t client_id_len; const char *string; + uint8_t *data; uint16_t mtu; struct sd_dhcp_route *routes; int r; @@ -667,6 +707,18 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { if (r >= 0) serialize_dhcp_routes(f, "ROUTES", routes, r); + r = sd_dhcp_lease_get_vendor_specific(lease, &data); + if (r >= 0) { + _cleanup_free_ char *option_hex = NULL; + + option_hex = hexmem(data, r); + if (!option_hex) { + r = -ENOMEM; + goto finish; + } + fprintf(f, "VENDOR_SPECIFIC=%s\n", option_hex); + } + r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len); if (r >= 0) { _cleanup_free_ char *client_id_hex = NULL; diff --git a/src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h b/src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h index 4296b91d..079a1bb3 100644 --- a/src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h +++ b/src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h @@ -45,6 +45,7 @@ int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname); int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path); int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routesgn); +int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, uint8_t **data); int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id, size_t *client_id_len); diff --git a/src/dhcp-manager/tests/test-dhcp-utils.c b/src/dhcp-manager/tests/test-dhcp-utils.c index 53688a5b..618188df 100644 --- a/src/dhcp-manager/tests/test-dhcp-utils.c +++ b/src/dhcp-manager/tests/test-dhcp-utils.c @@ -72,7 +72,7 @@ static void test_generic_options (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const NMPlatformIP4Address *address; const NMPlatformIP4Route *route; guint32 tmp; @@ -147,7 +147,7 @@ static void test_wins_options (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const NMPlatformIP4Address *address; guint32 tmp; const char *expected_wins1 = "63.12.199.5"; @@ -176,6 +176,31 @@ test_wins_options (void) } static void +test_vendor_option_metered (void) +{ + GHashTable *options; + gs_unref_object NMIP4Config *ip4_config = NULL; + static const Option data[] = { + { "vendor_encapsulated_options", "ANDROID_METERED" }, + { NULL, NULL } + }; + + options = fill_table (generic_options, NULL); + ip4_config = nm_dhcp_utils_ip4_config_from_options ("eth0", options, 0); + g_assert (ip4_config); + g_assert (nm_ip4_config_get_metered (ip4_config) == FALSE); + g_hash_table_destroy (options); + g_clear_object (&ip4_config); + + options = fill_table (generic_options, NULL); + options = fill_table (data, options); + ip4_config = nm_dhcp_utils_ip4_config_from_options ("eth0", options, 0); + g_assert (ip4_config); + g_assert (nm_ip4_config_get_metered (ip4_config) == TRUE); + g_hash_table_destroy (options); +} + +static void ip4_test_route (NMIP4Config *ip4_config, guint route_num, const char *expected_dest, @@ -208,7 +233,7 @@ static void test_classless_static_routes_1 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; const char *expected_route2_dest = "10.0.0.0"; @@ -236,7 +261,7 @@ static void test_classless_static_routes_2 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; const char *expected_route2_dest = "10.0.0.0"; @@ -264,7 +289,7 @@ static void test_fedora_dhclient_classless_static_routes (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "129.210.177.128"; const char *expected_route1_gw = "192.168.0.113"; const char *expected_route2_dest = "2.0.0.0"; @@ -296,7 +321,7 @@ static void test_dhclient_invalid_classless_routes_1 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; static const Option data[] = { @@ -325,7 +350,7 @@ static void test_dhcpcd_invalid_classless_routes_1 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "10.1.1.5"; const char *expected_route1_gw = "10.1.1.1"; const char *expected_route2_dest = "100.99.88.56"; @@ -359,7 +384,7 @@ static void test_dhclient_invalid_classless_routes_2 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "10.1.1.5"; const char *expected_route1_gw = "10.1.1.1"; const char *expected_route2_dest = "100.99.88.56"; @@ -392,7 +417,7 @@ static void test_dhcpcd_invalid_classless_routes_2 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "10.1.1.5"; const char *expected_route1_gw = "10.1.1.1"; const char *expected_route2_dest = "100.99.88.56"; @@ -427,7 +452,7 @@ static void test_dhclient_invalid_classless_routes_3 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; static const Option data[] = { @@ -455,7 +480,7 @@ static void test_dhcpcd_invalid_classless_routes_3 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; static Option data[] = { @@ -483,7 +508,7 @@ static void test_dhclient_gw_in_classless_routes (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; const char *expected_gateway = "192.2.3.4"; @@ -511,7 +536,7 @@ static void test_dhcpcd_gw_in_classless_routes (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; const char *expected_gateway = "192.2.3.4"; @@ -539,7 +564,7 @@ static void test_escaped_domain_searches (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_search0 = "host1"; const char *expected_search1 = "host2"; const char *expected_search2 = "host3"; @@ -566,7 +591,7 @@ static void test_invalid_escaped_domain_searches (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; static const Option data[] = { { "domain_search", "host1\\aahost2\\032host3" }, { NULL, NULL } @@ -591,7 +616,7 @@ static void test_ip4_missing_prefix (const char *ip, guint32 expected_prefix) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const NMPlatformIP4Address *address; options = fill_table (generic_options, NULL); @@ -631,7 +656,7 @@ static void test_ip4_prefix_classless (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const NMPlatformIP4Address *address; /* Ensure that the missing-subnet-mask handler doesn't mangle classless @@ -716,6 +741,7 @@ int main (int argc, char **argv) g_test_add_func ("/dhcp/ip4-missing-prefix-8", test_ip4_missing_prefix_8); g_test_add_func ("/dhcp/ip4-prefix-classless", test_ip4_prefix_classless); g_test_add_func ("/dhcp/client-id-from-string", test_client_id_from_string); + g_test_add_func ("/dhcp/vendor-option-metered", test_vendor_option_metered); return g_test_run (); } diff --git a/src/main.c b/src/main.c index dfc307b5..495262ef 100644 --- a/src/main.c +++ b/src/main.c @@ -476,13 +476,7 @@ main (int argc, char *argv[]) net_enabled, wifi_enabled, wwan_enabled, - wimax_enabled, - &error); - if (manager == NULL) { - nm_log_err (LOGD_CORE, "failed to initialize the network manager: %s", - error && error->message ? error->message : "(unknown)"); - goto done; - } + wimax_enabled); /* Initialize the supplicant manager */ sup_mgr = nm_supplicant_manager_get (); diff --git a/src/nm-access-point-glue.h b/src/nm-access-point-glue.h index ad4d5916..39b22cc2 100644 --- a/src/nm-access-point-glue.h +++ b/src/nm-access-point-glue.h @@ -68,6 +68,6 @@ const DBusGObjectInfo dbus_glib_nm_access_point_object_info = { 1, 0, "\0", "org.freedesktop.NetworkManager.AccessPoint\0PropertiesChanged\0\0", -"org.freedesktop.NetworkManager.AccessPoint\0Flags\0flags\0read\0org.freedesktop.NetworkManager.AccessPoint\0WpaFlags\0wpa_flags\0read\0org.freedesktop.NetworkManager.AccessPoint\0RsnFlags\0rsn_flags\0read\0org.freedesktop.NetworkManager.AccessPoint\0Ssid\0ssid\0read\0org.freedesktop.NetworkManager.AccessPoint\0Frequency\0frequency\0read\0org.freedesktop.NetworkManager.AccessPoint\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.AccessPoint\0Mode\0mode\0read\0org.freedesktop.NetworkManager.AccessPoint\0MaxBitrate\0max_bitrate\0read\0org.freedesktop.NetworkManager.AccessPoint\0Strength\0strength\0read\0\0" +"org.freedesktop.NetworkManager.AccessPoint\0Flags\0flags\0read\0org.freedesktop.NetworkManager.AccessPoint\0WpaFlags\0wpa_flags\0read\0org.freedesktop.NetworkManager.AccessPoint\0RsnFlags\0rsn_flags\0read\0org.freedesktop.NetworkManager.AccessPoint\0Ssid\0ssid\0read\0org.freedesktop.NetworkManager.AccessPoint\0Frequency\0frequency\0read\0org.freedesktop.NetworkManager.AccessPoint\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.AccessPoint\0Mode\0mode\0read\0org.freedesktop.NetworkManager.AccessPoint\0MaxBitrate\0max_bitrate\0read\0org.freedesktop.NetworkManager.AccessPoint\0Strength\0strength\0read\0org.freedesktop.NetworkManager.AccessPoint\0LastSeen\0last_seen\0read\0\0" }; diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index d40d571e..3a8e6cf5 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -100,6 +100,7 @@ enum { enum { DEVICE_CHANGED, + DEVICE_METERED_CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -109,6 +110,29 @@ static void _device_cleanup (NMActiveConnection *self); /****************************************************************/ +#define _NMLOG_DOMAIN LOGD_DEVICE +#define _NMLOG_PREFIX_NAME "active-connection" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + const NMLogLevel __level = (level); \ + \ + if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ + char __prefix[128]; \ + const char *__p_prefix = _NMLOG_PREFIX_NAME; \ + const void *const __self = (self); \ + \ + if (__self) { \ + g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ + __p_prefix = __prefix; \ + } \ + _nm_log (__level, _NMLOG_DOMAIN, 0, \ + "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + __p_prefix _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } \ + } G_STMT_END + +/****************************************************************/ + static const char * state_to_string (NMActiveConnectionState state) { @@ -401,6 +425,18 @@ device_master_changed (GObject *object, } } +static void +device_metered_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + NMActiveConnection *self = (NMActiveConnection *) user_data; + NMDevice *device = NM_DEVICE (object); + + g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self)); + g_signal_emit (self, signals[DEVICE_METERED_CHANGED], 0, nm_device_get_metered (device)); +} + gboolean nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device) { @@ -427,6 +463,8 @@ nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device) G_CALLBACK (device_state_changed), self); g_signal_connect (device, "notify::master", G_CALLBACK (device_master_changed), self); + g_signal_connect (device, "notify::" NM_DEVICE_METERED, + G_CALLBACK (device_metered_changed), self); if (!priv->assumed) { priv->pending_activation_id = g_strdup_printf ("activation::%p", (void *)self); @@ -473,15 +511,15 @@ check_master_ready (NMActiveConnection *self) NMActiveConnectionState master_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN; if (priv->state != NM_ACTIVE_CONNECTION_STATE_ACTIVATING) { - nm_log_dbg (LOGD_DEVICE, "(%p): not signalling master-ready (not activating)", self); + _LOGD ("not signalling master-ready (not activating)"); return; } if (!priv->master) { - nm_log_dbg (LOGD_DEVICE, "(%p): not signalling master-ready (no master)", self); + _LOGD ("not signalling master-ready (no master)"); return; } if (priv->master_ready) { - nm_log_dbg (LOGD_DEVICE, "(%p): not signalling master-ready (already signaled)", self); + _LOGD ("not signalling master-ready (already signaled)"); return; } @@ -491,12 +529,12 @@ check_master_ready (NMActiveConnection *self) * or higher states. */ master_state = nm_active_connection_get_state (priv->master); - nm_log_dbg (LOGD_DEVICE, "(%p): master ActiveConnection [%p] state now '%s' (%d)", - self, priv->master, state_to_string (master_state), master_state); + _LOGD ("master ActiveConnection [%p] state now '%s' (%d)", + priv->master, state_to_string (master_state), master_state); if ( master_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING || master_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { - nm_log_dbg (LOGD_DEVICE, "(%p): signalling master-ready", self); + _LOGD ("signalling master-ready"); priv->master_ready = TRUE; g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_INT_MASTER_READY); @@ -520,8 +558,8 @@ master_state_cb (NMActiveConnection *master, check_master_ready (self); - nm_log_dbg (LOGD_DEVICE, "(%p): master ActiveConnection [%p] state now '%s' (%d)", - self, master, state_to_string (master_state), master_state); + _LOGD ("master ActiveConnection [%p] state now '%s' (%d)", + master, state_to_string (master_state), master_state); if ( master_state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING && !priv->master_ready) { @@ -558,8 +596,8 @@ nm_active_connection_set_master (NMActiveConnection *self, NMActiveConnection *m g_return_if_fail (priv->device != nm_active_connection_get_device (master)); } - nm_log_dbg (LOGD_DEVICE, "(%p): master ActiveConnection is [%p] %s", - self, master, nm_active_connection_get_id (master)); + _LOGD ("master ActiveConnection is [%p] %s", + master, nm_active_connection_get_id (master)); priv->master = g_object_ref (master); g_signal_connect (priv->master, @@ -838,6 +876,7 @@ _device_cleanup (NMActiveConnection *self) if (priv->device) { g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_state_changed), self); g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_master_changed), self); + g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_metered_changed), self); } if (priv->pending_activation_id) { @@ -1043,6 +1082,14 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class) NULL, NULL, NULL, G_TYPE_NONE, 2, NM_TYPE_DEVICE, NM_TYPE_DEVICE); + signals[DEVICE_METERED_CHANGED] = + g_signal_new (NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMActiveConnectionClass, device_metered_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_UINT); + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), G_TYPE_FROM_CLASS (ac_class), &dbus_glib_nm_active_connection_object_info); diff --git a/src/nm-active-connection.h b/src/nm-active-connection.h index 710cfeed..4db5e6ff 100644 --- a/src/nm-active-connection.h +++ b/src/nm-active-connection.h @@ -57,7 +57,8 @@ #define NM_ACTIVE_CONNECTION_INT_MASTER_READY "int-master-ready" /* Internal signals*/ -#define NM_ACTIVE_CONNECTION_DEVICE_CHANGED "device-changed" +#define NM_ACTIVE_CONNECTION_DEVICE_CHANGED "device-changed" +#define NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED "device-metered-changed" struct _NMActiveConnection { GObject parent; @@ -78,6 +79,9 @@ typedef struct { void (*device_changed) (NMActiveConnection *connection, NMDevice *new_device, NMDevice *old_device); + + void (*device_metered_changed) (NMActiveConnection *connection, + NMMetered new_value); } NMActiveConnectionClass; GType nm_active_connection_get_type (void); diff --git a/src/nm-auth-manager.c b/src/nm-auth-manager.c index 8bd167ef..09a5791f 100644 --- a/src/nm-auth-manager.c +++ b/src/nm-auth-manager.c @@ -30,27 +30,21 @@ #define POLKIT_INTERFACE "org.freedesktop.PolicyKit1.Authority" -#define _LOG_DEFAULT_DOMAIN LOGD_CORE - -#define _LOG(level, domain, ...) \ +#define _NMLOG_PREFIX_NAME "auth" +#define _NMLOG_DOMAIN LOGD_CORE +#define _NMLOG(level, ...) \ G_STMT_START { \ - if (nm_logging_enabled ((level), (domain))) { \ - char __prefix[30] = "auth"; \ + if (nm_logging_enabled ((level), (_NMLOG_DOMAIN))) { \ + char __prefix[30] = _NMLOG_PREFIX_NAME; \ \ if ((self) != singleton_instance) \ - g_snprintf (__prefix, sizeof (__prefix), "auth[%p]", (self)); \ - _nm_log ((level), (domain), 0, \ + g_snprintf (__prefix, sizeof (__prefix), ""_NMLOG_PREFIX_NAME"[%p]", (self)); \ + _nm_log ((level), (_NMLOG_DOMAIN), 0, \ "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ __prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ } \ } G_STMT_END -#define _LOGD(...) _LOG (LOGL_DEBUG, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) -#define _LOGI(...) _LOG (LOGL_INFO, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) -#define _LOGW(...) _LOG (LOGL_WARN, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) -#define _LOGE(...) _LOG (LOGL_ERR, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) - - enum { PROP_0, PROP_POLKIT_ENABLED, diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index 81ac8f9d..e7e52cae 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -36,24 +36,15 @@ G_DEFINE_TYPE (NMConnectivity, nm_connectivity, G_TYPE_OBJECT) #define NM_CONNECTIVITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONNECTIVITY, NMConnectivityPrivate)) - -#define _LOG_DEFAULT_DOMAIN LOGD_CONCHECK - -#define _LOG(level, domain, ...) \ +#define _NMLOG_DOMAIN LOGD_CONCHECK +#define _NMLOG(level, ...) \ G_STMT_START { \ - nm_log ((level), (domain), \ + nm_log ((level), (_NMLOG_DOMAIN), \ "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ "connectivity: " \ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ } G_STMT_END -#define _LOGT(...) _LOG (LOGL_TRACE, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) -#define _LOGD(...) _LOG (LOGL_DEBUG, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) -#define _LOGI(...) _LOG (LOGL_INFO, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) -#define _LOGW(...) _LOG (LOGL_WARN, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) -#define _LOGE(...) _LOG (LOGL_ERR, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) - - typedef struct { char *uri; char *response; @@ -151,25 +142,31 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_ goto done; } - /* Check headers; if we find the NM-specific one we're done */ - nm_header = soup_message_headers_get_one (msg->response_headers, "X-NetworkManager-Status"); - if (g_strcmp0 (nm_header, "online") == 0) { - _LOGD ("check for uri '%s' with Status header successful.", uri); - new_state = NM_CONNECTIVITY_FULL; - } else if (msg->status_code == SOUP_STATUS_OK) { - /* check response */ - if (msg->response_body->data && g_str_has_prefix (msg->response_body->data, response)) { - _LOGD ("check for uri '%s' successful.", uri); + if (msg->status_code == 511) { + _LOGD ("check for uri '%s' returned status '%d %s'; captive portal present.", + uri, msg->status_code, msg->reason_phrase); + new_state = NM_CONNECTIVITY_PORTAL; + } else { + /* Check headers; if we find the NM-specific one we're done */ + nm_header = soup_message_headers_get_one (msg->response_headers, "X-NetworkManager-Status"); + if (g_strcmp0 (nm_header, "online") == 0) { + _LOGD ("check for uri '%s' with Status header successful.", uri); new_state = NM_CONNECTIVITY_FULL; + } else if (msg->status_code == SOUP_STATUS_OK) { + /* check response */ + if (msg->response_body->data && g_str_has_prefix (msg->response_body->data, response)) { + _LOGD ("check for uri '%s' successful.", uri); + new_state = NM_CONNECTIVITY_FULL; + } else { + _LOGI ("check for uri '%s' did not match expected response '%s'; assuming captive portal.", + uri, response); + new_state = NM_CONNECTIVITY_PORTAL; + } } else { - _LOGI ("check for uri '%s' did not match expected response '%s'; assuming captive portal.", - uri, response); + _LOGI ("check for uri '%s' returned status '%d %s'; assuming captive portal.", + uri, msg->status_code, msg->reason_phrase); new_state = NM_CONNECTIVITY_PORTAL; } - } else { - _LOGI ("check for uri '%s' returned status '%d %s'; assuming captive portal.", - uri, msg->status_code, msg->reason_phrase); - new_state = NM_CONNECTIVITY_PORTAL; } done: @@ -365,12 +362,14 @@ set_property (GObject *object, guint property_id, NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); const char *uri, *response; guint interval; + gboolean changed; switch (property_id) { case PROP_URI: uri = g_value_get_string (value); if (uri && !*uri) uri = NULL; + changed = g_strcmp0 (uri, priv->uri) != 0; #if WITH_CONCHECK if (uri) { SoupURI *soup_uri = soup_uri_new (uri); @@ -379,11 +378,14 @@ set_property (GObject *object, guint property_id, _LOGE ("invalid uri '%s' for connectivity check.", uri); uri = NULL; } + if (uri && soup_uri && changed && + soup_uri_get_scheme(soup_uri) == SOUP_URI_SCHEME_HTTPS) + _LOGW ("use of HTTPS for connectivity checking is not reliable and is discouraged (URI: %s)", uri); if (soup_uri) soup_uri_free (soup_uri); } #endif - if (g_strcmp0 (uri, priv->uri) != 0) { + if (changed) { g_free (priv->uri); priv->uri = g_strdup (uri); _reschedule_periodic_checks (self, TRUE); diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c index fbb07ce3..96a8c855 100644 --- a/src/nm-default-route-manager.c +++ b/src/nm-default-route-manager.c @@ -21,10 +21,9 @@ #include "config.h" -#include "nm-default-route-manager.h" - -#include "string.h" +#include <string.h> +#include "nm-default-route-manager.h" #include "nm-logging.h" #include "nm-device.h" #include "nm-vpn-connection.h" @@ -62,7 +61,17 @@ G_DEFINE_TYPE (NMDefaultRouteManager, nm_default_route_manager, G_TYPE_OBJECT) NM_DEFINE_SINGLETON_GETTER (NMDefaultRouteManager, nm_default_route_manager_get, NM_TYPE_DEFAULT_ROUTE_MANAGER); -#define _LOG(level, addr_family, ...) \ +#define _NMLOG_PREFIX_NAME "default-route" +#undef _NMLOG_ENABLED +#define _NMLOG_ENABLED(level, addr_family) \ + ({ \ + const int __addr_family = (addr_family); \ + const NMLogLevel __level = (level); \ + const NMLogDomain __domain = __addr_family == AF_INET ? LOGD_IP4 : (__addr_family == AF_INET6 ? LOGD_IP6 : LOGD_IP); \ + \ + nm_logging_enabled (__level, __domain); \ + }) +#define _NMLOG(level, addr_family, ...) \ G_STMT_START { \ const int __addr_family = (addr_family); \ const NMLogLevel __level = (level); \ @@ -70,23 +79,18 @@ NM_DEFINE_SINGLETON_GETTER (NMDefaultRouteManager, nm_default_route_manager_get, \ if (nm_logging_enabled (__level, __domain)) { \ char __ch = __addr_family == AF_INET ? '4' : (__addr_family == AF_INET6 ? '6' : '-'); \ - char __prefix[30] = "default-route"; \ + char __prefix[30] = _NMLOG_PREFIX_NAME; \ \ if ((self) != singleton_instance) \ - g_snprintf (__prefix, sizeof (__prefix), "default-route%c[%p]", __ch, (self)); \ + g_snprintf (__prefix, sizeof (__prefix), ""_NMLOG_PREFIX_NAME"%c[%p]", __ch, (self)); \ else \ - __prefix[STRLEN ("default-route")] = __ch; \ + __prefix[STRLEN (_NMLOG_PREFIX_NAME)] = __ch; \ _nm_log (__level, __domain, 0, \ "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ __prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ } \ } G_STMT_END -#define _LOGD(addr_family, ...) _LOG (LOGL_DEBUG, addr_family, __VA_ARGS__) -#define _LOGI(addr_family, ...) _LOG (LOGL_INFO , addr_family, __VA_ARGS__) -#define _LOGW(addr_family, ...) _LOG (LOGL_WARN , addr_family, __VA_ARGS__) -#define _LOGE(addr_family, ...) _LOG (LOGL_ERR , addr_family, __VA_ARGS__) - #define LOG_ENTRY_FMT "entry[%u/%s:%p:%s:%c:%csync]" #define LOG_ENTRY_ARGS(entry_idx, entry) \ (entry_idx), \ @@ -1290,7 +1294,9 @@ _resync_idle_reschedule (NMDefaultRouteManager *self) g_source_remove (priv->resync.idle_handle); else _LOGD (0, "resync: schedule on idle"); - priv->resync.idle_handle = g_idle_add ((GSourceFunc) _resync_idle_now, self); + /* Schedule this at low priority so that on an external change to platform + * a NMDevice has a chance to picks up the changes first. */ + priv->resync.idle_handle = g_idle_add_full (G_PRIORITY_LOW, (GSourceFunc) _resync_idle_now, self, NULL); } else if (!priv->resync.idle_handle) { priv->resync.idle_handle = g_timeout_add (priv->resync.backoff_wait_time_ms, (GSourceFunc) _resync_idle_now, self); _LOGD (0, "resync: schedule in %u.%03u seconds (%u)", priv->resync.backoff_wait_time_ms/1000, diff --git a/src/nm-device-glue.h b/src/nm-device-glue.h index a740b7a7..c511c84c 100644 --- a/src/nm-device-glue.h +++ b/src/nm-device-glue.h @@ -74,6 +74,6 @@ const DBusGObjectInfo dbus_glib_nm_device_object_info = { 1, 2, "org.freedesktop.NetworkManager.Device\0Disconnect\0A\0\0org.freedesktop.NetworkManager.Device\0Delete\0A\0\0\0", "org.freedesktop.NetworkManager.Device\0StateChanged\0\0", -"org.freedesktop.NetworkManager.Device\0Udi\0udi\0read\0org.freedesktop.NetworkManager.Device\0Interface\0interface\0read\0org.freedesktop.NetworkManager.Device\0IpInterface\0ip_interface\0read\0org.freedesktop.NetworkManager.Device\0Driver\0driver\0read\0org.freedesktop.NetworkManager.Device\0DriverVersion\0driver_version\0read\0org.freedesktop.NetworkManager.Device\0FirmwareVersion\0firmware_version\0read\0org.freedesktop.NetworkManager.Device\0Capabilities\0capabilities\0read\0org.freedesktop.NetworkManager.Device\0Ip4Address\0ip4_address\0read\0org.freedesktop.NetworkManager.Device\0State\0state\0read\0org.freedesktop.NetworkManager.Device\0StateReason\0state_reason\0read\0org.freedesktop.NetworkManager.Device\0ActiveConnection\0active_connection\0read\0org.freedesktop.NetworkManager.Device\0Ip4Config\0ip4_config\0read\0org.freedesktop.NetworkManager.Device\0Dhcp4Config\0dhcp4_config\0read\0org.freedesktop.NetworkManager.Device\0Ip6Config\0ip6_config\0read\0org.freedesktop.NetworkManager.Device\0Dhcp6Config\0dhcp6_config\0read\0org.freedesktop.NetworkManager.Device\0Managed\0managed\0read\0org.freedesktop.NetworkManager.Device\0Autoconnect\0autoconnect\0readwrite\0org.freedesktop.NetworkManager.Device\0FirmwareMissing\0firmware_missing\0read\0org.freedesktop.NetworkManager.Device\0DeviceType\0device_type\0read\0org.freedesktop.NetworkManager.Device\0AvailableConnections\0available_connections\0read\0org.freedesktop.NetworkManager.Device\0PhysicalPortId\0physical_port_id\0read\0org.freedesktop.NetworkManager.Device\0Mtu\0mtu\0read\0\0" +"org.freedesktop.NetworkManager.Device\0Udi\0udi\0read\0org.freedesktop.NetworkManager.Device\0Interface\0interface\0read\0org.freedesktop.NetworkManager.Device\0IpInterface\0ip_interface\0read\0org.freedesktop.NetworkManager.Device\0Driver\0driver\0read\0org.freedesktop.NetworkManager.Device\0DriverVersion\0driver_version\0read\0org.freedesktop.NetworkManager.Device\0FirmwareVersion\0firmware_version\0read\0org.freedesktop.NetworkManager.Device\0Capabilities\0capabilities\0read\0org.freedesktop.NetworkManager.Device\0Ip4Address\0ip4_address\0read\0org.freedesktop.NetworkManager.Device\0State\0state\0read\0org.freedesktop.NetworkManager.Device\0StateReason\0state_reason\0read\0org.freedesktop.NetworkManager.Device\0ActiveConnection\0active_connection\0read\0org.freedesktop.NetworkManager.Device\0Ip4Config\0ip4_config\0read\0org.freedesktop.NetworkManager.Device\0Dhcp4Config\0dhcp4_config\0read\0org.freedesktop.NetworkManager.Device\0Ip6Config\0ip6_config\0read\0org.freedesktop.NetworkManager.Device\0Dhcp6Config\0dhcp6_config\0read\0org.freedesktop.NetworkManager.Device\0Managed\0managed\0read\0org.freedesktop.NetworkManager.Device\0Autoconnect\0autoconnect\0readwrite\0org.freedesktop.NetworkManager.Device\0FirmwareMissing\0firmware_missing\0read\0org.freedesktop.NetworkManager.Device\0DeviceType\0device_type\0read\0org.freedesktop.NetworkManager.Device\0AvailableConnections\0available_connections\0read\0org.freedesktop.NetworkManager.Device\0PhysicalPortId\0physical_port_id\0read\0org.freedesktop.NetworkManager.Device\0Mtu\0mtu\0read\0org.freedesktop.NetworkManager.Device\0Metered\0metered\0read\0\0" }; diff --git a/src/nm-enum-types.c b/src/nm-enum-types.c index f92158d3..1ff95970 100644 --- a/src/nm-enum-types.c +++ b/src/nm-enum-types.c @@ -741,6 +741,26 @@ nm_pobject_type_get_type (void) return g_define_type_id__volatile; } GType +nm_ip_config_merge_flags_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GFlagsValue values[] = { + { NM_IP_CONFIG_MERGE_DEFAULT, "NM_IP_CONFIG_MERGE_DEFAULT", "default" }, + { NM_IP_CONFIG_MERGE_NO_ROUTES, "NM_IP_CONFIG_MERGE_NO_ROUTES", "no-routes" }, + { NM_IP_CONFIG_MERGE_NO_DNS, "NM_IP_CONFIG_MERGE_NO_DNS", "no-dns" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("NMIPConfigMergeFlags"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType nm_match_spec_match_type_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; diff --git a/src/nm-enum-types.h b/src/nm-enum-types.h index 86f17f04..0997211e 100644 --- a/src/nm-enum-types.h +++ b/src/nm-enum-types.h @@ -64,6 +64,8 @@ GType nm_link_type_get_type (void) G_GNUC_CONST; #define NM_TYPE_LINK_TYPE (nm_link_type_get_type ()) GType nm_pobject_type_get_type (void) G_GNUC_CONST; #define NM_TYPE_POBJECT_TYPE (nm_pobject_type_get_type ()) +GType nm_ip_config_merge_flags_get_type (void) G_GNUC_CONST; +#define NM_TYPE_IP_CONFIG_MERGE_FLAGS (nm_ip_config_merge_flags_get_type ()) GType nm_match_spec_match_type_get_type (void) G_GNUC_CONST; #define NM_TYPE_MATCH_SPEC_MATCH_TYPE (nm_match_spec_match_type_get_type ()) GType nm_utils_test_flags_get_type (void) G_GNUC_CONST; diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index 2192f36b..18966c57 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -87,6 +87,7 @@ dhcp4_state_changed (NMDhcpClient *client, NMDhcpState state, NMIP4Config *ip4_config, GHashTable *options, + const char *event_id, gpointer user_data) { static NMIP4Config *last_config = NULL; @@ -103,7 +104,7 @@ dhcp4_state_changed (NMDhcpClient *client, if (last_config) nm_ip4_config_subtract (existing, last_config); - nm_ip4_config_merge (existing, ip4_config); + nm_ip4_config_merge (existing, ip4_config, NM_IP_CONFIG_MERGE_DEFAULT); if (!nm_ip4_config_commit (existing, ifindex, TRUE, global_opt.priority_v4)) nm_log_warn (LOGD_DHCP4, "(%s): failed to apply DHCPv4 config", global_opt.ifname); @@ -240,7 +241,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da if (last_config) nm_ip6_config_subtract (existing, last_config); - nm_ip6_config_merge (existing, ip6_config); + nm_ip6_config_merge (existing, ip6_config, NM_IP_CONFIG_MERGE_DEFAULT); if (!nm_ip6_config_commit (existing, ifindex, TRUE)) nm_log_warn (LOGD_IP6, "(%s): failed to apply IPv6 config", global_opt.ifname); diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index db8c4b43..5918f3dc 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -35,6 +35,7 @@ #include "nm-core-internal.h" #include "nm-route-manager.h" #include "gsystem-local-alloc.h" +#include "nm-macros-internal.h" G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, G_TYPE_OBJECT) @@ -45,6 +46,7 @@ typedef struct { gboolean never_default; guint32 gateway; + gboolean has_gateway; GArray *addresses; GArray *routes; GArray *nameservers; @@ -56,6 +58,8 @@ typedef struct { GArray *wins; guint32 mtu; NMIPConfigSource mtu_source; + gint64 route_metric; + gboolean metered; } NMIP4ConfigPrivate; /* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */ @@ -185,7 +189,7 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) guint i; guint32 lowest_metric = G_MAXUINT32; guint32 old_gateway = 0; - gboolean has_gateway = FALSE; + gboolean old_has_gateway = FALSE; /* Slaves have no IP configuration */ if (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex) > 0) @@ -202,6 +206,7 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) /* Extract gateway from default route */ old_gateway = priv->gateway; + old_has_gateway = priv->has_gateway; for (i = 0; i < priv->routes->len; ) { const NMPlatformIP4Route *route = &g_array_index (priv->routes, NMPlatformIP4Route, i); @@ -210,7 +215,7 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) priv->gateway = route->gateway; lowest_metric = route->metric; } - has_gateway = TRUE; + priv->has_gateway = TRUE; /* Remove the default route from the list */ g_array_remove_index_fast (priv->routes, i); continue; @@ -218,10 +223,14 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) i++; } + /* we detect the route metric based on the default route. All non-default + * routes have their route metrics explicitly set. */ + priv->route_metric = priv->has_gateway ? (gint64) lowest_metric : (gint64) -1; + /* If there is a host route to the gateway, ignore that route. It is * automatically added by NetworkManager when needed. */ - if (has_gateway) { + if (priv->has_gateway) { for (i = 0; i < priv->routes->len; i++) { const NMPlatformIP4Route *route = &g_array_index (priv->routes, NMPlatformIP4Route, i); @@ -237,7 +246,7 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) /* If the interface has the default route, and has IPv4 addresses, capture * nameservers from /etc/resolv.conf. */ - if (priv->addresses->len && has_gateway && capture_resolv_conf) { + if (priv->addresses->len && priv->has_gateway && capture_resolv_conf) { if (nm_ip4_config_capture_resolv_conf (priv->nameservers, NULL)) _NOTIFY (config, PROP_NAMESERVERS); } @@ -247,7 +256,8 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) _NOTIFY (config, PROP_ROUTE_DATA); _NOTIFY (config, PROP_ADDRESSES); _NOTIFY (config, PROP_ROUTES); - if (priv->gateway != old_gateway) + if ( priv->gateway != old_gateway + || priv->has_gateway != old_has_gateway) _NOTIFY (config, PROP_GATEWAY); return config; @@ -335,6 +345,7 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_fu void nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, guint32 default_route_metric) { + NMIP4ConfigPrivate *priv; guint naddresses, nroutes, nnameservers, nsearches; int i; @@ -343,6 +354,8 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting)); + priv = NM_IP4_CONFIG_GET_PRIVATE (config); + g_object_freeze_notify (G_OBJECT (config)); naddresses = nm_setting_ip_config_get_num_addresses (setting); @@ -362,6 +375,9 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu nm_ip4_config_set_gateway (config, gateway); } + if (priv->route_metric == -1) + priv->route_metric = nm_setting_ip_config_get_route_metric (setting); + /* Addresses */ for (i = 0; i < naddresses; i++) { NMIPAddress *s_addr = nm_setting_ip_config_get_address (setting, i); @@ -430,6 +446,7 @@ nm_ip4_config_create_setting (const NMIP4Config *config) guint naddresses, nroutes, nnameservers, nsearches; const char *method = NULL; int i; + gint64 route_metric; s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new ()); @@ -445,6 +462,7 @@ nm_ip4_config_create_setting (const NMIP4Config *config) nroutes = nm_ip4_config_get_num_routes (config); nnameservers = nm_ip4_config_get_num_nameservers (config); nsearches = nm_ip4_config_get_num_searches (config); + route_metric = nm_ip4_config_get_route_metric (config); /* Addresses */ for (i = 0; i < naddresses; i++) { @@ -470,7 +488,7 @@ nm_ip4_config_create_setting (const NMIP4Config *config) } /* Gateway */ - if ( gateway + if ( nm_ip4_config_has_gateway (config) && nm_setting_ip_config_get_num_addresses (s_ip4) > 0) { g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, nm_utils_inet4_ntop (gateway, NULL), @@ -480,7 +498,11 @@ nm_ip4_config_create_setting (const NMIP4Config *config) /* Use 'disabled' if the method wasn't previously set */ if (!method) method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED; - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, method, NULL); + + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, method, + NM_SETTING_IP_CONFIG_ROUTE_METRIC, (gint64) route_metric, + NULL); /* Routes */ for (i = 0; i < nroutes; i++) { @@ -521,13 +543,17 @@ nm_ip4_config_create_setting (const NMIP4Config *config) /******************************************************************/ void -nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src) +nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFlags merge_flags) { + NMIP4ConfigPrivate *dst_priv, *src_priv; guint32 i; g_return_if_fail (src != NULL); g_return_if_fail (dst != NULL); + dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst); + src_priv = NM_IP4_CONFIG_GET_PRIVATE (src); + g_object_freeze_notify (G_OBJECT (dst)); /* addresses */ @@ -535,24 +561,37 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src) nm_ip4_config_add_address (dst, nm_ip4_config_get_address (src, i)); /* nameservers */ - for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) - nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i)); + if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) { + for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) + nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i)); + } /* default gateway */ - if (nm_ip4_config_get_gateway (src)) + if (nm_ip4_config_has_gateway (src)) nm_ip4_config_set_gateway (dst, nm_ip4_config_get_gateway (src)); /* routes */ - for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) - nm_ip4_config_add_route (dst, nm_ip4_config_get_route (src, i)); + if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) { + for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) + nm_ip4_config_add_route (dst, nm_ip4_config_get_route (src, i)); + } + + if (dst_priv->route_metric == -1) + dst_priv->route_metric = src_priv->route_metric; + else if (src_priv->route_metric != -1) + dst_priv->route_metric = MIN (dst_priv->route_metric, src_priv->route_metric); /* domains */ - for (i = 0; i < nm_ip4_config_get_num_domains (src); i++) - nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i)); + if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) { + for (i = 0; i < nm_ip4_config_get_num_domains (src); i++) + nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i)); + } /* dns searches */ - for (i = 0; i < nm_ip4_config_get_num_searches (src); i++) - nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i)); + if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) { + for (i = 0; i < nm_ip4_config_get_num_searches (src); i++) + nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i)); + } /* MSS */ if (nm_ip4_config_get_mss (src)) @@ -564,15 +603,23 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src) nm_ip4_config_get_mtu_source (src)); /* NIS */ - for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++) - nm_ip4_config_add_nis_server (dst, nm_ip4_config_get_nis_server (src, i)); + if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) { + for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++) + nm_ip4_config_add_nis_server (dst, nm_ip4_config_get_nis_server (src, i)); - if (nm_ip4_config_get_nis_domain (src)) - nm_ip4_config_set_nis_domain (dst, nm_ip4_config_get_nis_domain (src)); + if (nm_ip4_config_get_nis_domain (src)) + nm_ip4_config_set_nis_domain (dst, nm_ip4_config_get_nis_domain (src)); + } /* WINS */ - for (i = 0; i < nm_ip4_config_get_num_wins (src); i++) - nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i)); + if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) { + for (i = 0; i < nm_ip4_config_get_num_wins (src); i++) + nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i)); + } + + /* metered flag */ + nm_ip4_config_set_metered (dst, nm_ip4_config_get_metered (dst) || + nm_ip4_config_get_metered (src)); g_object_thaw_notify (G_OBJECT (dst)); } @@ -721,11 +768,14 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) } /* default gateway */ - if (nm_ip4_config_get_gateway (src) == nm_ip4_config_get_gateway (dst)) - nm_ip4_config_set_gateway (dst, 0); + if ( (nm_ip4_config_has_gateway (src) == nm_ip4_config_has_gateway (dst)) + && (nm_ip4_config_get_gateway (src) == nm_ip4_config_get_gateway (dst))) + nm_ip4_config_unset_gateway (dst); if (!nm_ip4_config_get_num_addresses (dst)) - nm_ip4_config_set_gateway (dst, 0); + nm_ip4_config_unset_gateway (dst); + + /* ignore route_metric */ /* routes */ for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) { @@ -796,12 +846,15 @@ nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src) i++; } + /* ignore route_metric */ /* ignore nameservers */ /* default gateway */ if ( !nm_ip4_config_get_num_addresses (dst) - || (nm_ip4_config_get_gateway (src) != nm_ip4_config_get_gateway (dst))) - nm_ip4_config_set_gateway (dst, 0); + || (nm_ip4_config_has_gateway (src) != nm_ip4_config_has_gateway (dst)) + || (nm_ip4_config_get_gateway (src) != nm_ip4_config_get_gateway (dst))) { + nm_ip4_config_unset_gateway (dst); + } /* routes */ for (i = 0; i < nm_ip4_config_get_num_routes (dst); ) { @@ -867,11 +920,17 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev } /* default gateway */ - if (src_priv->gateway != dst_priv->gateway) { + if ( src_priv->gateway != dst_priv->gateway + || src_priv->has_gateway != dst_priv->has_gateway) { nm_ip4_config_set_gateway (dst, src_priv->gateway); has_relevant_changes = TRUE; } + if (src_priv->route_metric != dst_priv->route_metric) { + dst_priv->route_metric = src_priv->route_metric; + has_minor_changes = TRUE; + } + /* addresses */ num = nm_ip4_config_get_num_addresses (src); are_equal = num == nm_ip4_config_get_num_addresses (dst); @@ -1028,6 +1087,12 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev has_minor_changes = TRUE; } + /* metered */ + if (src_priv->metered != dst_priv->metered) { + dst_priv->metered = src_priv->metered; + has_minor_changes = TRUE; + } + /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */ g_assert (config_equal == !has_relevant_changes); @@ -1059,8 +1124,10 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail) g_message (" a: %s", nm_platform_ip4_address_to_string (nm_ip4_config_get_address (config, i))); /* default gateway */ - tmp = nm_ip4_config_get_gateway (config); - g_message (" gw: %s", nm_utils_inet4_ntop (tmp, NULL)); + if (nm_ip4_config_has_gateway (config)) { + tmp = nm_ip4_config_get_gateway (config); + g_message (" gw: %s", nm_utils_inet4_ntop (tmp, NULL)); + } /* nameservers */ for (i = 0; i < nm_ip4_config_get_num_nameservers (config); i++) { @@ -1098,6 +1165,7 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail) } g_message (" n-dflt: %d", nm_ip4_config_get_never_default (config)); + g_message (" mtrd: %d", (int) nm_ip4_config_get_metered (config)); } gboolean @@ -1139,12 +1207,33 @@ nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - if (priv->gateway != gateway) { + if (priv->gateway != gateway || !priv->has_gateway) { priv->gateway = gateway; + priv->has_gateway = TRUE; _NOTIFY (config, PROP_GATEWAY); } } +void +nm_ip4_config_unset_gateway (NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + if (priv->has_gateway) { + priv->gateway = 0; + priv->has_gateway = FALSE; + _NOTIFY (config, PROP_GATEWAY); + } +} + +gboolean +nm_ip4_config_has_gateway (const NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + return priv->has_gateway; +} + guint32 nm_ip4_config_get_gateway (const NMIP4Config *config) { @@ -1153,6 +1242,14 @@ nm_ip4_config_get_gateway (const NMIP4Config *config) return priv->gateway; } +gint64 +nm_ip4_config_get_route_metric (const NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + return priv->route_metric; +} + /******************************************************************/ void @@ -1744,6 +1841,24 @@ nm_ip4_config_get_mtu_source (const NMIP4Config *config) /******************************************************************/ +void +nm_ip4_config_set_metered (NMIP4Config *config, gboolean metered) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + priv->metered = !!metered; +} + +gboolean +nm_ip4_config_get_metered (const NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + return priv->metered; +} + +/******************************************************************/ + static inline void hash_u32 (GChecksum *sum, guint32 n) { @@ -1760,6 +1875,7 @@ nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only g_return_if_fail (sum); if (!dns_only) { + hash_u32 (sum, nm_ip4_config_has_gateway (config)); hash_u32 (sum, nm_ip4_config_get_gateway (config)); for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++) { @@ -1856,6 +1972,7 @@ nm_ip4_config_init (NMIP4Config *config) priv->searches = g_ptr_array_new_with_free_func (g_free); priv->nis = g_array_new (FALSE, TRUE, sizeof (guint32)); priv->wins = g_array_new (FALSE, TRUE, sizeof (guint32)); + priv->route_metric = -1; } static void @@ -2020,7 +2137,7 @@ get_property (GObject *object, guint prop_id, } break; case PROP_GATEWAY: - if (priv->gateway) + if (priv->has_gateway) g_value_set_string (value, nm_utils_inet4_ntop (priv->gateway, NULL)); else g_value_set_string (value, NULL); diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 46367524..cb3038aa 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -69,7 +69,7 @@ void nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *settin NMSetting *nm_ip4_config_create_setting (const NMIP4Config *config); /* Utility functions */ -void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src); +void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFlags merge_flags); void nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src); void nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src); gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes); @@ -80,7 +80,10 @@ void nm_ip4_config_dump (const NMIP4Config *config, const char *detail); void nm_ip4_config_set_never_default (NMIP4Config *config, gboolean never_default); gboolean nm_ip4_config_get_never_default (const NMIP4Config *config); void nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway); +void nm_ip4_config_unset_gateway (NMIP4Config *config); +gboolean nm_ip4_config_has_gateway (const NMIP4Config *config); guint32 nm_ip4_config_get_gateway (const NMIP4Config *config); +gint64 nm_ip4_config_get_route_metric (const NMIP4Config *config); /* Addresses */ void nm_ip4_config_reset_addresses (NMIP4Config *config); @@ -146,6 +149,10 @@ void nm_ip4_config_set_mtu (NMIP4Config *config, guint32 mtu, NMIPConfigSource s guint32 nm_ip4_config_get_mtu (const NMIP4Config *config); NMIPConfigSource nm_ip4_config_get_mtu_source (const NMIP4Config *config); +/* Metered */ +void nm_ip4_config_set_metered (NMIP4Config *config, gboolean metered); +gboolean nm_ip4_config_get_metered (const NMIP4Config *config); + void nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only); gboolean nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 48aeb64a..9647268d 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -34,6 +34,7 @@ #include "nm-ip6-config-glue.h" #include "nm-route-manager.h" #include "NetworkManagerUtils.h" +#include "nm-macros-internal.h" G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, G_TYPE_OBJECT) @@ -50,6 +51,7 @@ typedef struct { GPtrArray *domains; GPtrArray *searches; guint32 mss; + gint64 route_metric; } NMIP6ConfigPrivate; @@ -329,6 +331,10 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co i++; } + /* we detect the route metric based on the default route. All non-default + * routes have their route metrics explicitly set. */ + priv->route_metric = has_gateway ? (gint64) lowest_metric : (gint64) -1; + /* If there is a host route to the gateway, ignore that route. It is * automatically added by NetworkManager when needed. */ @@ -408,6 +414,7 @@ nm_ip6_config_commit (const NMIP6Config *config, int ifindex, gboolean routes_fu void nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, guint32 default_route_metric) { + NMIP6ConfigPrivate *priv; guint naddresses, nroutes, nnameservers, nsearches; const char *gateway_str; int i; @@ -417,6 +424,8 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting)); + priv = NM_IP6_CONFIG_GET_PRIVATE (config); + naddresses = nm_setting_ip_config_get_num_addresses (setting); nroutes = nm_setting_ip_config_get_num_routes (setting); nnameservers = nm_setting_ip_config_get_num_dns (setting); @@ -437,6 +446,9 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu nm_ip6_config_set_gateway (config, &gateway); } + if (priv->route_metric == -1) + priv->route_metric = nm_setting_ip_config_get_route_metric (setting); + /* Addresses */ for (i = 0; i < naddresses; i++) { NMIPAddress *s_addr = nm_setting_ip_config_get_address (setting, i); @@ -500,6 +512,7 @@ nm_ip6_config_create_setting (const NMIP6Config *config) guint naddresses, nroutes, nnameservers, nsearches; const char *method = NULL; int i; + gint64 route_metric; s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new ()); @@ -515,6 +528,7 @@ nm_ip6_config_create_setting (const NMIP6Config *config) nroutes = nm_ip6_config_get_num_routes (config); nnameservers = nm_ip6_config_get_num_nameservers (config); nsearches = nm_ip6_config_get_num_searches (config); + route_metric = nm_ip6_config_get_route_metric (config); /* Addresses */ for (i = 0; i < naddresses; i++) { @@ -554,7 +568,11 @@ nm_ip6_config_create_setting (const NMIP6Config *config) /* Use 'ignore' if the method wasn't previously set */ if (!method) method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - g_object_set (s_ip6, NM_SETTING_IP_CONFIG_METHOD, method, NULL); + + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_METHOD, method, + NM_SETTING_IP_CONFIG_ROUTE_METRIC, (gint64) route_metric, + NULL); /* Routes */ for (i = 0; i < nroutes; i++) { @@ -599,13 +617,17 @@ nm_ip6_config_create_setting (const NMIP6Config *config) /******************************************************************/ void -nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src) +nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFlags merge_flags) { + NMIP6ConfigPrivate *dst_priv, *src_priv; guint32 i; g_return_if_fail (src != NULL); g_return_if_fail (dst != NULL); + dst_priv = NM_IP6_CONFIG_GET_PRIVATE (dst); + src_priv = NM_IP6_CONFIG_GET_PRIVATE (src); + g_object_freeze_notify (G_OBJECT (dst)); /* addresses */ @@ -621,16 +643,27 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src) nm_ip6_config_set_gateway (dst, nm_ip6_config_get_gateway (src)); /* routes */ - for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) - nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i)); + if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) { + for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) + nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i)); + } + + if (dst_priv->route_metric == -1) + dst_priv->route_metric = src_priv->route_metric; + else if (src_priv->route_metric != -1) + dst_priv->route_metric = MIN (dst_priv->route_metric, src_priv->route_metric); /* domains */ - for (i = 0; i < nm_ip6_config_get_num_domains (src); i++) - nm_ip6_config_add_domain (dst, nm_ip6_config_get_domain (src, i)); + if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) { + for (i = 0; i < nm_ip6_config_get_num_domains (src); i++) + nm_ip6_config_add_domain (dst, nm_ip6_config_get_domain (src, i)); + } /* dns searches */ - for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) - nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i)); + if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) { + for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) + nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i)); + } if (nm_ip6_config_get_mss (src)) nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src)); @@ -776,6 +809,8 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) if (!nm_ip6_config_get_num_addresses (dst)) nm_ip6_config_set_gateway (dst, NULL); + /* ignore route_metric */ + /* routes */ for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) { idx = _routes_get_index (dst, nm_ip6_config_get_route (src, i)); @@ -824,6 +859,7 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src) i++; } + /* ignore route_metric */ /* ignore nameservers */ /* default gateway */ @@ -902,6 +938,11 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev has_relevant_changes = TRUE; } + if (src_priv->route_metric != dst_priv->route_metric) { + dst_priv->route_metric = src_priv->route_metric; + has_minor_changes = TRUE; + } + /* addresses */ num = nm_ip6_config_get_num_addresses (src); are_equal = num == nm_ip6_config_get_num_addresses (dst); @@ -1112,6 +1153,14 @@ nm_ip6_config_get_gateway (const NMIP6Config *config) return IN6_IS_ADDR_UNSPECIFIED (&priv->gateway) ? NULL : &priv->gateway; } +gint64 +nm_ip6_config_get_route_metric (const NMIP6Config *config) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + return priv->route_metric; +} + /******************************************************************/ void @@ -1672,6 +1721,7 @@ nm_ip6_config_init (NMIP6Config *config) priv->nameservers = g_array_new (FALSE, TRUE, sizeof (struct in6_addr)); priv->domains = g_ptr_array_new_with_free_func (g_free); priv->searches = g_ptr_array_new_with_free_func (g_free); + priv->route_metric = -1; } static void diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 66f15888..279f89a7 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -69,7 +69,7 @@ void nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *settin NMSetting *nm_ip6_config_create_setting (const NMIP6Config *config); /* Utility functions */ -void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src); +void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFlags merge_flags); void nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src); void nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src); gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes); @@ -81,6 +81,7 @@ void nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_defaul gboolean nm_ip6_config_get_never_default (const NMIP6Config *config); void nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *); const struct in6_addr *nm_ip6_config_get_gateway (const NMIP6Config *config); +gint64 nm_ip6_config_get_route_metric (const NMIP6Config *config); /* Addresses */ void nm_ip6_config_reset_addresses (NMIP6Config *config); diff --git a/src/nm-logging.h b/src/nm-logging.h index 82a4e71f..40218062 100644 --- a/src/nm-logging.h +++ b/src/nm-logging.h @@ -167,4 +167,35 @@ gboolean nm_logging_setup (const char *level, void nm_logging_syslog_openlog (gboolean debug); void nm_logging_syslog_closelog (void); +/*****************************************************************************/ + +/* This is the default definition of _NMLOG_ENABLED(). Special implementations + * might want to undef this and redefine it. */ +#define _NMLOG_ENABLED(level) ( nm_logging_enabled ((level), (_NMLOG_DOMAIN)) ) + +#define _LOGt(...) _NMLOG (LOGL_TRACE, __VA_ARGS__) +#define _LOGD(...) _NMLOG (LOGL_DEBUG, __VA_ARGS__) +#define _LOGI(...) _NMLOG (LOGL_INFO , __VA_ARGS__) +#define _LOGW(...) _NMLOG (LOGL_WARN , __VA_ARGS__) +#define _LOGE(...) _NMLOG (LOGL_ERR , __VA_ARGS__) + +#define _LOGt_ENABLED(...) _NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__) +#define _LOGD_ENABLED(...) _NMLOG_ENABLED (LOGL_DEBUG, ##__VA_ARGS__) +#define _LOGI_ENABLED(...) _NMLOG_ENABLED (LOGL_INFO , ##__VA_ARGS__) +#define _LOGW_ENABLED(...) _NMLOG_ENABLED (LOGL_WARN , ##__VA_ARGS__) +#define _LOGE_ENABLED(...) _NMLOG_ENABLED (LOGL_ERR , ##__VA_ARGS__) + +/* _LOGt() and _LOGT() both log with level TRACE, but the latter is disabled by default, + * unless building with --with-more-logging. */ +#ifdef NM_MORE_LOGGING +#define _LOGT_ENABLED(...) _NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__) +#define _LOGT(...) _NMLOG (LOGL_TRACE, __VA_ARGS__) +#else +/* still call the logging macros to get compile time checks, but they will be optimize out. */ +#define _LOGT_ENABLED(...) ( FALSE && (_NMLOG_ENABLED (LOGL_TRACE, ##__VA_ARGS__)) ) +#define _LOGT(...) G_STMT_START { if (FALSE) { _NMLOG (LOGL_TRACE, __VA_ARGS__); } } G_STMT_END +#endif + +/*****************************************************************************/ + #endif /* __NETWORKMANAGER_LOGGING_H__ */ diff --git a/src/nm-manager-glue.h b/src/nm-manager-glue.h index d907f4d2..f7840c9f 100644 --- a/src/nm-manager-glue.h +++ b/src/nm-manager-glue.h @@ -411,6 +411,6 @@ const DBusGObjectInfo dbus_glib_nm_manager_object_info = { 1, 12, "org.freedesktop.NetworkManager\0GetDevices\0S\0devices\0O\0F\0N\0ao\0\0org.freedesktop.NetworkManager\0GetDeviceByIpIface\0S\0iface\0I\0s\0device\0O\0F\0N\0o\0\0org.freedesktop.NetworkManager\0ActivateConnection\0A\0connection\0I\0o\0device\0I\0o\0specific_object\0I\0o\0active_connection\0O\0F\0N\0o\0\0org.freedesktop.NetworkManager\0AddAndActivateConnection\0A\0connection\0I\0a{sa{sv}}\0device\0I\0o\0specific_object\0I\0o\0path\0O\0F\0N\0o\0active_connection\0O\0F\0N\0o\0\0org.freedesktop.NetworkManager\0DeactivateConnection\0A\0active_connection\0I\0o\0\0org.freedesktop.NetworkManager\0Sleep\0A\0sleep\0I\0b\0\0org.freedesktop.NetworkManager\0Enable\0A\0enable\0I\0b\0\0org.freedesktop.NetworkManager\0GetPermissions\0A\0permissions\0O\0F\0N\0a{ss}\0\0org.freedesktop.NetworkManager\0SetLogging\0A\0level\0I\0s\0domains\0I\0s\0\0org.freedesktop.NetworkManager\0GetLogging\0S\0level\0O\0F\0N\0s\0domains\0O\0F\0N\0s\0\0org.freedesktop.NetworkManager\0CheckConnectivity\0A\0connectivity\0O\0F\0N\0u\0\0org.freedesktop.NetworkManager\0state\0S\0state\0O\0F\0N\0u\0\0\0", "org.freedesktop.NetworkManager\0CheckPermissions\0org.freedesktop.NetworkManager\0StateChanged\0org.freedesktop.NetworkManager\0PropertiesChanged\0org.freedesktop.NetworkManager\0DeviceAdded\0org.freedesktop.NetworkManager\0DeviceRemoved\0\0", -"org.freedesktop.NetworkManager\0Devices\0devices\0read\0org.freedesktop.NetworkManager\0NetworkingEnabled\0networking_enabled\0read\0org.freedesktop.NetworkManager\0WirelessEnabled\0wireless_enabled\0readwrite\0org.freedesktop.NetworkManager\0WirelessHardwareEnabled\0wireless_hardware_enabled\0read\0org.freedesktop.NetworkManager\0WwanEnabled\0wwan_enabled\0readwrite\0org.freedesktop.NetworkManager\0WwanHardwareEnabled\0wwan_hardware_enabled\0read\0org.freedesktop.NetworkManager\0WimaxEnabled\0wimax_enabled\0readwrite\0org.freedesktop.NetworkManager\0WimaxHardwareEnabled\0wimax_hardware_enabled\0read\0org.freedesktop.NetworkManager\0ActiveConnections\0active_connections\0read\0org.freedesktop.NetworkManager\0PrimaryConnection\0primary_connection\0read\0org.freedesktop.NetworkManager\0PrimaryConnectionType\0primary_connection_type\0read\0org.freedesktop.NetworkManager\0ActivatingConnection\0activating_connection\0read\0org.freedesktop.NetworkManager\0Startup\0startup\0read\0org.freedesktop.NetworkManager\0Version\0version\0read\0org.freedesktop.NetworkManager\0State\0state\0read\0org.freedesktop.NetworkManager\0Connectivity\0connectivity\0read\0\0" +"org.freedesktop.NetworkManager\0Devices\0devices\0read\0org.freedesktop.NetworkManager\0NetworkingEnabled\0networking_enabled\0read\0org.freedesktop.NetworkManager\0WirelessEnabled\0wireless_enabled\0readwrite\0org.freedesktop.NetworkManager\0WirelessHardwareEnabled\0wireless_hardware_enabled\0read\0org.freedesktop.NetworkManager\0WwanEnabled\0wwan_enabled\0readwrite\0org.freedesktop.NetworkManager\0WwanHardwareEnabled\0wwan_hardware_enabled\0read\0org.freedesktop.NetworkManager\0WimaxEnabled\0wimax_enabled\0readwrite\0org.freedesktop.NetworkManager\0WimaxHardwareEnabled\0wimax_hardware_enabled\0read\0org.freedesktop.NetworkManager\0ActiveConnections\0active_connections\0read\0org.freedesktop.NetworkManager\0PrimaryConnection\0primary_connection\0read\0org.freedesktop.NetworkManager\0PrimaryConnectionType\0primary_connection_type\0read\0org.freedesktop.NetworkManager\0Metered\0metered\0read\0org.freedesktop.NetworkManager\0ActivatingConnection\0activating_connection\0read\0org.freedesktop.NetworkManager\0Startup\0startup\0read\0org.freedesktop.NetworkManager\0Version\0version\0read\0org.freedesktop.NetworkManager\0State\0state\0read\0org.freedesktop.NetworkManager\0Connectivity\0connectivity\0read\0\0" }; diff --git a/src/nm-manager.c b/src/nm-manager.c index 080cdb8b..34ec0819 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -161,6 +161,7 @@ typedef struct { guint ac_cleanup_id; NMActiveConnection *primary_connection; NMActiveConnection *activating_connection; + NMMetered metered; GSList *devices; NMState state; @@ -170,7 +171,6 @@ typedef struct { NMPolicy *policy; NMDBusManager *dbus_mgr; - gboolean prop_filter_added; NMRfkillManager *rfkill_mgr; NMSettings *settings; @@ -194,6 +194,7 @@ typedef struct { guint timestamp_update_id; gboolean startup; + gboolean devices_inited; } NMManagerPrivate; #define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate)) @@ -233,6 +234,7 @@ enum { PROP_PRIMARY_CONNECTION_TYPE, PROP_ACTIVATING_CONNECTION, PROP_DEVICES, + PROP_METERED, /* Not exported */ PROP_HOSTNAME, @@ -658,6 +660,30 @@ find_best_device_state (NMManager *manager) } static void +nm_manager_update_metered (NMManager *manager) +{ + NMManagerPrivate *priv; + NMDevice *device; + NMMetered value = NM_METERED_UNKNOWN; + + g_return_if_fail (NM_IS_MANAGER (manager)); + priv = NM_MANAGER_GET_PRIVATE (manager); + + if (priv->primary_connection) { + device = nm_active_connection_get_device (priv->primary_connection); + if (device) + value = nm_device_get_metered (device); + } + + if (value != priv->metered) { + priv->metered = value; + nm_log_dbg (LOGD_CORE, "New manager metered value: %d", + (int) priv->metered); + g_object_notify (G_OBJECT (manager), NM_MANAGER_METERED); + } +} + +static void nm_manager_update_state (NMManager *manager) { NMManagerPrivate *priv; @@ -718,6 +744,9 @@ check_if_startup_complete (NMManager *self) if (!priv->startup) return; + if (!priv->devices_inited) + return; + if (!nm_settings_get_startup_complete (priv->settings)) { nm_log_dbg (LOGD_CORE, "check_if_startup_complete returns FALSE because of NMSettings"); return; @@ -1159,18 +1188,26 @@ system_hostname_changed_cb (NMSettings *settings, char *hostname; hostname = nm_settings_get_hostname (priv->settings); + + /* nm_settings_get_hostname() does not return an empty hostname. */ + nm_assert (!hostname || *hostname); + if (!hostname && !priv->hostname) return; - if (hostname && priv->hostname && !strcmp (hostname, priv->hostname)) + if (hostname && priv->hostname && !strcmp (hostname, priv->hostname)) { + g_free (hostname); return; + } + + /* realloc, to free possibly trailing data after NUL. */ + if (hostname) + hostname = g_realloc (hostname, strlen (hostname) + 1); g_free (priv->hostname); - priv->hostname = (hostname && strlen (hostname)) ? g_strdup (hostname) : NULL; + priv->hostname = hostname; g_object_notify (G_OBJECT (self), NM_MANAGER_HOSTNAME); nm_dhcp_manager_set_default_hostname (nm_dhcp_manager_get (), priv->hostname); - - g_free (hostname); } /*******************************************************************/ @@ -4173,6 +4210,8 @@ nm_manager_start (NMManager *self) */ system_create_virtual_devices (self); + priv->devices_inited = TRUE; + check_if_startup_complete (self); } @@ -4260,6 +4299,14 @@ firmware_dir_changed (GFileMonitor *monitor, } static void +connection_metered_changed (GObject *object, + NMMetered metered, + gpointer user_data) +{ + nm_manager_update_metered (NM_MANAGER (user_data)); +} + +static void policy_default_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data) { NMManager *self = NM_MANAGER (user_data); @@ -4281,11 +4328,23 @@ policy_default_device_changed (GObject *object, GParamSpec *pspec, gpointer user ac = NULL; if (ac != priv->primary_connection) { - g_clear_object (&priv->primary_connection); + if (priv->primary_connection) { + g_signal_handlers_disconnect_by_func (priv->primary_connection, + G_CALLBACK (connection_metered_changed), + self); + g_clear_object (&priv->primary_connection); + } + priv->primary_connection = ac ? g_object_ref (ac) : NULL; + + if (priv->primary_connection) { + g_signal_connect (priv->primary_connection, NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED, + G_CALLBACK (connection_metered_changed), self); + } nm_log_dbg (LOGD_CORE, "PrimaryConnection now %s", ac ? nm_active_connection_get_id (ac) : "(none)"); g_object_notify (G_OBJECT (self), NM_MANAGER_PRIMARY_CONNECTION); g_object_notify (G_OBJECT (self), NM_MANAGER_PRIMARY_CONNECTION_TYPE); + nm_manager_update_metered (self); } } @@ -4625,17 +4684,13 @@ dbus_connection_changed_cb (NMDBusManager *dbus_mgr, gpointer user_data) { NMManager *self = NM_MANAGER (user_data); - gboolean success = FALSE; + gboolean success; if (dbus_connection) { - /* Register property filter on new connection; there's no reason this - * should fail except out-of-memory or program error; if it does fail - * then there's no Manager property access control, which is bad. - */ + /* Only fails on ENOMEM */ success = dbus_connection_add_filter (dbus_connection, prop_filter, self, NULL); g_assert (success); } - NM_MANAGER_GET_PRIVATE (self)->prop_filter_added = success; } /**********************************************************************/ @@ -4663,11 +4718,9 @@ nm_manager_new (NMSettings *settings, gboolean initial_net_enabled, gboolean initial_wifi_enabled, gboolean initial_wwan_enabled, - gboolean initial_wimax_enabled, - GError **error) + gboolean initial_wimax_enabled) { NMManagerPrivate *priv; - DBusGConnection *bus; DBusConnection *dbus_connection; NMConfigData *config_data; @@ -4680,16 +4733,14 @@ nm_manager_new (NMSettings *settings, priv = NM_MANAGER_GET_PRIVATE (singleton); - bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - if (!bus) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, - "Failed to initialize D-Bus connection"); - g_object_unref (singleton); - return NULL; - } + dbus_connection = nm_dbus_manager_get_dbus_connection (priv->dbus_mgr); + if (dbus_connection) { + gboolean success; - dbus_connection = dbus_g_connection_get_connection (bus); - g_assert (dbus_connection); + /* Only fails on ENOMEM */ + success = dbus_connection_add_filter (dbus_connection, prop_filter, singleton, NULL); + g_assert (success); + } priv->policy = nm_policy_new (singleton, settings); g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP4_DEVICE, @@ -4714,14 +4765,6 @@ nm_manager_new (NMSettings *settings, g_signal_connect (priv->connectivity, "notify::" NM_CONNECTIVITY_STATE, G_CALLBACK (connectivity_changed), singleton); - if (!dbus_connection_add_filter (dbus_connection, prop_filter, singleton, NULL)) { - g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, - "Failed to register DBus connection filter"); - g_object_unref (singleton); - return NULL; - } - priv->prop_filter_added = TRUE; - priv->settings = g_object_ref (settings); g_signal_connect (priv->settings, "notify::" NM_SETTINGS_STARTUP_COMPLETE, G_CALLBACK (settings_startup_complete_changed), singleton); @@ -4879,6 +4922,8 @@ nm_manager_init (NMManager *manager) /* Update timestamps in active connections */ priv->timestamp_update_id = g_timeout_add_seconds (300, (GSourceFunc) periodic_update_active_connection_timestamps, manager); + + priv->metered = NM_METERED_UNKNOWN; } static void @@ -4963,6 +5008,9 @@ get_property (GObject *object, guint prop_id, } g_value_take_boxed (value, array); break; + case PROP_METERED: + g_value_set_uint (value, priv->metered); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -5013,7 +5061,6 @@ dispose (GObject *object) { NMManager *manager = NM_MANAGER (object); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - DBusGConnection *bus; DBusConnection *dbus_connection; g_slist_free_full (priv->auth_chains, (GDestroyNotify) nm_auth_chain_unref); @@ -5059,14 +5106,9 @@ dispose (GObject *object) /* Unregister property filter */ if (priv->dbus_mgr) { - bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - if (bus) { - dbus_connection = dbus_g_connection_get_connection (bus); - if (dbus_connection && priv->prop_filter_added) { - dbus_connection_remove_filter (dbus_connection, prop_filter, manager); - priv->prop_filter_added = FALSE; - } - } + dbus_connection = nm_dbus_manager_get_dbus_connection (priv->dbus_mgr); + if (dbus_connection) + dbus_connection_remove_filter (dbus_connection, prop_filter, manager); g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, manager); priv->dbus_mgr = NULL; } @@ -5238,6 +5280,20 @@ nm_manager_class_init (NMManagerClass *manager_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * NMManager:metered: + * + * Whether the connectivity is metered. + * + * Since: 1.0.6 + **/ + g_object_class_install_property + (object_class, PROP_METERED, + g_param_spec_uint (NM_MANAGER_METERED, "", "", + 0, G_MAXUINT32, NM_METERED_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + /* signals */ signals[DEVICE_ADDED] = g_signal_new ("device-added", diff --git a/src/nm-manager.h b/src/nm-manager.h index 3b00e805..711bcce8 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -51,6 +51,7 @@ #define NM_MANAGER_PRIMARY_CONNECTION_TYPE "primary-connection-type" #define NM_MANAGER_ACTIVATING_CONNECTION "activating-connection" #define NM_MANAGER_DEVICES "devices" +#define NM_MANAGER_METERED "metered" /* Not exported */ #define NM_MANAGER_HOSTNAME "hostname" @@ -83,8 +84,7 @@ NMManager * nm_manager_new (NMSettings *settings, gboolean initial_net_enabled, gboolean initial_wifi_enabled, gboolean initial_wwan_enabled, - gboolean initial_wimax_enabled, - GError **error); + gboolean initial_wimax_enabled); NMManager * nm_manager_get (void); diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c index 5ee6c865..b392fc17 100644 --- a/src/nm-route-manager.c +++ b/src/nm-route-manager.c @@ -18,10 +18,10 @@ * Copyright (C) 2015 Red Hat, Inc. */ -#include <string.h> - #include "config.h" +#include <string.h> + #include "nm-route-manager.h" #include "nm-platform.h" #include "nmp-object.h" @@ -112,9 +112,17 @@ static const VTableIP vtable_v4, vtable_v6; /*********************************************************************************************/ -#define _LOG_PREFIX_NAME "route-mgr" - -#define _LOG(level, addr_family, ...) \ +#define _NMLOG_PREFIX_NAME "route-mgr" +#undef _NMLOG_ENABLED +#define _NMLOG_ENABLED(level, addr_family) \ + ({ \ + const int __addr_family = (addr_family); \ + const NMLogLevel __level = (level); \ + const NMLogDomain __domain = __addr_family == AF_INET ? LOGD_IP4 : (__addr_family == AF_INET6 ? LOGD_IP6 : LOGD_IP); \ + \ + nm_logging_enabled (__level, __domain); \ + }) +#define _NMLOG(level, addr_family, ...) \ G_STMT_START { \ const int __addr_family = (addr_family); \ const NMLogLevel __level = (level); \ @@ -122,38 +130,17 @@ static const VTableIP vtable_v4, vtable_v6; \ if (nm_logging_enabled (__level, __domain)) { \ char __ch = __addr_family == AF_INET ? '4' : (__addr_family == AF_INET6 ? '6' : '-'); \ - char __prefix[30] = _LOG_PREFIX_NAME; \ + char __prefix[30] = _NMLOG_PREFIX_NAME; \ \ if ((self) != singleton_instance) \ - g_snprintf (__prefix, sizeof (__prefix), "%s%c[%p]", _LOG_PREFIX_NAME, __ch, (self)); \ + g_snprintf (__prefix, sizeof (__prefix), "%s%c[%p]", _NMLOG_PREFIX_NAME, __ch, (self)); \ else \ - __prefix[STRLEN (_LOG_PREFIX_NAME)] = __ch; \ + __prefix[STRLEN (_NMLOG_PREFIX_NAME)] = __ch; \ _nm_log ((level), (__domain), 0, \ "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ __prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ } \ } G_STMT_END -#define _LOG_LEVEL_ENABLED(level, addr_family) \ - ({ \ - const int __addr_family = (addr_family); \ - const NMLogLevel __level = (level); \ - const NMLogDomain __domain = __addr_family == AF_INET ? LOGD_IP4 : (__addr_family == AF_INET6 ? LOGD_IP6 : LOGD_IP); \ - \ - nm_logging_enabled (__level, __domain); \ - }) - -#ifdef NM_MORE_LOGGING -#define _LOGT_ENABLED(addr_family) _LOG_LEVEL_ENABLED (LOGL_TRACE, addr_family) -#define _LOGT(addr_family, ...) _LOG (LOGL_TRACE, addr_family, __VA_ARGS__) -#else -#define _LOGT_ENABLED(addr_family) (FALSE && _LOG_LEVEL_ENABLED (LOGL_TRACE, addr_family)) -#define _LOGT(addr_family, ...) G_STMT_START { if (FALSE) { _LOG (LOGL_TRACE, addr_family, __VA_ARGS__); } } G_STMT_END -#endif - -#define _LOGD(addr_family, ...) _LOG (LOGL_DEBUG, addr_family, __VA_ARGS__) -#define _LOGI(addr_family, ...) _LOG (LOGL_INFO , addr_family, __VA_ARGS__) -#define _LOGW(addr_family, ...) _LOG (LOGL_WARN , addr_family, __VA_ARGS__) -#define _LOGE(addr_family, ...) _LOG (LOGL_ERR , addr_family, __VA_ARGS__) /*********************************************************************************************/ diff --git a/src/nm-types.h b/src/nm-types.h index 1a002ac3..5806e15d 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -127,6 +127,12 @@ typedef enum { NMP_OBJECT_TYPE_MAX = __NMP_OBJECT_TYPE_LAST - 1, } NMPObjectType; +typedef enum { + NM_IP_CONFIG_MERGE_DEFAULT = 0, + NM_IP_CONFIG_MERGE_NO_ROUTES = (1LL << 0), + NM_IP_CONFIG_MERGE_NO_DNS = (1LL << 1), +} NMIPConfigMergeFlags; + /* settings */ typedef struct _NMAgentManager NMAgentManager; typedef struct _NMSecretAgent NMSecretAgent; diff --git a/src/org.freedesktop.NetworkManager.conf b/src/org.freedesktop.NetworkManager.conf index 0f1019b9..afbcc720 100644 --- a/src/org.freedesktop.NetworkManager.conf +++ b/src/org.freedesktop.NetworkManager.conf @@ -25,6 +25,8 @@ <allow send_destination="org.freedesktop.NetworkManager.vpnc"/> <allow send_destination="org.freedesktop.NetworkManager.ssh"/> <allow send_destination="org.freedesktop.NetworkManager.iodine"/> + <allow send_destination="org.freedesktop.NetworkManager.l2tp"/> + <allow send_destination="org.freedesktop.NetworkManager.libreswan"/> </policy> <policy context="default"> <deny own="org.freedesktop.NetworkManager"/> diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 80757f4e..cd0a4e07 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -67,8 +67,9 @@ /*********************************************************************************************/ -#define _LOG_DOMAIN LOGD_PLATFORM -#define _LOG_PREFIX_NAME "platform-linux" +#define _NMLOG_DOMAIN LOGD_PLATFORM +#define _NMLOG_PREFIX_NAME "platform-linux" +#define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, platform, __VA_ARGS__) #define _LOG(level, domain, self, ...) \ G_STMT_START { \ @@ -77,11 +78,11 @@ \ if (nm_logging_enabled (__level, __domain)) { \ char __prefix[32]; \ - const char *__p_prefix = _LOG_PREFIX_NAME; \ + const char *__p_prefix = _NMLOG_PREFIX_NAME; \ const void *const __self = (self); \ \ if (__self && __self != nm_platform_try_get ()) { \ - g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _LOG_PREFIX_NAME, __self); \ + g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ __p_prefix = __prefix; \ } \ _nm_log (__level, __domain, 0, \ @@ -89,25 +90,12 @@ __p_prefix _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ } \ } G_STMT_END -#define _LOG_LEVEL_ENABLED(level, domain) \ - ( nm_logging_enabled ((level), (domain)) ) -#ifdef NM_MORE_LOGGING -#define _LOGT_ENABLED() _LOG_LEVEL_ENABLED (LOGL_TRACE, _LOG_DOMAIN) -#define _LOGT(...) _LOG (LOGL_TRACE, _LOG_DOMAIN, platform, __VA_ARGS__) -#else -#define _LOGT_ENABLED() FALSE -#define _LOGT(...) G_STMT_START { if (FALSE) { _LOG (LOGL_TRACE, _LOG_DOMAIN, platform, __VA_ARGS__); } } G_STMT_END -#endif - -#define _LOGD(...) _LOG (LOGL_DEBUG, _LOG_DOMAIN, platform, __VA_ARGS__) -#define _LOGI(...) _LOG (LOGL_INFO , _LOG_DOMAIN, platform, __VA_ARGS__) -#define _LOGW(...) _LOG (LOGL_WARN , _LOG_DOMAIN, platform, __VA_ARGS__) -#define _LOGE(...) _LOG (LOGL_ERR , _LOG_DOMAIN, platform, __VA_ARGS__) - -#define debug(...) _LOG (LOGL_DEBUG, _LOG_DOMAIN, NULL, __VA_ARGS__) -#define warning(...) _LOG (LOGL_WARN , _LOG_DOMAIN, NULL, __VA_ARGS__) -#define error(...) _LOG (LOGL_ERR , _LOG_DOMAIN, NULL, __VA_ARGS__) +#define trace(...) _LOG (LOGL_TRACE, _NMLOG_DOMAIN, NULL, __VA_ARGS__) +#define debug(...) _LOG (LOGL_DEBUG, _NMLOG_DOMAIN, NULL, __VA_ARGS__) +#define info(...) _LOG (LOGL_INFO, _NMLOG_DOMAIN, NULL, __VA_ARGS__) +#define warning(...) _LOG (LOGL_WARN , _NMLOG_DOMAIN, NULL, __VA_ARGS__) +#define error(...) _LOG (LOGL_ERR , _NMLOG_DOMAIN, NULL, __VA_ARGS__) /****************************************************************** * Forward declarations and enums @@ -150,8 +138,10 @@ static NMPCacheOpsType cache_remove_netlink (NMPlatform *platform, const NMPObje struct libnl_vtable { void *handle; + void *handle_route; int (*f_nl_has_capability) (int capability); + int (*f_rtnl_link_get_link_netnsid) (const struct rtnl_link *link, gint32 *out_link_netnsid); }; static int @@ -160,24 +150,25 @@ _nl_f_nl_has_capability (int capability) return FALSE; } -static struct libnl_vtable * +static const struct libnl_vtable * _nl_get_vtable (void) { static struct libnl_vtable vtable; if (G_UNLIKELY (!vtable.f_nl_has_capability)) { - void *handle; - - handle = dlopen ("libnl-3.so.200", RTLD_LAZY | RTLD_NOLOAD); - if (handle) { - vtable.handle = handle; - vtable.f_nl_has_capability = dlsym (handle, "nl_has_capability"); + vtable.handle = dlopen ("libnl-3.so.200", RTLD_LAZY | RTLD_NOLOAD); + if (vtable.handle) { + vtable.f_nl_has_capability = dlsym (vtable.handle, "nl_has_capability"); + } + vtable.handle_route = dlopen ("libnl-route-3.so.200", RTLD_LAZY | RTLD_NOLOAD); + if (vtable.handle_route) { + vtable.f_rtnl_link_get_link_netnsid = dlsym (vtable.handle_route, "rtnl_link_get_link_netnsid"); } if (!vtable.f_nl_has_capability) vtable.f_nl_has_capability = &_nl_f_nl_has_capability; - g_return_val_if_fail (vtable.handle, &vtable); + trace ("libnl: rtnl_link_get_link_netnsid() %s", vtable.f_rtnl_link_get_link_netnsid ? "supported" : "not supported"); } return &vtable; @@ -189,6 +180,26 @@ _nl_has_capability (int capability) return (_nl_get_vtable ()->f_nl_has_capability) (capability); } +static int +_rtnl_link_get_link_netnsid (const struct rtnl_link *link, gint32 *out_link_netnsid) +{ + const struct libnl_vtable *vtable; + + g_return_val_if_fail (link, -NLE_INVAL); + g_return_val_if_fail (out_link_netnsid, -NLE_INVAL); + + vtable = _nl_get_vtable (); + return vtable->f_rtnl_link_get_link_netnsid + ? vtable->f_rtnl_link_get_link_netnsid (link, out_link_netnsid) + : -NLE_OPNOTSUPP; +} + +gboolean +nm_platform_check_support_libnl_link_netnsid (void) +{ + return !!(_nl_get_vtable ()->f_rtnl_link_get_link_netnsid); +} + /* Automatic deallocation of local variables */ #define auto_nl_object __attribute__((cleanup(_nl_auto_nl_object))) static void @@ -994,6 +1005,7 @@ _nmp_vt_cmd_plobj_init_from_nl_link (NMPlatform *platform, NMPlatformObject *_ob gboolean completed_from_cache_val = FALSE; gboolean *completed_from_cache = complete_from_cache ? &completed_from_cache_val : NULL; const NMPObject *link_cached = NULL; + int parent; nm_assert (memcmp (obj, ((char [sizeof (NMPObjectLink)]) { 0 }), sizeof (NMPObjectLink)) == 0); @@ -1013,7 +1025,15 @@ _nmp_vt_cmd_plobj_init_from_nl_link (NMPlatform *platform, NMPlatformObject *_ob obj->flags = rtnl_link_get_flags (nlo); obj->connected = NM_FLAGS_HAS (obj->flags, IFF_LOWER_UP); obj->master = rtnl_link_get_master (nlo); - obj->parent = rtnl_link_get_link (nlo); + parent = rtnl_link_get_link (nlo); + if (parent > 0) { + gint32 link_netnsid; + + if (_rtnl_link_get_link_netnsid (nlo, &link_netnsid) == 0) + obj->parent = NM_PLATFORM_LINK_OTHER_NETNS; + else + obj->parent = parent; + } obj->mtu = rtnl_link_get_mtu (nlo); obj->arptype = rtnl_link_get_arptype (nlo); @@ -2306,11 +2326,25 @@ event_notification (struct nl_msg *msg, gpointer user_data) if (_support_user_ipv6ll_still_undecided() && msghdr->nlmsg_type == RTM_NEWLINK) _support_user_ipv6ll_detect ((struct rtnl_link *) nlo); - obj = nmp_object_from_nl (platform, nlo, FALSE, TRUE); + switch (msghdr->nlmsg_type) { + case RTM_DELADDR: + case RTM_DELLINK: + case RTM_DELROUTE: + /* The event notifies about a deleted object. We don't need to initialize all the + * fields of the nmp-object. Shortcut nmp_object_from_nl(). */ + obj = nmp_object_from_nl (platform, nlo, TRUE, TRUE); + _LOGD ("event-notification: %s, seq %u: %s", + _nl_nlmsg_type_to_str (msghdr->nlmsg_type, buf_nlmsg_type, sizeof (buf_nlmsg_type)), + msghdr->nlmsg_seq, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0)); + break; + default: + obj = nmp_object_from_nl (platform, nlo, FALSE, TRUE); + _LOGD ("event-notification: %s, seq %u: %s", + _nl_nlmsg_type_to_str (msghdr->nlmsg_type, buf_nlmsg_type, sizeof (buf_nlmsg_type)), + msghdr->nlmsg_seq, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); + break; + } - _LOGD ("event-notification: %s, seq %u: %s", - _nl_nlmsg_type_to_str (msghdr->nlmsg_type, buf_nlmsg_type, sizeof (buf_nlmsg_type)), - msghdr->nlmsg_seq, nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); if (obj) { auto_nmp_obj NMPObject *obj_cache = NULL; @@ -4549,7 +4583,7 @@ event_handler_read_netlink_one (NMPlatform *platform) debug ("Uncritical failure to retrieve incoming events: %s (%d)", nl_geterror (nle), nle); break; case -NLE_NOMEM: - warning ("Too many netlink events. Need to resynchronize platform cache"); + info ("Too many netlink events. Need to resynchronize platform cache"); /* Drain the event queue, we've lost events and are out of sync anyway and we'd * like to free up some space. We'll read in the status synchronously. */ _nl_sock_flush_data (priv->nlh_event); diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index d3c62bdd..b7f0947e 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -33,6 +33,7 @@ #include "nm-utils.h" #include "NetworkManagerUtils.h" #include "nm-logging.h" +#include "nm-setting-wired.h" /****************************************************************** @@ -48,8 +49,14 @@ ethtool_get (const char *name, gpointer edata) if (!name || !*name) return FALSE; + if (!nmp_utils_device_exists (name)) + return FALSE; + + /* nmp_utils_device_exists() already errors out if @name is invalid. */ + nm_assert (strlen (name) < IFNAMSIZ); + memset (&ifr, 0, sizeof (ifr)); - strncpy (ifr.ifr_name, name, IFNAMSIZ); + strcpy (ifr.ifr_name, name); ifr.ifr_data = edata; fd = socket (PF_INET, SOCK_DGRAM, 0); @@ -255,6 +262,43 @@ nmp_utils_ethtool_get_link_speed (const char *ifname, guint32 *out_speed) return TRUE; } +gboolean +nmp_utils_ethtool_set_wake_on_lan (const char *ifname, + NMSettingWiredWakeOnLan wol, + const char *wol_password) +{ + struct ethtool_wolinfo wol_info = { }; + + nm_log_dbg (LOGD_PLATFORM, "setting Wake-on-LAN options 0x%x, password '%s'", + (unsigned int) wol, wol_password); + + wol_info.cmd = ETHTOOL_SWOL; + wol_info.wolopts = 0; + + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY)) + wol_info.wolopts |= WAKE_PHY; + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST)) + wol_info.wolopts |= WAKE_UCAST; + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST)) + wol_info.wolopts |= WAKE_MCAST; + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST)) + wol_info.wolopts |= WAKE_BCAST; + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ARP)) + wol_info.wolopts |= WAKE_ARP; + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) + wol_info.wolopts |= WAKE_MAGIC; + + if (wol_password) { + if (!nm_utils_hwaddr_aton (wol_password, wol_info.sopass, ETH_ALEN)) { + nm_log_dbg (LOGD_PLATFORM, "couldn't parse Wake-on-LAN password '%s'", wol_password); + return FALSE; + } + wol_info.wolopts |= WAKE_MAGICSECURE; + } + + return ethtool_get (ifname, &wol_info); +} + /****************************************************************** * mii ******************************************************************/ @@ -270,6 +314,9 @@ nmp_utils_mii_supports_carrier_detect (const char *ifname) if (!ifname) return FALSE; + if (!nmp_utils_device_exists (ifname)) + return FALSE; + fd = socket (PF_INET, SOCK_DGRAM, 0); if (fd < 0) { nm_log_err (LOGD_PLATFORM, "mii: couldn't open control socket (%s)", ifname); @@ -433,4 +480,17 @@ nmp_utils_lifetime_get (guint32 timestamp, return TRUE; } +gboolean +nmp_utils_device_exists (const char *name) +{ +#define SYS_CLASS_NET "/sys/class/net/" + char sysdir[STRLEN (SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET; + if ( !name + || strlen (name) >= IFNAMSIZ + || !nm_utils_is_valid_path_component (name)) + g_return_val_if_reached (FALSE); + + strcpy (&sysdir[STRLEN (SYS_CLASS_NET)], name); + return g_file_test (sysdir, G_FILE_TEST_EXISTS); +} diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index 557de844..3769a8e1 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -26,6 +26,7 @@ #include <gudev/gudev.h> #include "nm-platform.h" +#include "nm-setting-wired.h" const char *nmp_utils_ethtool_get_driver (const char *ifname); @@ -33,6 +34,9 @@ gboolean nmp_utils_ethtool_supports_carrier_detect (const char *ifname); gboolean nmp_utils_ethtool_supports_vlans (const char *ifname); int nmp_utils_ethtool_get_peer_ifindex (const char *ifname); gboolean nmp_utils_ethtool_get_wake_on_lan (const char *ifname); +gboolean nmp_utils_ethtool_set_wake_on_lan (const char *ifname, NMSettingWiredWakeOnLan wol, + const char *wol_password); + gboolean nmp_utils_ethtool_get_link_speed (const char *ifname, guint32 *out_speed); gboolean nmp_utils_ethtool_get_driver_info (const char *ifname, @@ -63,4 +67,6 @@ gboolean nmp_utils_lifetime_get (guint32 timestamp, guint32 *out_lifetime, guint32 *out_preferred); +gboolean nmp_utils_device_exists (const char *name); + #endif /* __NM_PLATFORM_UTILS_H__ */ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index b6d87ff9..fcb5b061 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -43,43 +43,26 @@ G_STATIC_ASSERT (sizeof ( ((NMPlatformLink *) NULL)->addr.data ) == NM_UTILS_HWADDR_LEN_MAX); -#define _LOG_DOMAIN LOGD_PLATFORM -#define _LOG_PREFIX_NAME "platform" - -#define _LOG(level, domain, self, ...) \ +#define _NMLOG_DOMAIN LOGD_PLATFORM +#define _NMLOG_PREFIX_NAME "platform" +#define _NMLOG(level, ...) \ G_STMT_START { \ const NMLogLevel __level = (level); \ - const NMLogDomain __domain = (domain); \ \ - if (nm_logging_enabled (__level, __domain)) { \ + if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ char __prefix[32]; \ - const char *__p_prefix = _LOG_PREFIX_NAME; \ + const char *__p_prefix = _NMLOG_PREFIX_NAME; \ const void *const __self = (self); \ \ if (__self && __self != nm_platform_try_get ()) { \ - g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _LOG_PREFIX_NAME, __self); \ + g_snprintf (__prefix, sizeof (__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \ __p_prefix = __prefix; \ } \ - _nm_log (__level, __domain, 0, \ + _nm_log (__level, _NMLOG_DOMAIN, 0, \ "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ __p_prefix _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ } \ } G_STMT_END -#define _LOG_LEVEL_ENABLED(level, domain) \ - ( nm_logging_enabled ((level), (domain)) ) - -#ifdef NM_MORE_LOGGING -#define _LOGT_ENABLED() _LOG_LEVEL_ENABLED (LOGL_TRACE, _LOG_DOMAIN) -#define _LOGT(...) _LOG (LOGL_TRACE, _LOG_DOMAIN, self, __VA_ARGS__) -#else -#define _LOGT_ENABLED() FALSE -#define _LOGT(...) G_STMT_START { if (FALSE) { _LOG (LOGL_TRACE, _LOG_DOMAIN, self, __VA_ARGS__); } } G_STMT_END -#endif - -#define _LOGD(...) _LOG (LOGL_DEBUG, _LOG_DOMAIN, self, __VA_ARGS__) -#define _LOGI(...) _LOG (LOGL_INFO , _LOG_DOMAIN, self, __VA_ARGS__) -#define _LOGW(...) _LOG (LOGL_WARN , _LOG_DOMAIN, self, __VA_ARGS__) -#define _LOGE(...) _LOG (LOGL_ERR , _LOG_DOMAIN, self, __VA_ARGS__) #define NM_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_PLATFORM, NMPlatformPrivate)) @@ -464,9 +447,12 @@ nm_platform_link_get_all (NMPlatform *self) g_warn_if_fail (g_hash_table_contains (unseen, GINT_TO_POINTER (item->master))); } if (item->parent != 0) { - g_warn_if_fail (item->parent > 0); - g_warn_if_fail (item->parent != item->ifindex); - g_warn_if_fail (g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent))); + if (item->parent != NM_PLATFORM_LINK_OTHER_NETNS) { + g_warn_if_fail (item->parent > 0); + g_warn_if_fail (item->parent != item->ifindex); + g_warn_if_fail ( !nm_platform_check_support_libnl_link_netnsid () + || g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent))); + } } } #endif @@ -1873,7 +1859,7 @@ nm_platform_ip4_address_add (NMPlatform *self, g_return_val_if_fail (klass->ip4_address_add, FALSE); g_return_val_if_fail (!label || strlen (label) < sizeof (((NMPlatformIP4Address *) NULL)->label), FALSE); - if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + if (_LOGD_ENABLED ()) { NMPlatformIP4Address addr = { 0 }; addr.ifindex = ifindex; @@ -1909,7 +1895,7 @@ nm_platform_ip6_address_add (NMPlatform *self, g_return_val_if_fail (preferred <= lifetime, FALSE); g_return_val_if_fail (klass->ip6_address_add, FALSE); - if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + if (_LOGD_ENABLED ()) { NMPlatformIP6Address addr = { 0 }; addr.ifindex = ifindex; @@ -2190,7 +2176,7 @@ nm_platform_ip4_route_add (NMPlatform *self, g_return_val_if_fail (0 <= plen && plen <= 32, FALSE); g_return_val_if_fail (klass->ip4_route_add, FALSE); - if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + if (_LOGD_ENABLED ()) { NMPlatformIP4Route route = { 0 }; route.ifindex = ifindex; @@ -2218,7 +2204,7 @@ nm_platform_ip6_route_add (NMPlatform *self, g_return_val_if_fail (0 <= plen && plen <= 128, FALSE); g_return_val_if_fail (klass->ip6_route_add, FALSE); - if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) { + if (_LOGD_ENABLED ()) { NMPlatformIP6Route route = { 0 }; route.ifindex = ifindex; @@ -2372,8 +2358,10 @@ nm_platform_link_to_string (const NMPlatformLink *link) else master[0] = 0; - if (link->parent) - g_snprintf (parent, sizeof (master), "@%d", link->parent); + if (link->parent > 0) + g_snprintf (parent, sizeof (parent), "@%d", link->parent); + else if (link->parent == NM_PLATFORM_LINK_OTHER_NETNS) + g_strlcpy (parent, "@other-netns", sizeof (parent)); else parent[0] = 0; diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 4d254195..3219dd5a 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -87,6 +87,8 @@ typedef enum { _NM_PLATFORM_REASON_CACHE_CHECK_INTERNAL, } NMPlatformReason; +#define NM_PLATFORM_LINK_OTHER_NETNS (-1) + #define __NMPlatformObject_COMMON \ int ifindex; \ ; @@ -105,6 +107,10 @@ struct _NMPlatformLink { gboolean initialized; int master; + + /* rtnl_link_get_link(), IFLA_LINK. + * If IFLA_LINK_NETNSID indicates that the parent is in another namespace, + * this field be set to (negative) NM_PLATFORM_LINK_OTHER_NETNS. */ int parent; /* rtnl_link_get_arptype(), ifinfomsg.ifi_type. */ @@ -734,6 +740,7 @@ int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4R int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b); gboolean nm_platform_check_support_libnl_extended_ifa_flags (void); +gboolean nm_platform_check_support_libnl_link_netnsid (void); gboolean nm_platform_check_support_kernel_extended_ifa_flags (NMPlatform *self); gboolean nm_platform_check_support_user_ipv6ll (NMPlatform *self); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 51684b93..7fe2d7d3 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -18,10 +18,11 @@ * Copyright (C) 2015 Red Hat, Inc. */ -#include "nmp-object.h" +#include "config.h" #include <unistd.h> +#include "nmp-object.h" #include "nm-platform-utils.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" @@ -29,38 +30,21 @@ /*********************************************************************************************/ -#define _LOG_DOMAIN LOGD_PLATFORM - -#define _LOG(level, domain, obj, ...) \ +#define _NMLOG_DOMAIN LOGD_PLATFORM +#define _NMLOG(level, obj, ...) \ G_STMT_START { \ const NMLogLevel __level = (level); \ - const NMLogDomain __domain = (domain); \ \ - if (nm_logging_enabled (__level, __domain)) { \ + if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ const NMPObject *const __obj = (obj); \ \ - _nm_log (__level, __domain, 0, \ + _nm_log (__level, _NMLOG_DOMAIN, 0, \ "nmp-object[%p/%s]: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ __obj, \ (__obj ? NMP_OBJECT_GET_CLASS (__obj)->obj_type_name : "???") \ _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ } \ } G_STMT_END -#define _LOG_LEVEL_ENABLED(level, domain) \ - ( nm_logging_enabled ((level), (domain)) ) - -#ifdef NM_MORE_LOGGING -#define _LOGT_ENABLED() _LOG_LEVEL_ENABLED (LOGL_TRACE, _LOG_DOMAIN) -#define _LOGT(obj, ...) _LOG (LOGL_TRACE, _LOG_DOMAIN, obj, __VA_ARGS__) -#else -#define _LOGT_ENABLED() FALSE -#define _LOGT(obj, ...) G_STMT_START { if (FALSE) { _LOG (LOGL_TRACE, _LOG_DOMAIN, obj, __VA_ARGS__); } } G_STMT_END -#endif - -#define _LOGD(obj, ...) _LOG (LOGL_DEBUG, _LOG_DOMAIN, obj, __VA_ARGS__) -#define _LOGI(obj, ...) _LOG (LOGL_INFO , _LOG_DOMAIN, obj, __VA_ARGS__) -#define _LOGW(obj, ...) _LOG (LOGL_WARN , _LOG_DOMAIN, obj, __VA_ARGS__) -#define _LOGE(obj, ...) _LOG (LOGL_ERR , _LOG_DOMAIN, obj, __VA_ARGS__) /*********************************************************************************************/ diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index dc7b8397..ce371b75 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -231,10 +231,7 @@ test_slave (int master, int type, SignalData *master_changed) g_assert (nm_platform_link_release (NM_PLATFORM_GET, master, ifindex)); g_assert_cmpint (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex), ==, 0); accept_signals (link_changed, 1, 3); - if (link_type != NM_LINK_TYPE_TEAM) - accept_signals (master_changed, 1, 2); - else - accept_signals (master_changed, 1, 1); + accept_signals (master_changed, 1, 2); ensure_no_signal (master_changed); diff --git a/src/platform/wifi/wifi-utils-wext.c b/src/platform/wifi/wifi-utils-wext.c index 8428010a..470b73d1 100644 --- a/src/platform/wifi/wifi-utils-wext.c +++ b/src/platform/wifi/wifi-utils-wext.c @@ -34,6 +34,7 @@ #include "wifi-utils-wext.h" #include "nm-logging.h" #include "nm-utils.h" +#include "nm-platform-utils.h" /* Hacks necessary to #include wireless.h; yay for WEXT */ #ifndef __user @@ -670,6 +671,9 @@ wifi_wext_is_wifi (const char *iface) struct iwreq iwr; gboolean is_wifi = FALSE; + if (!nmp_utils_device_exists (iface)) + return FALSE; + fd = socket (PF_INET, SOCK_DGRAM, 0); if (fd >= 0) { strncpy (iwr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 0f67a216..da5384c0 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -38,32 +38,57 @@ #include "nm-properties-changed-signal.h" #include "nm-core-internal.h" #include "nm-glib-compat.h" +#include "gsystem-local-alloc.h" #define SETTINGS_TIMESTAMPS_FILE NMSTATEDIR "/timestamps" #define SETTINGS_SEEN_BSSIDS_FILE NMSTATEDIR "/seen-bssids" -static void impl_settings_connection_get_settings (NMSettingsConnection *connection, +#define _NMLOG_DOMAIN LOGD_SETTINGS +#define _NMLOG_PREFIX_NAME "settings-connection" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + const NMLogLevel __level = (level); \ + \ + if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \ + char __prefix[128]; \ + const char *__p_prefix = _NMLOG_PREFIX_NAME; \ + const void *const __self = (self); \ + \ + if (__self) { \ + const char *__uuid = nm_connection_get_uuid ((NMConnection *) __self); \ + \ + g_snprintf (__prefix, sizeof (__prefix), "%s[%p%s%s]", _NMLOG_PREFIX_NAME, __self, __uuid ? "," : "", __uuid ? __uuid : ""); \ + __p_prefix = __prefix; \ + } \ + _nm_log (__level, _NMLOG_DOMAIN, 0, \ + "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + __p_prefix _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } \ + } G_STMT_END + + +static void impl_settings_connection_get_settings (NMSettingsConnection *self, DBusGMethodInvocation *context); -static void impl_settings_connection_update (NMSettingsConnection *connection, +static void impl_settings_connection_update (NMSettingsConnection *self, GHashTable *new_settings, DBusGMethodInvocation *context); -static void impl_settings_connection_update_unsaved (NMSettingsConnection *connection, +static void impl_settings_connection_update_unsaved (NMSettingsConnection *self, GHashTable *new_settings, DBusGMethodInvocation *context); -static void impl_settings_connection_save (NMSettingsConnection *connection, +static void impl_settings_connection_save (NMSettingsConnection *self, DBusGMethodInvocation *context); -static void impl_settings_connection_delete (NMSettingsConnection *connection, +static void impl_settings_connection_delete (NMSettingsConnection *self, DBusGMethodInvocation *context); -static void impl_settings_connection_get_secrets (NMSettingsConnection *connection, +static void impl_settings_connection_get_secrets (NMSettingsConnection *self, const gchar *setting_name, DBusGMethodInvocation *context); -static void impl_settings_connection_clear_secrets (NMSettingsConnection *connection, +static void impl_settings_connection_clear_secrets (NMSettingsConnection *self, DBusGMethodInvocation *context); #include "nm-settings-connection-glue.h" @@ -146,7 +171,7 @@ typedef gboolean (*ForEachSecretFunc) (GHashTableIter *iter, gpointer user_data); static void -for_each_secret (NMConnection *connection, +for_each_secret (NMConnection *self, GHashTable *secrets, gboolean remove_non_secrets, ForEachSecretFunc callback, @@ -189,7 +214,7 @@ for_each_secret (NMConnection *connection, * from the connection data, since flags aren't secrets. What we're * iterating here is just the secrets, not a whole connection. */ - setting = nm_connection_get_setting_by_name (connection, setting_name); + setting = nm_connection_get_setting_by_name (self, setting_name); if (setting == NULL) continue; @@ -488,6 +513,9 @@ nm_settings_connection_replace_settings (NMSettingsConnection *self, nm_utils_log_connection_diff (new_connection, NM_CONNECTION (self), LOGL_DEBUG, LOGD_CORE, log_diff_name, "++ "); nm_connection_replace_settings_from_connection (NM_CONNECTION (self), new_connection); + + _LOGD ("replace settings from connection %p (%s)", new_connection, nm_connection_get_id (NM_CONNECTION (self))); + nm_settings_connection_set_flags (self, NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED | NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED, FALSE); @@ -526,7 +554,7 @@ nm_settings_connection_replace_settings (NMSettingsConnection *self, } static void -ignore_cb (NMSettingsConnection *connection, +ignore_cb (NMSettingsConnection *self, GError *error, gpointer user_data) { @@ -583,49 +611,49 @@ commit_changes (NMSettingsConnection *self, } void -nm_settings_connection_commit_changes (NMSettingsConnection *connection, +nm_settings_connection_commit_changes (NMSettingsConnection *self, NMSettingsConnectionCommitFunc callback, gpointer user_data) { - g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection)); + g_return_if_fail (NM_IS_SETTINGS_CONNECTION (self)); - if (NM_SETTINGS_CONNECTION_GET_CLASS (connection)->commit_changes) { - NM_SETTINGS_CONNECTION_GET_CLASS (connection)->commit_changes (connection, - callback ? callback : ignore_cb, - user_data); + if (NM_SETTINGS_CONNECTION_GET_CLASS (self)->commit_changes) { + NM_SETTINGS_CONNECTION_GET_CLASS (self)->commit_changes (self, + callback ? callback : ignore_cb, + user_data); } else { GError *error = g_error_new (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "%s: %s:%d commit_changes() unimplemented", __func__, __FILE__, __LINE__); if (callback) - callback (connection, error, user_data); + callback (self, error, user_data); g_error_free (error); } } void -nm_settings_connection_delete (NMSettingsConnection *connection, +nm_settings_connection_delete (NMSettingsConnection *self, NMSettingsConnectionDeleteFunc callback, gpointer user_data) { - g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection)); + g_return_if_fail (NM_IS_SETTINGS_CONNECTION (self)); - if (NM_SETTINGS_CONNECTION_GET_CLASS (connection)->delete) { - NM_SETTINGS_CONNECTION_GET_CLASS (connection)->delete (connection, - callback ? callback : ignore_cb, - user_data); + if (NM_SETTINGS_CONNECTION_GET_CLASS (self)->delete) { + NM_SETTINGS_CONNECTION_GET_CLASS (self)->delete (self, + callback ? callback : ignore_cb, + user_data); } else { GError *error = g_error_new (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "%s: %s:%d delete() unimplemented", __func__, __FILE__, __LINE__); if (callback) - callback (connection, error, user_data); + callback (self, error, user_data); g_error_free (error); } } static void -remove_entry_from_db (NMSettingsConnection *connection, const char* db_name) +remove_entry_from_db (NMSettingsConnection *self, const char* db_name) { GKeyFile *key_file; const char *db_file; @@ -644,7 +672,7 @@ remove_entry_from_db (NMSettingsConnection *connection, const char* db_name) gsize len; GError *error = NULL; - connection_uuid = nm_connection_get_uuid (NM_CONNECTION (connection)); + connection_uuid = nm_connection_get_uuid (NM_CONNECTION (self)); g_key_file_remove_key (key_file, db_name, connection_uuid, NULL); data = g_key_file_to_data (key_file, &len, &error); @@ -653,7 +681,7 @@ remove_entry_from_db (NMSettingsConnection *connection, const char* db_name) g_free (data); } if (error) { - nm_log_warn (LOGD_SETTINGS, "error writing %s file '%s': %s", db_name, db_file, error->message); + _LOGW ("error writing %s file '%s': %s", db_name, db_file, error->message); g_error_free (error); } } @@ -661,39 +689,39 @@ remove_entry_from_db (NMSettingsConnection *connection, const char* db_name) } static void -do_delete (NMSettingsConnection *connection, +do_delete (NMSettingsConnection *self, NMSettingsConnectionDeleteFunc callback, gpointer user_data) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMConnection *for_agents; - g_object_ref (connection); - set_visible (connection, FALSE); + g_object_ref (self); + set_visible (self, FALSE); /* Tell agents to remove secrets for this connection */ - for_agents = nm_simple_connection_new_clone (NM_CONNECTION (connection)); + for_agents = nm_simple_connection_new_clone (NM_CONNECTION (self)); nm_connection_clear_secrets (for_agents); nm_agent_manager_delete_secrets (priv->agent_mgr, for_agents); g_object_unref (for_agents); /* Remove timestamp from timestamps database file */ - remove_entry_from_db (connection, "timestamps"); + remove_entry_from_db (self, "timestamps"); /* Remove connection from seen-bssids database file */ - remove_entry_from_db (connection, "seen-bssids"); + remove_entry_from_db (self, "seen-bssids"); - nm_settings_connection_signal_remove (connection); + nm_settings_connection_signal_remove (self); - callback (connection, NULL, user_data); + callback (self, NULL, user_data); - g_object_unref (connection); + g_object_unref (self); } /**************************************************************/ static gboolean -supports_secrets (NMSettingsConnection *connection, const char *setting_name) +supports_secrets (NMSettingsConnection *self, const char *setting_name) { /* All secrets supported */ return TRUE; @@ -734,13 +762,13 @@ has_system_owned_secrets (GHashTableIter *iter, } static void -new_secrets_commit_cb (NMSettingsConnection *connection, +new_secrets_commit_cb (NMSettingsConnection *self, GError *error, gpointer user_data) { if (error) { - nm_log_warn (LOGD_SETTINGS, "Error saving new secrets to backing storage: (%d) %s", - error->code, error->message ? error->message : "(unknown)"); + _LOGW ("Error saving new secrets to backing storage: (%d) %s", + error->code, error->message ? error->message : "(unknown)"); } } @@ -767,12 +795,11 @@ agent_secrets_done_cb (NMAgentManager *manager, gboolean agent_had_system = FALSE; if (error) { - nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) secrets request error: (%d) %s", - nm_connection_get_uuid (NM_CONNECTION (self)), - setting_name, - call_id, - error->code, - error->message ? error->message : "(unknown)"); + _LOGD ("(%s:%u) secrets request error: (%d) %s", + setting_name, + call_id, + error->code, + error->message ? error->message : "(unknown)"); callback (self, call_id, NULL, setting_name, error, callback_data); return; @@ -789,11 +816,10 @@ agent_secrets_done_cb (NMAgentManager *manager, g_assert (secrets); if (agent_dbus_owner) { - nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) secrets returned from agent %s", - nm_connection_get_uuid (NM_CONNECTION (self)), - setting_name, - call_id, - agent_dbus_owner); + _LOGD ("(%s:%u) secrets returned from agent %s", + setting_name, + call_id, + agent_dbus_owner); /* If the agent returned any system-owned secrets (initial connect and no * secrets given when the connection was created, or something like that) @@ -807,36 +833,32 @@ agent_secrets_done_cb (NMAgentManager *manager, /* No user interaction was allowed when requesting secrets; the * agent is being bad. Remove system-owned secrets. */ - nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) interaction forbidden but agent %s returned system secrets", - nm_connection_get_uuid (NM_CONNECTION (self)), - setting_name, - call_id, - agent_dbus_owner); + _LOGD ("(%s:%u) interaction forbidden but agent %s returned system secrets", + setting_name, + call_id, + agent_dbus_owner); for_each_secret (NM_CONNECTION (self), secrets, FALSE, clear_nonagent_secrets, NULL); } else if (agent_has_modify == FALSE) { /* Agent didn't successfully authenticate; clear system-owned secrets * from the secrets the agent returned. */ - nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) agent failed to authenticate but provided system secrets", - nm_connection_get_uuid (NM_CONNECTION (self)), - setting_name, - call_id); + _LOGD ("(%s:%u) agent failed to authenticate but provided system secrets", + setting_name, + call_id); for_each_secret (NM_CONNECTION (self), secrets, FALSE, clear_nonagent_secrets, NULL); } } } else { - nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) existing secrets returned", - nm_connection_get_uuid (NM_CONNECTION (self)), - setting_name, - call_id); + _LOGD ("(%s:%u) existing secrets returned", + setting_name, + call_id); } - nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) secrets request completed", - nm_connection_get_uuid (NM_CONNECTION (self)), - setting_name, - call_id); + _LOGD ("(%s:%u) secrets request completed", + setting_name, + call_id); /* If no user interaction was allowed, make sure that no "unsaved" secrets * came back. Unsaved secrets by definition require user interaction. @@ -869,34 +891,30 @@ agent_secrets_done_cb (NMAgentManager *manager, * nothing has changed, since agent-owned secrets don't get saved here. */ if (agent_had_system) { - nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) saving new secrets to backing storage", - nm_connection_get_uuid (NM_CONNECTION (self)), - setting_name, - call_id); + _LOGD ("(%s:%u) saving new secrets to backing storage", + setting_name, + call_id); nm_settings_connection_commit_changes (self, new_secrets_commit_cb, NULL); } else { - nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) new agent secrets processed", - nm_connection_get_uuid (NM_CONNECTION (self)), - setting_name, - call_id); + _LOGD ("(%s:%u) new agent secrets processed", + setting_name, + call_id); } } else { - nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) failed to update with agent secrets: (%d) %s", - nm_connection_get_uuid (NM_CONNECTION (self)), - setting_name, - call_id, - local ? local->code : -1, - (local && local->message) ? local->message : "(unknown)"); + _LOGD ("(%s:%u) failed to update with agent secrets: (%d) %s", + setting_name, + call_id, + local ? local->code : -1, + (local && local->message) ? local->message : "(unknown)"); } g_variant_unref (secrets_dict); } else { - nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) failed to update with existing secrets: (%d) %s", - nm_connection_get_uuid (NM_CONNECTION (self)), - setting_name, - call_id, - local ? local->code : -1, - (local && local->message) ? local->message : "(unknown)"); + _LOGD ("(%s:%u) failed to update with existing secrets: (%d) %s", + setting_name, + call_id, + local ? local->code : -1, + (local && local->message) ? local->message : "(unknown)"); } callback (self, call_id, agent_username, setting_name, local, callback_data); @@ -907,7 +925,7 @@ agent_secrets_done_cb (NMAgentManager *manager, /** * nm_settings_connection_get_secrets: - * @connection: the #NMSettingsConnection + * @self: the #NMSettingsConnection * @subject: the #NMAuthSubject originating the request * @setting_name: the setting to return secrets for * @flags: flags to modify the secrets request @@ -935,7 +953,7 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self, GVariant *existing_secrets; GHashTable *existing_secrets_hash; guint32 call_id = 0; - char *joined_hints = NULL; + gs_free char *joined_hints = NULL; /* Use priv->secrets to work around the fact that nm_connection_clear_secrets() * will clear secrets on this object's settings. @@ -973,17 +991,11 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self, if (existing_secrets) g_variant_unref (existing_secrets); - if (nm_logging_enabled (LOGL_DEBUG, LOGD_SETTINGS)) { - if (hints) - joined_hints = g_strjoinv (",", (char **) hints); - nm_log_dbg (LOGD_SETTINGS, "(%s/%s:%u) secrets requested flags 0x%X hints '%s'", - nm_connection_get_uuid (NM_CONNECTION (self)), - setting_name, - call_id, - flags, - joined_hints ? joined_hints : "(none)"); - g_free (joined_hints); - } + _LOGD ("(%s:%u) secrets requested flags 0x%X hints '%s'", + setting_name, + call_id, + flags, + (hints && hints[0]) ? (joined_hints = g_strjoinv (",", (char **) hints)) : "(none)"); return call_id; } @@ -994,9 +1006,8 @@ nm_settings_connection_cancel_secrets (NMSettingsConnection *self, { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); - nm_log_dbg (LOGD_SETTINGS, "(%s:%u) secrets canceled", - nm_connection_get_uuid (NM_CONNECTION (self)), - call_id); + _LOGD ("(%u) secrets canceled", + call_id); priv->reqs = g_slist_remove (priv->reqs, GUINT_TO_POINTER (call_id)); nm_agent_manager_cancel_secrets (priv->agent_mgr, call_id); @@ -1004,7 +1015,7 @@ nm_settings_connection_cancel_secrets (NMSettingsConnection *self, /**** User authorization **************************************/ -typedef void (*AuthCallback) (NMSettingsConnection *connection, +typedef void (*AuthCallback) (NMSettingsConnection *self, DBusGMethodInvocation *context, NMAuthSubject *subject, GError *error, @@ -1136,13 +1147,13 @@ auth_start (NMSettingsConnection *self, /**** DBus method handlers ************************************/ static gboolean -check_writable (NMConnection *connection, GError **error) +check_writable (NMConnection *self, GError **error) { NMSettingConnection *s_con; - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (self), FALSE); - s_con = nm_connection_get_setting_connection (connection); + s_con = nm_connection_get_setting_connection (self); if (!s_con) { g_set_error_literal (error, NM_SETTINGS_ERROR, @@ -1272,11 +1283,11 @@ has_some_secrets_cb (NMSetting *setting, } static gboolean -any_secrets_present (NMConnection *connection) +any_secrets_present (NMConnection *self) { gboolean has_secrets = FALSE; - nm_connection_for_each_setting_value (connection, has_some_secrets_cb, &has_secrets); + nm_connection_for_each_setting_value (self, has_some_secrets_cb, &has_secrets); return has_secrets; } @@ -1515,7 +1526,7 @@ impl_settings_connection_save (NMSettingsConnection *self, } static void -con_delete_cb (NMSettingsConnection *connection, +con_delete_cb (NMSettingsConnection *self, GError *error, gpointer user_data) { @@ -1528,7 +1539,7 @@ con_delete_cb (NMSettingsConnection *connection, } static void -delete_auth_cb (NMSettingsConnection *self, +delete_auth_cb (NMSettingsConnection *self, DBusGMethodInvocation *context, NMAuthSubject *subject, GError *error, @@ -1543,7 +1554,7 @@ delete_auth_cb (NMSettingsConnection *self, } static const char * -get_modify_permission_basic (NMSettingsConnection *connection) +get_modify_permission_basic (NMSettingsConnection *self) { NMSettingConnection *s_con; @@ -1551,7 +1562,7 @@ get_modify_permission_basic (NMSettingsConnection *connection) * we use the 'modify.own' permission instead of 'modify.system'. If the * request affects more than just the caller, require 'modify.system'. */ - s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection)); + s_con = nm_connection_get_setting_connection (NM_CONNECTION (self)); g_assert (s_con); if (nm_setting_connection_get_num_permissions (s_con) == 1) return NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN; @@ -1692,7 +1703,7 @@ clear_secrets_cb (NMSettingsConnection *self, } static void -dbus_clear_secrets_auth_cb (NMSettingsConnection *self, +dbus_clear_secrets_auth_cb (NMSettingsConnection *self, DBusGMethodInvocation *context, NMAuthSubject *subject, GError *error, @@ -1815,7 +1826,7 @@ nm_settings_connection_set_flags_all (NMSettingsConnection *self, NMSettingsConn /** * nm_settings_connection_get_timestamp: - * @connection: the #NMSettingsConnection + * @self: the #NMSettingsConnection * @out_timestamp: the connection's timestamp * * Returns the time (in seconds since the Unix epoch) when the connection @@ -1824,19 +1835,19 @@ nm_settings_connection_set_flags_all (NMSettingsConnection *self, NMSettingsConn * Returns: %TRUE if the timestamp has ever been set, otherwise %FALSE. **/ gboolean -nm_settings_connection_get_timestamp (NMSettingsConnection *connection, +nm_settings_connection_get_timestamp (NMSettingsConnection *self, guint64 *out_timestamp) { - g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (connection), FALSE); + g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE); if (out_timestamp) - *out_timestamp = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->timestamp; - return NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->timestamp_set; + *out_timestamp = NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->timestamp; + return NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->timestamp_set; } /** * nm_settings_connection_update_timestamp: - * @connection: the #NMSettingsConnection + * @self: the #NMSettingsConnection * @timestamp: timestamp to set into the connection and to store into * the timestamps database * @flush_to_disk: if %TRUE, commit timestamp update to persistent storage @@ -1844,18 +1855,18 @@ nm_settings_connection_get_timestamp (NMSettingsConnection *connection, * Updates the connection and timestamps database with the provided timestamp. **/ void -nm_settings_connection_update_timestamp (NMSettingsConnection *connection, +nm_settings_connection_update_timestamp (NMSettingsConnection *self, guint64 timestamp, gboolean flush_to_disk) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); const char *connection_uuid; GKeyFile *timestamps_file; char *data, *tmp; gsize len; GError *error = NULL; - g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection)); + g_return_if_fail (NM_IS_SETTINGS_CONNECTION (self)); /* Update timestamp in private storage */ priv->timestamp = timestamp; @@ -1868,11 +1879,11 @@ nm_settings_connection_update_timestamp (NMSettingsConnection *connection, timestamps_file = g_key_file_new (); if (!g_key_file_load_from_file (timestamps_file, SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) { if (!(error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT)) - nm_log_warn (LOGD_SETTINGS, "error parsing timestamps file '%s': %s", SETTINGS_TIMESTAMPS_FILE, error->message); + _LOGW ("error parsing timestamps file '%s': %s", SETTINGS_TIMESTAMPS_FILE, error->message); g_clear_error (&error); } - connection_uuid = nm_connection_get_uuid (NM_CONNECTION (connection)); + connection_uuid = nm_connection_get_uuid (NM_CONNECTION (self)); tmp = g_strdup_printf ("%" G_GUINT64_FORMAT, timestamp); g_key_file_set_value (timestamps_file, "timestamps", connection_uuid, tmp); g_free (tmp); @@ -1883,7 +1894,7 @@ nm_settings_connection_update_timestamp (NMSettingsConnection *connection, g_free (data); } if (error) { - nm_log_warn (LOGD_SETTINGS, "error saving timestamp to file '%s': %s", SETTINGS_TIMESTAMPS_FILE, error->message); + _LOGW ("error saving timestamp to file '%s': %s", SETTINGS_TIMESTAMPS_FILE, error->message); g_error_free (error); } g_key_file_free (timestamps_file); @@ -1891,27 +1902,27 @@ nm_settings_connection_update_timestamp (NMSettingsConnection *connection, /** * nm_settings_connection_read_and_fill_timestamp: - * @connection: the #NMSettingsConnection + * @self: the #NMSettingsConnection * * Retrieves timestamp of the connection's last usage from database file and * stores it into the connection private data. **/ void -nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *connection) +nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *self) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); const char *connection_uuid; guint64 timestamp = 0; GKeyFile *timestamps_file; GError *err = NULL; char *tmp_str; - g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection)); + g_return_if_fail (NM_IS_SETTINGS_CONNECTION (self)); /* Get timestamp from database file */ timestamps_file = g_key_file_new (); g_key_file_load_from_file (timestamps_file, SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL); - connection_uuid = nm_connection_get_uuid (NM_CONNECTION (connection)); + connection_uuid = nm_connection_get_uuid (NM_CONNECTION (self)); tmp_str = g_key_file_get_value (timestamps_file, "timestamps", connection_uuid, &err); if (tmp_str) { timestamp = g_ascii_strtoull (tmp_str, NULL, 10); @@ -1923,8 +1934,8 @@ nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *connection priv->timestamp = timestamp; priv->timestamp_set = TRUE; } else { - nm_log_dbg (LOGD_SETTINGS, "failed to read connection timestamp for '%s': (%d) %s", - connection_uuid, err->code, err->message); + _LOGD ("failed to read connection timestamp: (%d) %s", + err->code, err->message); g_clear_error (&err); } g_key_file_free (timestamps_file); @@ -1932,7 +1943,7 @@ nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *connection /** * nm_settings_connection_get_seen_bssids: - * @connection: the #NMSettingsConnection + * @self: the #NMSettingsConnection * * Returns current list of seen BSSIDs for the connection. * @@ -1940,14 +1951,14 @@ nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *connection * The caller is responsible for freeing the list, but not the content. **/ char ** -nm_settings_connection_get_seen_bssids (NMSettingsConnection *connection) +nm_settings_connection_get_seen_bssids (NMSettingsConnection *self) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); GHashTableIter iter; char **bssids, *bssid; int i; - g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (connection), NULL); + g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), NULL); bssids = g_new (char *, g_hash_table_size (priv->seen_bssids) + 1); @@ -1962,34 +1973,34 @@ nm_settings_connection_get_seen_bssids (NMSettingsConnection *connection) /** * nm_settings_connection_has_seen_bssid: - * @connection: the #NMSettingsConnection + * @self: the #NMSettingsConnection * @bssid: the BSSID to check the seen BSSID list for * * Returns: %TRUE if the given @bssid is in the seen BSSIDs list **/ gboolean -nm_settings_connection_has_seen_bssid (NMSettingsConnection *connection, +nm_settings_connection_has_seen_bssid (NMSettingsConnection *self, const char *bssid) { - g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (connection), FALSE); + g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE); g_return_val_if_fail (bssid != NULL, FALSE); - return !!g_hash_table_lookup (NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->seen_bssids, bssid); + return !!g_hash_table_lookup (NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->seen_bssids, bssid); } /** * nm_settings_connection_add_seen_bssid: - * @connection: the #NMSettingsConnection + * @self: the #NMSettingsConnection * @seen_bssid: BSSID to set into the connection and to store into * the seen-bssids database * * Updates the connection and seen-bssids database with the provided BSSID. **/ void -nm_settings_connection_add_seen_bssid (NMSettingsConnection *connection, +nm_settings_connection_add_seen_bssid (NMSettingsConnection *self, const char *seen_bssid) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); const char *connection_uuid; GKeyFile *seen_bssids_file; char *data, *bssid_str; @@ -2020,13 +2031,13 @@ nm_settings_connection_add_seen_bssid (NMSettingsConnection *connection, g_key_file_set_list_separator (seen_bssids_file, ','); if (!g_key_file_load_from_file (seen_bssids_file, SETTINGS_SEEN_BSSIDS_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) { if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { - nm_log_warn (LOGD_SETTINGS, "error parsing seen-bssids file '%s': %s", - SETTINGS_SEEN_BSSIDS_FILE, error->message); + _LOGW ("error parsing seen-bssids file '%s': %s", + SETTINGS_SEEN_BSSIDS_FILE, error->message); } g_clear_error (&error); } - connection_uuid = nm_connection_get_uuid (NM_CONNECTION (connection)); + connection_uuid = nm_connection_get_uuid (NM_CONNECTION (self)); g_key_file_set_string_list (seen_bssids_file, "seen-bssids", connection_uuid, list, n); g_free (list); @@ -2038,23 +2049,23 @@ nm_settings_connection_add_seen_bssid (NMSettingsConnection *connection, g_key_file_free (seen_bssids_file); if (error) { - nm_log_warn (LOGD_SETTINGS, "error saving seen-bssids to file '%s': %s", - SETTINGS_SEEN_BSSIDS_FILE, error->message); + _LOGW ("error saving seen-bssids to file '%s': %s", + SETTINGS_SEEN_BSSIDS_FILE, error->message); g_error_free (error); } } /** * nm_settings_connection_read_and_fill_seen_bssids: - * @connection: the #NMSettingsConnection + * @self: the #NMSettingsConnection * * Retrieves seen BSSIDs of the connection from database file and stores then into the * connection private data. **/ void -nm_settings_connection_read_and_fill_seen_bssids (NMSettingsConnection *connection) +nm_settings_connection_read_and_fill_seen_bssids (NMSettingsConnection *self) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); const char *connection_uuid; GKeyFile *seen_bssids_file; char **tmp_strv = NULL; @@ -2065,7 +2076,7 @@ nm_settings_connection_read_and_fill_seen_bssids (NMSettingsConnection *connecti seen_bssids_file = g_key_file_new (); g_key_file_set_list_separator (seen_bssids_file, ','); if (g_key_file_load_from_file (seen_bssids_file, SETTINGS_SEEN_BSSIDS_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL)) { - connection_uuid = nm_connection_get_uuid (NM_CONNECTION (connection)); + connection_uuid = nm_connection_get_uuid (NM_CONNECTION (self)); tmp_strv = g_key_file_get_string_list (seen_bssids_file, "seen-bssids", connection_uuid, &len, NULL); } g_key_file_free (seen_bssids_file); @@ -2082,7 +2093,7 @@ nm_settings_connection_read_and_fill_seen_bssids (NMSettingsConnection *connecti * seen-bssids list from the deprecated seen-bssids property of the * wifi setting. */ - s_wifi = nm_connection_get_setting_wireless (NM_CONNECTION (connection)); + s_wifi = nm_connection_get_setting_wireless (NM_CONNECTION (self)); if (s_wifi) { len = nm_setting_wireless_get_num_seen_bssids (s_wifi); for (i = 0; i < len; i++) { @@ -2098,16 +2109,16 @@ nm_settings_connection_read_and_fill_seen_bssids (NMSettingsConnection *connecti #define AUTOCONNECT_RESET_RETRIES_TIMER 300 int -nm_settings_connection_get_autoconnect_retries (NMSettingsConnection *connection) +nm_settings_connection_get_autoconnect_retries (NMSettingsConnection *self) { - return NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->autoconnect_retries; + return NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->autoconnect_retries; } void -nm_settings_connection_set_autoconnect_retries (NMSettingsConnection *connection, +nm_settings_connection_set_autoconnect_retries (NMSettingsConnection *self, int retries) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); priv->autoconnect_retries = retries; if (retries) @@ -2117,34 +2128,34 @@ nm_settings_connection_set_autoconnect_retries (NMSettingsConnection *connection } void -nm_settings_connection_reset_autoconnect_retries (NMSettingsConnection *connection) +nm_settings_connection_reset_autoconnect_retries (NMSettingsConnection *self) { - nm_settings_connection_set_autoconnect_retries (connection, AUTOCONNECT_RETRIES_DEFAULT); + nm_settings_connection_set_autoconnect_retries (self, AUTOCONNECT_RETRIES_DEFAULT); } gint32 -nm_settings_connection_get_autoconnect_retry_time (NMSettingsConnection *connection) +nm_settings_connection_get_autoconnect_retry_time (NMSettingsConnection *self) { - return NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->autoconnect_retry_time; + return NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->autoconnect_retry_time; } NMDeviceStateReason -nm_settings_connection_get_autoconnect_blocked_reason (NMSettingsConnection *connection) +nm_settings_connection_get_autoconnect_blocked_reason (NMSettingsConnection *self) { - return NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->autoconnect_blocked_reason; + return NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->autoconnect_blocked_reason; } void -nm_settings_connection_set_autoconnect_blocked_reason (NMSettingsConnection *connection, +nm_settings_connection_set_autoconnect_blocked_reason (NMSettingsConnection *self, NMDeviceStateReason reason) { - NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->autoconnect_blocked_reason = reason; + NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->autoconnect_blocked_reason = reason; } gboolean -nm_settings_connection_can_autoconnect (NMSettingsConnection *connection) +nm_settings_connection_can_autoconnect (NMSettingsConnection *self) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMSettingConnection *s_con; const char *permission; @@ -2153,13 +2164,13 @@ nm_settings_connection_can_autoconnect (NMSettingsConnection *connection) || priv->autoconnect_blocked_reason != NM_DEVICE_STATE_REASON_NONE) return FALSE; - s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection)); + s_con = nm_connection_get_setting_connection (NM_CONNECTION (self)); if (!nm_setting_connection_get_autoconnect (s_con)) return FALSE; - permission = nm_utils_get_shared_wifi_permission (NM_CONNECTION (connection)); + permission = nm_utils_get_shared_wifi_permission (NM_CONNECTION (self)); if (permission) { - if (nm_settings_connection_check_permission (connection, permission) == FALSE) + if (nm_settings_connection_check_permission (self, permission) == FALSE) return FALSE; } @@ -2168,89 +2179,89 @@ nm_settings_connection_can_autoconnect (NMSettingsConnection *connection) /** * nm_settings_connection_get_nm_generated: - * @connection: an #NMSettingsConnection + * @self: an #NMSettingsConnection * - * Gets the "nm-generated" flag on @connection. + * Gets the "nm-generated" flag on @self. * * A connection is "nm-generated" if it was generated by * nm_device_generate_connection() and has not been modified or * saved by the user since then. */ gboolean -nm_settings_connection_get_nm_generated (NMSettingsConnection *connection) +nm_settings_connection_get_nm_generated (NMSettingsConnection *self) { - return NM_FLAGS_HAS (nm_settings_connection_get_flags (connection), NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED); + return NM_FLAGS_HAS (nm_settings_connection_get_flags (self), NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED); } /** * nm_settings_connection_get_nm_generated_assumed: - * @connection: an #NMSettingsConnection + * @self: an #NMSettingsConnection * - * Gets the "nm-generated-assumed" flag on @connection. + * Gets the "nm-generated-assumed" flag on @self. * * The connection is a generated connection especially * generated for connection assumption. */ gboolean -nm_settings_connection_get_nm_generated_assumed (NMSettingsConnection *connection) +nm_settings_connection_get_nm_generated_assumed (NMSettingsConnection *self) { - return NM_FLAGS_HAS (nm_settings_connection_get_flags (connection), NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED); + return NM_FLAGS_HAS (nm_settings_connection_get_flags (self), NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED); } gboolean -nm_settings_connection_get_ready (NMSettingsConnection *connection) +nm_settings_connection_get_ready (NMSettingsConnection *self) { - return NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->ready; + return NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->ready; } void -nm_settings_connection_set_ready (NMSettingsConnection *connection, +nm_settings_connection_set_ready (NMSettingsConnection *self, gboolean ready) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); ready = !!ready; if (priv->ready != ready) { priv->ready = ready; - g_object_notify (G_OBJECT (connection), NM_SETTINGS_CONNECTION_READY); + g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTION_READY); } } /** * nm_settings_connection_set_filename: - * @connection: an #NMSettingsConnection - * @filename: @connection's filename + * @self: an #NMSettingsConnection + * @filename: @self's filename * - * Called by a backend to sets the filename that @connection is read + * Called by a backend to sets the filename that @self is read * from/written to. */ void -nm_settings_connection_set_filename (NMSettingsConnection *connection, +nm_settings_connection_set_filename (NMSettingsConnection *self, const char *filename) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); if (g_strcmp0 (filename, priv->filename) != 0) { g_free (priv->filename); priv->filename = g_strdup (filename); - g_object_notify (G_OBJECT (connection), NM_SETTINGS_CONNECTION_FILENAME); + g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTION_FILENAME); } } /** * nm_settings_connection_get_filename: - * @connection: an #NMSettingsConnection + * @self: an #NMSettingsConnection * - * Gets the filename that @connection was read from/written to. This may be - * %NULL if @connection is unsaved, or if it is associated with a backend that + * Gets the filename that @self was read from/written to. This may be + * %NULL if @self is unsaved, or if it is associated with a backend that * does not store each connection in a separate file. * - * Returns: @connection's filename. + * Returns: @self's filename. */ const char * -nm_settings_connection_get_filename (NMSettingsConnection *connection) +nm_settings_connection_get_filename (NMSettingsConnection *self) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); return priv->filename; } @@ -2283,12 +2294,24 @@ nm_settings_connection_init (NMSettingsConnection *self) } static void +constructed (GObject *object) +{ + NMSettingsConnection *self = NM_SETTINGS_CONNECTION (object); + + _LOGD ("constructed (%s)", G_OBJECT_TYPE_NAME (self)); + + G_OBJECT_CLASS (nm_settings_connection_parent_class)->constructed (object); +} + +static void dispose (GObject *object) { NMSettingsConnection *self = NM_SETTINGS_CONNECTION (object); NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); GSList *iter; + _LOGD ("disposing"); + if (priv->updated_idle_id) { g_source_remove (priv->updated_idle_id); priv->updated_idle_id = 0; @@ -2389,6 +2412,7 @@ nm_settings_connection_class_init (NMSettingsConnectionClass *class) g_type_class_add_private (class, sizeof (NMSettingsConnectionPrivate)); /* Virtual methods */ + object_class->constructed = constructed; object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; @@ -2439,7 +2463,7 @@ nm_settings_connection_class_init (NMSettingsConnectionClass *class) /* Signals */ /* Emitted when the connection is changed for any reason */ - signals[UPDATED] = + signals[UPDATED] = g_signal_new (NM_SETTINGS_CONNECTION_UPDATED, G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_FIRST, diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h index 49661f38..512112f0 100644 --- a/src/settings/nm-settings-connection.h +++ b/src/settings/nm-settings-connection.h @@ -81,11 +81,11 @@ typedef enum typedef struct _NMSettingsConnectionClass NMSettingsConnectionClass; -typedef void (*NMSettingsConnectionCommitFunc) (NMSettingsConnection *connection, +typedef void (*NMSettingsConnectionCommitFunc) (NMSettingsConnection *self, GError *error, gpointer user_data); -typedef void (*NMSettingsConnectionDeleteFunc) (NMSettingsConnection *connection, +typedef void (*NMSettingsConnectionDeleteFunc) (NMSettingsConnection *self, GError *error, gpointer user_data); @@ -97,26 +97,26 @@ struct _NMSettingsConnectionClass { GObjectClass parent; /* virtual methods */ - void (*replace_and_commit) (NMSettingsConnection *connection, + void (*replace_and_commit) (NMSettingsConnection *self, NMConnection *new_connection, NMSettingsConnectionCommitFunc callback, gpointer user_data); - void (*commit_changes) (NMSettingsConnection *connection, + void (*commit_changes) (NMSettingsConnection *self, NMSettingsConnectionCommitFunc callback, gpointer user_data); - void (*delete) (NMSettingsConnection *connection, + void (*delete) (NMSettingsConnection *self, NMSettingsConnectionDeleteFunc callback, gpointer user_data); - gboolean (*supports_secrets) (NMSettingsConnection *connection, + gboolean (*supports_secrets) (NMSettingsConnection *self, const char *setting_name); }; GType nm_settings_connection_get_type (void); -void nm_settings_connection_commit_changes (NMSettingsConnection *connection, +void nm_settings_connection_commit_changes (NMSettingsConnection *self, NMSettingsConnectionCommitFunc callback, gpointer user_data); @@ -131,18 +131,18 @@ void nm_settings_connection_replace_and_commit (NMSettingsConnection *self, NMSettingsConnectionCommitFunc callback, gpointer user_data); -void nm_settings_connection_delete (NMSettingsConnection *connection, +void nm_settings_connection_delete (NMSettingsConnection *self, NMSettingsConnectionDeleteFunc callback, gpointer user_data); -typedef void (*NMSettingsConnectionSecretsFunc) (NMSettingsConnection *connection, +typedef void (*NMSettingsConnectionSecretsFunc) (NMSettingsConnection *self, guint32 call_id, const char *agent_username, const char *setting_name, GError *error, gpointer user_data); -guint32 nm_settings_connection_get_secrets (NMSettingsConnection *connection, +guint32 nm_settings_connection_get_secrets (NMSettingsConnection *self, NMAuthSubject *subject, const char *setting_name, NMSecretAgentGetSecretsFlags flags, @@ -151,7 +151,7 @@ guint32 nm_settings_connection_get_secrets (NMSettingsConnection *connection, gpointer callback_data, GError **error); -void nm_settings_connection_cancel_secrets (NMSettingsConnection *connection, +void nm_settings_connection_cancel_secrets (NMSettingsConnection *self, guint32 call_id); gboolean nm_settings_connection_is_visible (NMSettingsConnection *self); @@ -165,52 +165,52 @@ void nm_settings_connection_signal_remove (NMSettingsConnection *self); gboolean nm_settings_connection_get_unsaved (NMSettingsConnection *self); -NMSettingsConnectionFlags nm_settings_connection_get_flags (NMSettingsConnection *connection); -NMSettingsConnectionFlags nm_settings_connection_set_flags (NMSettingsConnection *connection, NMSettingsConnectionFlags flags, gboolean set); -NMSettingsConnectionFlags nm_settings_connection_set_flags_all (NMSettingsConnection *connection, NMSettingsConnectionFlags flags); +NMSettingsConnectionFlags nm_settings_connection_get_flags (NMSettingsConnection *self); +NMSettingsConnectionFlags nm_settings_connection_set_flags (NMSettingsConnection *self, NMSettingsConnectionFlags flags, gboolean set); +NMSettingsConnectionFlags nm_settings_connection_set_flags_all (NMSettingsConnection *self, NMSettingsConnectionFlags flags); -gboolean nm_settings_connection_get_timestamp (NMSettingsConnection *connection, +gboolean nm_settings_connection_get_timestamp (NMSettingsConnection *self, guint64 *out_timestamp); -void nm_settings_connection_update_timestamp (NMSettingsConnection *connection, +void nm_settings_connection_update_timestamp (NMSettingsConnection *self, guint64 timestamp, gboolean flush_to_disk); -void nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *connection); +void nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *self); -char **nm_settings_connection_get_seen_bssids (NMSettingsConnection *connection); +char **nm_settings_connection_get_seen_bssids (NMSettingsConnection *self); -gboolean nm_settings_connection_has_seen_bssid (NMSettingsConnection *connection, +gboolean nm_settings_connection_has_seen_bssid (NMSettingsConnection *self, const char *bssid); -void nm_settings_connection_add_seen_bssid (NMSettingsConnection *connection, +void nm_settings_connection_add_seen_bssid (NMSettingsConnection *self, const char *seen_bssid); -void nm_settings_connection_read_and_fill_seen_bssids (NMSettingsConnection *connection); +void nm_settings_connection_read_and_fill_seen_bssids (NMSettingsConnection *self); -int nm_settings_connection_get_autoconnect_retries (NMSettingsConnection *connection); -void nm_settings_connection_set_autoconnect_retries (NMSettingsConnection *connection, +int nm_settings_connection_get_autoconnect_retries (NMSettingsConnection *self); +void nm_settings_connection_set_autoconnect_retries (NMSettingsConnection *self, int retries); -void nm_settings_connection_reset_autoconnect_retries (NMSettingsConnection *connection); +void nm_settings_connection_reset_autoconnect_retries (NMSettingsConnection *self); -gint32 nm_settings_connection_get_autoconnect_retry_time (NMSettingsConnection *connection); +gint32 nm_settings_connection_get_autoconnect_retry_time (NMSettingsConnection *self); -NMDeviceStateReason nm_settings_connection_get_autoconnect_blocked_reason (NMSettingsConnection *connection); -void nm_settings_connection_set_autoconnect_blocked_reason (NMSettingsConnection *connection, +NMDeviceStateReason nm_settings_connection_get_autoconnect_blocked_reason (NMSettingsConnection *self); +void nm_settings_connection_set_autoconnect_blocked_reason (NMSettingsConnection *self, NMDeviceStateReason reason); -gboolean nm_settings_connection_can_autoconnect (NMSettingsConnection *connection); +gboolean nm_settings_connection_can_autoconnect (NMSettingsConnection *self); -gboolean nm_settings_connection_get_nm_generated (NMSettingsConnection *connection); -gboolean nm_settings_connection_get_nm_generated_assumed (NMSettingsConnection *connection); +gboolean nm_settings_connection_get_nm_generated (NMSettingsConnection *self); +gboolean nm_settings_connection_get_nm_generated_assumed (NMSettingsConnection *self); -gboolean nm_settings_connection_get_ready (NMSettingsConnection *connection); -void nm_settings_connection_set_ready (NMSettingsConnection *connection, +gboolean nm_settings_connection_get_ready (NMSettingsConnection *self); +void nm_settings_connection_set_ready (NMSettingsConnection *self, gboolean ready); -void nm_settings_connection_set_filename (NMSettingsConnection *connection, +void nm_settings_connection_set_filename (NMSettingsConnection *self, const char *filename); -const char *nm_settings_connection_get_filename (NMSettingsConnection *connection); +const char *nm_settings_connection_get_filename (NMSettingsConnection *self); G_END_DECLS diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c index a18920c6..9499d8ce 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c +++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c @@ -67,6 +67,8 @@ typedef struct { gulong devtimeout_link_changed_handler; guint devtimeout_timeout_id; + + NMInotifyHelper *inotify_helper; } NMIfcfgConnectionPrivate; enum { @@ -84,6 +86,14 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; +static NMInotifyHelper * +_get_inotify_helper (NMIfcfgConnectionPrivate *priv) +{ + if (!priv->inotify_helper) + priv->inotify_helper = g_object_ref (nm_inotify_helper_get ()); + return priv->inotify_helper; +} + static gboolean devtimeout_ready (gpointer user_data) { @@ -149,6 +159,7 @@ nm_ifcfg_connection_check_devtimeout (NMIfcfgConnection *self) const char *ifname; const char *filename; guint devtimeout; + const NMPlatformLink *pllink; s_con = nm_connection_get_setting_connection (NM_CONNECTION (self)); @@ -160,11 +171,13 @@ nm_ifcfg_connection_check_devtimeout (NMIfcfgConnection *self) filename = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (self)); if (!filename) return; - devtimeout = devtimeout_from_file (filename); - if (!devtimeout) + + pllink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, ifname); + if (pllink && pllink->initialized) return; - if (nm_platform_link_get_ifindex (NM_PLATFORM_GET, ifname) != 0) + devtimeout = devtimeout_from_file (filename); + if (!devtimeout) return; /* ONBOOT=yes, DEVICE and DEVTIMEOUT are set, but device is not present */ @@ -261,7 +274,7 @@ path_watch_stop (NMIfcfgConnection *self) NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self); NMInotifyHelper *ih; - ih = nm_inotify_helper_get (); + ih = _get_inotify_helper (priv); if (priv->ih_event_id) { g_signal_handler_disconnect (ih, priv->ih_event_id); @@ -315,7 +328,9 @@ filename_changed (GObject *object, priv->route6file = utils_get_route6_path (ifcfg_path); if (nm_config_get_monitor_connection_files (nm_config_get ())) { - NMInotifyHelper *ih = nm_inotify_helper_get (); + NMInotifyHelper *ih; + + ih = _get_inotify_helper (priv); priv->ih_event_id = g_signal_connect (ih, "event", G_CALLBACK (files_changed_cb), self); priv->file_wd = nm_inotify_helper_add_watch (ih, ifcfg_path); @@ -509,6 +524,8 @@ dispose (GObject *object) priv->devtimeout_timeout_id = 0; } + g_clear_object (&priv->inotify_helper); + G_OBJECT_CLASS (nm_ifcfg_connection_parent_class)->dispose (object); } diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c index 1a3f791a..526cdafe 100644 --- a/src/settings/plugins/ifcfg-rh/plugin.c +++ b/src/settings/plugins/ifcfg-rh/plugin.c @@ -42,7 +42,7 @@ #include <selinux/selinux.h> #endif -#include <nm-setting-connection.h> +#include "nm-setting-connection.h" #include "common.h" #include "nm-dbus-glib-types.h" @@ -64,22 +64,15 @@ #define DBUS_OBJECT_PATH "/com/redhat/ifcfgrh1" -#define _LOG_DEFAULT_DOMAIN LOGD_SETTINGS - -#define _LOG(level, domain, ...) \ +#define _NMLOG_DOMAIN LOGD_SETTINGS +#define _NMLOG(level, ...) \ G_STMT_START { \ - nm_log ((level), (domain), \ + nm_log ((level), (_NMLOG_DOMAIN), \ "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ "ifcfg-rh: " \ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ } G_STMT_END -#define _LOGT(...) _LOG (LOGL_TRACE, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) -#define _LOGD(...) _LOG (LOGL_DEBUG, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) -#define _LOGI(...) _LOG (LOGL_INFO, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) -#define _LOGW(...) _LOG (LOGL_WARN, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) -#define _LOGE(...) _LOG (LOGL_ERR, _LOG_DEFAULT_DOMAIN, __VA_ARGS__) - #define ERR_GET_MSG(err) (((err) && (err)->message) ? (err)->message : "(unknown)") diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index ec874167..72123e66 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -250,6 +250,15 @@ make_connection_setting (const char *file, g_free (value); } + switch (svTrueValue (ifcfg, "CONNECTION_METERED", -1)) { + case TRUE: + g_object_set (s_con, NM_SETTING_CONNECTION_METERED, NM_METERED_YES, NULL); + break; + case FALSE: + g_object_set (s_con, NM_SETTING_CONNECTION_METERED, NM_METERED_NO, NULL); + break; + } + return NM_SETTING (s_con); } @@ -3492,6 +3501,80 @@ wireless_connection_from_ifcfg (const char *file, return connection; } +static void +parse_ethtool_options (shvarFile *ifcfg, NMSettingWired *s_wired, char *value) +{ + NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; + gboolean use_password = FALSE; + char **words, **iter, *flag; + + if (!value || !value[0]) + return; + + words = g_strsplit_set (value, " ", 0); + iter = words; + + while (iter[0]) { + if (g_str_equal (iter[0], "wol") && iter[1] && *iter[1]) { + for (flag = iter[1]; *flag; flag++) { + switch (*flag) { + case 'p': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_PHY; + break; + case 'u': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST; + break; + case 'm': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST; + break; + case 'b': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST; + break; + case 'a': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_ARP; + break; + case 'g': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC; + break; + case 's': + use_password = TRUE; + break; + case 'd': + wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; + use_password = FALSE; + break; + default: + PARSE_WARNING ("unrecognized Wake-on-LAN option '%c'", *flag); + } + } + + if (!NM_FLAGS_HAS (wol_flags, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) + use_password = FALSE; + + g_object_set (s_wired, NM_SETTING_WIRED_WAKE_ON_LAN, wol_flags, NULL); + iter += 2; + continue; + } + + if (g_str_equal (iter[0], "sopass") && iter[1] && *iter[1]) { + if (use_password) { + if (nm_utils_hwaddr_valid (iter[1], ETH_ALEN)) + g_object_set (s_wired, NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, iter[1], NULL); + else + PARSE_WARNING ("Wake-on-LAN password '%s' is invalid", iter[1]); + } else + PARSE_WARNING ("Wake-on-LAN password not expected"); + iter += 2; + continue; + } + + /* Silently skip unknown options */ + iter++; + } + + g_strfreev (words); +} + static NMSetting * make_wired_setting (shvarFile *ifcfg, const char *file, @@ -3627,6 +3710,10 @@ make_wired_setting (shvarFile *ifcfg, g_free (value); } + value = svGetValue (ifcfg, "ETHTOOL_OPTS", FALSE); + parse_ethtool_options (ifcfg, s_wired, value); + g_free (value); + return (NMSetting *) s_wired; error: diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c index 4a5ca1d1..283aa826 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -303,11 +303,11 @@ svGetValueFull (shvarFile *s, const char *key, gboolean verbatim) * return FALSE if <key> resolves to any non-truth value (e.g. "no", "n", "false") * return <default> otherwise */ -gboolean -svTrueValue (shvarFile *s, const char *key, gboolean def) +gint +svTrueValue (shvarFile *s, const char *key, gint def) { char *tmp; - gboolean returnValue = def; + gint returnValue = def; tmp = svGetValue (s, key, FALSE); if (!tmp) diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index 4902541b..de7a3585 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/settings/plugins/ifcfg-rh/shvar.h @@ -62,7 +62,7 @@ char *svGetValueFull (shvarFile *s, const char *key, gboolean verbatim); * return FALSE if <key> resolves to any non-truth value (e.g. "no", "n", "false") * return <def> otherwise */ -gboolean svTrueValue (shvarFile *s, const char *key, gboolean def); +gint svTrueValue (shvarFile *s, const char *key, gint def); gint64 svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 max, gint64 fallback); diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am index a20a78d9..7b5aaf17 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am @@ -123,7 +123,8 @@ EXTRA_DIST = \ ifcfg-test-team-master \ ifcfg-test-team-port \ ifcfg-test-team-port-empty-config \ - ifcfg-test-vlan-trailing-spaces + ifcfg-test-vlan-trailing-spaces \ + ifcfg-test-wired-wake-on-lan # make target dependencies can't have colons in their names, which ends up # meaning that we can't add the alias files to EXTRA_DIST diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in index ef06c5ef..2435434d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in @@ -518,7 +518,8 @@ EXTRA_DIST = \ ifcfg-test-team-master \ ifcfg-test-team-port \ ifcfg-test-team-port-empty-config \ - ifcfg-test-vlan-trailing-spaces + ifcfg-test-vlan-trailing-spaces \ + ifcfg-test-wired-wake-on-lan # make target dependencies can't have colons in their names, which ends up diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-wake-on-lan b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-wake-on-lan new file mode 100644 index 00000000..1dfc9a43 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-wake-on-lan @@ -0,0 +1,22 @@ +# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile) +TYPE=Ethernet +DEVICE=eth0 +HWADDR=00:11:22:33:44:ee +BOOTPROTO=none +ONBOOT=yes +USERCTL=yes +MTU=1492 +NM_CONTROLLED=yes +DNS1=4.2.2.1 +DNS2=4.2.2.2 +IPADDR=192.168.1.5 +NETMASK=255.255.255.0 +GATEWAY=192.168.1.1 +IPV6INIT=yes +IPV6_AUTOCONF=no +IPV6ADDR=dead:beaf::1 +IPV6ADDR_SECONDARIES="dead:beaf::2/56" +DNS3=1:2:3:4::a +DNS4=1:2:3:4::b +RES_OPTIONS= +ETHTOOL_OPTS="speed 100 duplex full wol apgs sopass 00:11:22:33:44:55 autoneg off" diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index d2fb6867..f2f85d3c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -5104,6 +5104,43 @@ test_read_wifi_wep_eap_ttls_chap (void) } static void +test_read_wired_wake_on_lan (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + gboolean success; + GError *error = NULL; + + connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-wake-on-lan", + NULL, TYPE_WIRELESS, NULL, &error); + g_assert_no_error (error); + g_assert (connection); + + success = nm_connection_verify (connection, &error); + g_assert_no_error (error); + g_assert (success); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME); + + s_wired = nm_connection_get_setting_wired (connection); + g_assert (s_wired); + g_assert_cmpint (nm_setting_wired_get_wake_on_lan (s_wired), + ==, + NM_SETTING_WIRED_WAKE_ON_LAN_ARP | + NM_SETTING_WIRED_WAKE_ON_LAN_PHY | + NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC); + + g_assert_cmpstr (nm_setting_wired_get_wake_on_lan_password (s_wired), + ==, + "00:11:22:33:44:55"); + + g_object_unref (connection); +} + +static void test_read_wifi_hidden (void) { NMConnection *connection; @@ -5218,6 +5255,90 @@ test_write_wifi_hidden (void) } static void +test_write_wired_wake_on_lan (void) +{ + NMConnection *connection, *reread; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingWiredWakeOnLan wol; + char *uuid, *testfile = NULL, *val; + gboolean success; + GError *error = NULL; + shvarFile *f; + + connection = nm_simple_connection_new (); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wired Wake-on-LAN", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + wol = NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST | + NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST | + NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC; + + g_object_set (s_wired, + NM_SETTING_WIRED_WAKE_ON_LAN, wol, + NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, "00:00:00:11:22:33", + NULL); + + success = nm_connection_verify (connection, &error); + g_assert_no_error (error); + g_assert (success); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + g_assert_no_error (error); + g_assert (success); + + f = svOpenFile (testfile, &error); + g_assert_no_error (error); + g_assert (f); + + /* re-read the file to check that the key was written. */ + val = svGetValue (f, "ETHTOOL_OPTS", FALSE); + g_assert (val); + g_assert (strstr (val, "wol")); + g_assert (strstr (val, "sopass 00:00:00:11:22:33")); + g_free (val); + svCloseFile (f); + + /* reread will be normalized, so we must normalize connection too. */ + nm_connection_normalize (connection, NULL, NULL, NULL); + + /* re-read the connection for comparison */ + reread = connection_from_file_test (testfile, NULL, TYPE_ETHERNET, + NULL, &error); + unlink (testfile); + g_assert_no_error (error); + g_assert (reread); + + success = nm_connection_verify (reread, &error); + g_assert_no_error (error); + g_assert (success); + + g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT)); + + g_free (testfile); + g_object_unref (connection); + g_object_unref (reread); +} + +static void test_read_wifi_band_a (void) { NMConnection *connection; @@ -6405,7 +6526,7 @@ test_write_wired_static_ip6_only_gw (gconstpointer user_data) g_assert (addr6); /* assert that the gateway was written and reloaded as expected */ - if (!gateway6 || !strcmp (gateway6, "::")) { + if (!gateway6) { g_assert (nm_setting_ip_config_get_gateway (s_ip6) == NULL); g_assert (written_ifcfg_gateway == NULL); } else { @@ -12551,6 +12672,7 @@ int main (int argc, char **argv) test_read_vlan_only_vlan_id (); test_read_vlan_only_device (); g_test_add_func (TPATH "vlan/physdev", test_read_vlan_physdev); + g_test_add_func (TPATH "wired/read-wake-on-lan", test_read_wired_wake_on_lan); test_write_wired_static (); test_write_wired_static_ip6_only (); @@ -12565,6 +12687,7 @@ int main (int argc, char **argv) test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_BLOB, NM_SETTING_SECRET_FLAG_NONE); test_write_wired_aliases (); g_test_add_func (TPATH "ipv4/write-static-addresses-GATEWAY", test_write_gateway); + g_test_add_func (TPATH "wired/write-wake-on-lan", test_write_wired_wake_on_lan); test_write_wifi_open (); test_write_wifi_open_hex_ssid (); test_write_wifi_wep (); diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c index 52bf51d1..69b7d64a 100644 --- a/src/settings/plugins/ifcfg-rh/writer.c +++ b/src/settings/plugins/ifcfg-rh/writer.c @@ -42,6 +42,8 @@ #include <nm-setting-team-port.h> #include "nm-core-internal.h" #include <nm-utils.h> +#include "nm-core-internal.h" +#include "nm-macros-internal.h" #include "nm-logging.h" #include "gsystem-local-alloc.h" @@ -1048,6 +1050,8 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) const char *const *s390_subchannels; GString *str; const char * const *macaddr_blacklist; + NMSettingWiredWakeOnLan wol; + const char *wol_password; s_wired = nm_connection_get_setting_wired (connection); if (!s_wired) { @@ -1131,6 +1135,37 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) g_string_free (str, TRUE); } + wol = nm_setting_wired_get_wake_on_lan (s_wired); + wol_password = nm_setting_wired_get_wake_on_lan_password (s_wired); + if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT) + svSetValue (ifcfg, "ETHTOOL_OPTS", NULL, FALSE); + else { + str = g_string_sized_new (30); + g_string_append (str, "wol "); + + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY)) + g_string_append (str, "p"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST)) + g_string_append (str, "u"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST)) + g_string_append (str, "m"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST)) + g_string_append (str, "b"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ARP)) + g_string_append (str, "a"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) + g_string_append (str, "g"); + + if (!NM_FLAGS_ANY (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ALL)) + g_string_append (str, "d"); + + if (wol_password && NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) + g_string_append_printf (str, "s sopass %s", wol_password); + + svSetValue (ifcfg, "ETHTOOL_OPTS", str->str, FALSE); + g_string_free (str, TRUE); + } + svSetValue (ifcfg, "TYPE", TYPE_ETHERNET, FALSE); return TRUE; @@ -1159,11 +1194,42 @@ vlan_priority_maplist_to_stringlist (NMSettingVlan *s_vlan, NMVlanPriorityMap ma } static gboolean +write_wired_for_virtual (NMConnection *connection, shvarFile *ifcfg) +{ + NMSettingWired *s_wired; + gboolean has_wired = FALSE; + + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + const char *device_mac, *cloned_mac; + char *tmp; + guint32 mtu; + + has_wired = TRUE; + + device_mac = nm_setting_wired_get_mac_address (s_wired); + if (device_mac) + svSetValue (ifcfg, "HWADDR", device_mac, FALSE); + + cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); + if (cloned_mac) + svSetValue (ifcfg, "MACADDR", cloned_mac, FALSE); + + mtu = nm_setting_wired_get_mtu (s_wired); + if (mtu) { + tmp = g_strdup_printf ("%u", mtu); + svSetValue (ifcfg, "MTU", tmp, FALSE); + g_free (tmp); + } + } + return has_wired; +} + +static gboolean write_vlan_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, GError **error) { NMSettingVlan *s_vlan; NMSettingConnection *s_con; - NMSettingWired *s_wired; char *tmp; guint32 vlan_flags = 0; @@ -1217,34 +1283,13 @@ write_vlan_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, svSetValue (ifcfg, "MACADDR", NULL, FALSE); svSetValue (ifcfg, "MTU", NULL, FALSE); - s_wired = nm_connection_get_setting_wired (connection); - if (s_wired) { - const char *device_mac, *cloned_mac; - guint32 mtu; - - *wired = TRUE; - - device_mac = nm_setting_wired_get_mac_address (s_wired); - if (device_mac) - svSetValue (ifcfg, "HWADDR", device_mac, FALSE); - - cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - if (cloned_mac) - svSetValue (ifcfg, "MACADDR", cloned_mac, FALSE); - - mtu = nm_setting_wired_get_mtu (s_wired); - if (mtu) { - tmp = g_strdup_printf ("%u", mtu); - svSetValue (ifcfg, "MTU", tmp, FALSE); - g_free (tmp); - } - } + *wired = write_wired_for_virtual (connection, ifcfg); return TRUE; } static gboolean -write_bonding_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) +write_bonding_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, GError **error) { NMSettingBond *s_bond; const char *iface; @@ -1292,11 +1337,13 @@ write_bonding_setting (NMConnection *connection, shvarFile *ifcfg, GError **erro svSetValue (ifcfg, "TYPE", TYPE_BOND, FALSE); svSetValue (ifcfg, "BONDING_MASTER", "yes", FALSE); + *wired = write_wired_for_virtual (connection, ifcfg); + return TRUE; } static gboolean -write_team_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) +write_team_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, GError **error) { NMSettingTeam *s_team; const char *iface; @@ -1321,6 +1368,8 @@ write_team_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) svSetValue (ifcfg, "TEAM_CONFIG", config, FALSE); svSetValue (ifcfg, "DEVICETYPE", TYPE_TEAM, FALSE); + *wired = write_wired_for_virtual (connection, ifcfg); + return TRUE; } @@ -1764,6 +1813,17 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) svSetValue (ifcfg, "GATEWAY_PING_TIMEOUT", tmp, FALSE); g_free (tmp); } + + switch (nm_setting_connection_get_metered (s_con)) { + case NM_METERED_YES: + svSetValue (ifcfg, "CONNECTION_METERED", "yes", FALSE); + break; + case NM_METERED_NO: + svSetValue (ifcfg, "CONNECTION_METERED", "no", FALSE); + break; + default: + svSetValue (ifcfg, "CONNECTION_METERED", NULL, FALSE); + } } static gboolean @@ -2564,10 +2624,10 @@ write_connection (NMConnection *connection, if (!write_infiniband_setting (connection, ifcfg, error)) goto out; } else if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME)) { - if (!write_bonding_setting (connection, ifcfg, error)) + if (!write_bonding_setting (connection, ifcfg, &wired, error)) goto out; } else if (!strcmp (type, NM_SETTING_TEAM_SETTING_NAME)) { - if (!write_team_setting (connection, ifcfg, error)) + if (!write_team_setting (connection, ifcfg, &wired, error)) goto out; } else if (!strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME)) { if (!write_bridge_setting (connection, ifcfg, error)) diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c index b78a24d0..c4c725c1 100644 --- a/src/supplicant-manager/nm-supplicant-config.c +++ b/src/supplicant-manager/nm-supplicant-config.c @@ -308,12 +308,32 @@ nm_supplicant_config_get_blobs (NMSupplicantConfig * self) return NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->blobs; } -#define TWO_GHZ_FREQS "2412,2417,2422,2427,2432,2437,2442,2447,2452,2457,2462,2467,2472,2484" -#define FIVE_GHZ_FREQS "4915,4920,4925,4935,4940,4945,4960,4980,5035,5040,5045,5055,5060,5080," \ - "5170,5180,5190,5200,5210,5220,5230,5240,5260,5280,5300,5320,5500," \ - "5520,5540,5560,5580,5600,5620,5640,5660,5680,5700,5745,5765,5785," \ - "5805,5825" - +static const char * +wifi_freqs_to_string (gboolean bg_band) +{ + static const char *str_2ghz = NULL; + static const char *str_5ghz = NULL; + const char *str; + + str = bg_band ? str_2ghz : str_5ghz; + + if (G_UNLIKELY (str == NULL)) { + GString *tmp; + const guint *freqs; + int i; + + freqs = bg_band ? nm_utils_wifi_2ghz_freqs () : nm_utils_wifi_5ghz_freqs (); + tmp = g_string_sized_new (bg_band ? 70 : 225); + for (i = 0; freqs[i]; i++) + g_string_append_printf (tmp, i == 0 ? "%d" : " %d", freqs[i]); + str = g_string_free (tmp, FALSE); + if (bg_band) + str_2ghz = str; + else + str_5ghz = str; + } + return str; +} gboolean nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self, @@ -323,6 +343,7 @@ nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self, NMSupplicantConfigPrivate *priv; gboolean is_adhoc, is_ap; const char *mode, *band; + guint32 channel; GBytes *ssid; const char *bssid; @@ -393,22 +414,35 @@ nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self, } band = nm_setting_wireless_get_band (setting); + channel = nm_setting_wireless_get_channel (setting); if (band) { - const char *freqs = NULL; + if (channel) { + guint32 freq; + char *str_freq; + + freq = nm_utils_wifi_channel_to_freq (channel, band); + str_freq = g_strdup_printf ("%u", freq); + if (!nm_supplicant_config_add_option (self, "freq_list", str_freq, -1, FALSE)) { + g_free (str_freq); + nm_log_warn (LOGD_SUPPLICANT, "Error adding frequency list to supplicant config."); + return FALSE; + } + g_free (str_freq); + } else { + const char *freqs = NULL; - if (!strcmp (band, "a")) - freqs = FIVE_GHZ_FREQS; - else if (!strcmp (band, "bg")) - freqs = TWO_GHZ_FREQS; + if (!strcmp (band, "a")) + freqs = wifi_freqs_to_string (FALSE); + else if (!strcmp (band, "bg")) + freqs = wifi_freqs_to_string (TRUE); - if (freqs && !nm_supplicant_config_add_option (self, "freq_list", freqs, strlen (freqs), FALSE)) { - nm_log_warn (LOGD_SUPPLICANT, "Error adding frequency list/band to supplicant config."); - return FALSE; + if (freqs && !nm_supplicant_config_add_option (self, "freq_list", freqs, strlen (freqs), FALSE)) { + nm_log_warn (LOGD_SUPPLICANT, "Error adding frequency list/band to supplicant config."); + return FALSE; + } } } - // FIXME: channel config item - return TRUE; } diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index e9775a19..66bab2e3 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -1093,8 +1093,14 @@ scan_request_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; - if (error) - nm_log_warn (LOGD_SUPPLICANT, "Could not get scan request result: %s", error->message); + if (error) { + if (_nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.Interface.ScanError")) + nm_log_dbg (LOGD_SUPPLICANT, "Could not get scan request result: %s", error->message); + else { + g_dbus_error_strip_remote_error (error); + nm_log_warn (LOGD_SUPPLICANT, "Could not get scan request result: %s", error->message); + } + } g_signal_emit (NM_SUPPLICANT_INTERFACE (user_data), signals[SCAN_DONE], 0, error ? FALSE : TRUE); } diff --git a/src/tests/config/nm-test-device.c b/src/tests/config/nm-test-device.c index b5f65ded..681f4966 100644 --- a/src/tests/config/nm-test-device.c +++ b/src/tests/config/nm-test-device.c @@ -26,10 +26,10 @@ #include "nm-device-private.h" #include "nm-utils.h" -static GObjectClass *g_object_class; - G_DEFINE_TYPE (NMTestDevice, nm_test_device, NM_TYPE_DEVICE) +#define PARENT_CLASS (G_OBJECT_CLASS (g_type_class_peek_parent (nm_test_device_parent_class))) + static void nm_test_device_init (NMTestDevice *self) { @@ -44,21 +44,21 @@ constructor (GType type, guint n_construct_params, GObjectConstructParam *construct_params) { - return g_object_class->constructor (type, - n_construct_params, - construct_params); + return PARENT_CLASS->constructor (type, + n_construct_params, + construct_params); } static void constructed (GObject *object) { - g_object_class->constructed (object); + PARENT_CLASS->constructed (object); } static void dispose (GObject *object) { - g_object_class->dispose (object); + PARENT_CLASS->dispose (object); } static NMDeviceCapabilities @@ -73,8 +73,6 @@ nm_test_device_class_init (NMTestDeviceClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - g_object_class = g_type_class_peek (G_TYPE_OBJECT); - object_class->constructor = constructor; object_class->constructed = constructed; object_class->dispose = dispose; diff --git a/src/tests/test-general-with-expect.c b/src/tests/test-general-with-expect.c index bb52bde2..fe76e3fa 100644 --- a/src/tests/test-general-with-expect.c +++ b/src/tests/test-general-with-expect.c @@ -35,6 +35,42 @@ /*******************************************/ +static void +test_nm_utils_monotonic_timestamp_as_boottime (void) +{ + gint64 timestamp_ns_per_tick, now, now_boottime, now_boottime_2, now_boottime_3; + struct timespec tp; + clockid_t clockid; + guint i; + + if (clock_gettime (CLOCK_BOOTTIME, &tp) != 0 && errno == EINVAL) + clockid = CLOCK_MONOTONIC; + else + clockid = CLOCK_BOOTTIME; + + for (i = 0; i < 10; i++) { + + if (clock_gettime (clockid, &tp) != 0) + g_assert_not_reached (); + now_boottime = ( ((gint64) tp.tv_sec) * NM_UTILS_NS_PER_SECOND ) + ((gint64) tp.tv_nsec); + + now = nm_utils_get_monotonic_timestamp_ns (); + + now_boottime_2 = nm_utils_monotonic_timestamp_as_boottime (now, 1); + g_assert_cmpint (now_boottime_2, >=, 0); + g_assert_cmpint (now_boottime_2, >=, now_boottime); + g_assert_cmpint (now_boottime_2 - now_boottime, <=, NM_UTILS_NS_PER_SECOND / 1000); + + for (timestamp_ns_per_tick = 1; timestamp_ns_per_tick <= NM_UTILS_NS_PER_SECOND; timestamp_ns_per_tick *= 10) { + now_boottime_3 = nm_utils_monotonic_timestamp_as_boottime (now / timestamp_ns_per_tick, timestamp_ns_per_tick); + + g_assert_cmpint (now_boottime_2 / timestamp_ns_per_tick, ==, now_boottime_3); + } + } +} + +/*******************************************/ + struct test_nm_utils_kill_child_async_data { GMainLoop *loop; @@ -385,7 +421,7 @@ _remove_at_indexes_init_random_idx (GArray *idx, guint array_len, guint idx_len) } static void -test_nm_utils_array_remove_at_indexes () +test_nm_utils_array_remove_at_indexes (void) { gs_unref_array GArray *idx = NULL, *array = NULL; gs_unref_hashtable GHashTable *unique = NULL; @@ -822,6 +858,7 @@ main (int argc, char **argv) { nmtst_init_assert_logging (&argc, &argv, "DEBUG", "DEFAULT"); + g_test_add_func ("/general/nm_utils_monotonic_timestamp_as_boottime", test_nm_utils_monotonic_timestamp_as_boottime); g_test_add_func ("/general/nm_utils_kill_child", test_nm_utils_kill_child); g_test_add_func ("/general/nm_ethernet_address_is_valid", test_nm_ethernet_address_is_valid); g_test_add_func ("/general/nm_multi_index", test_nm_multi_index); diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c index c8bdc75f..235cfd42 100644 --- a/src/tests/test-ip4-config.c +++ b/src/tests/test-ip4-config.c @@ -316,12 +316,12 @@ test_merge_subtract_mss_mtu (void) nm_ip4_config_set_mss (cfg3, expected_mss3); nm_ip4_config_set_mtu (cfg3, expected_mtu3, NM_IP_CONFIG_SOURCE_UNKNOWN); - nm_ip4_config_merge (cfg1, cfg2); + nm_ip4_config_merge (cfg1, cfg2, NM_IP_CONFIG_MERGE_DEFAULT); /* ensure MSS and MTU are in cfg1 */ g_assert_cmpuint (nm_ip4_config_get_mss (cfg1), ==, expected_mss2); g_assert_cmpuint (nm_ip4_config_get_mtu (cfg1), ==, expected_mtu2); - nm_ip4_config_merge (cfg1, cfg3); + nm_ip4_config_merge (cfg1, cfg3, NM_IP_CONFIG_MERGE_DEFAULT); /* ensure again the MSS and MTU in cfg1 got overriden */ g_assert_cmpuint (nm_ip4_config_get_mss (cfg1), ==, expected_mss3); g_assert_cmpuint (nm_ip4_config_get_mtu (cfg1), ==, expected_mtu3); diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c index 0164930d..9046bf88 100644 --- a/src/tests/test-route-manager.c +++ b/src/tests/test-route-manager.c @@ -377,7 +377,7 @@ setup_dev0_ip6 (int ifindex) /* Add an address so that a route to the gateway below gets added. */ nm_platform_ip6_address_add (NM_PLATFORM_GET, ifindex, - *nmtst_inet6_from_string ("2001:db8:8086::2"), + *nmtst_inet6_from_string ("2001:db8:8086::666"), in6addr_any, 64, 3600, diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 795a8187..c34155ef 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -932,11 +932,11 @@ apply_parent_device_config (NMVpnConnection *connection) * vpn-config. Instead we tell NMDefaultRouteManager directly about the * default route. */ if (vpn4_parent_config) { - nm_ip4_config_merge (vpn4_parent_config, priv->ip4_config); + nm_ip4_config_merge (vpn4_parent_config, priv->ip4_config, NM_IP_CONFIG_MERGE_DEFAULT); nm_ip4_config_set_gateway (vpn4_parent_config, 0); } if (vpn6_parent_config) { - nm_ip6_config_merge (vpn6_parent_config, priv->ip6_config); + nm_ip6_config_merge (vpn6_parent_config, priv->ip6_config, NM_IP_CONFIG_MERGE_DEFAULT); nm_ip6_config_set_gateway (vpn6_parent_config, NULL); } } |