From ee9c73a923909e23a649407be77e25235d769e25 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Fri, 11 May 2018 22:08:45 +0200 Subject: New upstream version 1.10.8 --- src/devices/wwan/nm-modem.c | 294 +++++++++++++++----------------------------- 1 file changed, 101 insertions(+), 193 deletions(-) (limited to 'src/devices/wwan/nm-modem.c') diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 61b7247e..010a2b60 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -44,10 +44,13 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMModem, PROP_CONTROL_PORT, - PROP_IP_IFINDEX, + PROP_DATA_PORT, PROP_PATH, PROP_UID, PROP_DRIVER, + PROP_IP4_METHOD, + PROP_IP6_METHOD, + PROP_IP_TIMEOUT, PROP_STATE, PROP_DEVICE_ID, PROP_SIM_ID, @@ -76,12 +79,7 @@ typedef struct _NMModemPrivate { char *driver; char *control_port; char *data_port; - - /* TODO: ip_iface is solely used for nm_modem_owns_port(). - * We should rework the code that it's not necessary */ - char *ip_iface; - - int ip_ifindex; + char *ppp_iface; NMModemIPMethod ip4_method; NMModemIPMethod ip6_method; NMUtilsIPv6IfaceId iid; @@ -98,7 +96,7 @@ typedef struct _NMModemPrivate { guint32 secrets_tries; NMActRequestGetSecretsCallId *secrets_id; - guint mm_ip_timeout; + guint32 mm_ip_timeout; guint32 ip4_route_table; guint32 ip4_route_metric; @@ -154,10 +152,6 @@ _nmlog_prefix (char *prefix, NMModem *self) _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ } G_STMT_END -/*****************************************************************************/ - -static void _set_ip_ifindex (NMModem *self, int ifindex, const char *ifname); - /*****************************************************************************/ /* State/enabled/connected */ @@ -456,28 +450,20 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ } static void -ppp_ifindex_set (NMPPPManager *ppp_manager, - int ifindex, - const char *iface, - gpointer user_data) +set_data_port (NMModem *self, const char *new_data_port) { - NMModem *self = NM_MODEM (user_data); - - nm_assert (ifindex >= 0); - nm_assert (NM_MODEM_GET_PRIVATE (self)->ppp_manager == ppp_manager); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - if (ifindex <= 0 && iface) { - /* this might happen, if the ifname was already deleted - * and we failed to resolve ifindex. - * - * Forget about the name. */ - iface = NULL; + if (g_strcmp0 (priv->data_port, new_data_port) != 0) { + g_free (priv->data_port); + priv->data_port = g_strdup (new_data_port); + _notify (self, PROP_DATA_PORT); } - _set_ip_ifindex (self, ifindex, iface); } static void ppp_ip4_config (NMPPPManager *ppp_manager, + const char *iface, NMIP4Config *config, gpointer user_data) { @@ -489,6 +475,9 @@ ppp_ip4_config (NMPPPManager *ppp_manager, guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */ gboolean dns_workaround = FALSE; + /* Notify about the new data port to use */ + set_data_port (self, iface); + /* Work around a PPP bug (#1732) which causes many mobile broadband * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers. * Apparently fixed in ppp-2.4.5 but we've had some reports that this is @@ -530,12 +519,16 @@ ppp_ip4_config (NMPPPManager *ppp_manager, static void ppp_ip6_config (NMPPPManager *ppp_manager, + const char *iface, const NMUtilsIPv6IfaceId *iid, NMIP6Config *config, gpointer user_data) { NMModem *self = NM_MODEM (user_data); + /* Notify about the new data port to use */ + set_data_port (self, iface); + NM_MODEM_GET_PRIVATE (self)->iid = *iid; nm_modem_emit_ip6_config_result (self, config, NULL); @@ -564,18 +557,6 @@ port_speed_is_zero (const char *port) { struct termios options; nm_auto_close int fd = -1; - gs_free char *path = NULL; - - nm_assert (port); - - if (port[0] != '/') { - if ( !port[0] - || strchr (port, '/') - || NM_IN_STRSET (port, ".", "..")) - return FALSE; - path = g_build_path ("/sys/class/tty", port, NULL); - port = path; - } fd = open (port, O_RDWR | O_NONBLOCK | O_NOCTTY | O_CLOEXEC); if (fd < 0) @@ -617,12 +598,6 @@ ppp_stage3_ip_config_start (NMModem *self, return NM_ACT_STAGE_RETURN_FAILURE; } - if (!priv->data_port) { - _LOGE ("error starting PPP (no data port)"); - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; - } - /* Check if ModemManager requested a specific IP timeout to be used. If 0 reported, * use the default one (30s) */ if (priv->mm_ip_timeout > 0) { @@ -654,7 +629,9 @@ ppp_stage3_ip_config_start (NMModem *self, ip_timeout, baud_override, &error)) { _LOGE ("error starting PPP: %s", error->message); g_error_free (error); + g_clear_object (&priv->ppp_manager); + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } @@ -662,9 +639,6 @@ ppp_stage3_ip_config_start (NMModem *self, g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, G_CALLBACK (ppp_state_changed), self); - g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, - G_CALLBACK (ppp_ifindex_set), - self); g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, G_CALLBACK (ppp_ip4_config), self); @@ -1091,20 +1065,12 @@ nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection) gboolean nm_modem_complete_connection (NMModem *self, NMConnection *connection, - NMConnection *const*existing_connections, + const GSList *existing_connections, GError **error) { - NMModemClass *klass; - - klass = NM_MODEM_GET_CLASS (self); - if (!klass->complete_connection) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, - "Modem class %s had no complete_connection method", - G_OBJECT_TYPE_NAME (self)); - return FALSE; - } - - return klass->complete_connection (self, connection, existing_connections, error); + if (NM_MODEM_GET_CLASS (self)->complete_connection) + return NM_MODEM_GET_CLASS (self)->complete_connection (self, connection, existing_connections, error); + return FALSE; } /*****************************************************************************/ @@ -1129,10 +1095,7 @@ deactivate_cleanup (NMModem *self, NMDevice *device) priv->in_bytes = priv->out_bytes = 0; - if (priv->ppp_manager) { - g_signal_handlers_disconnect_by_data (priv->ppp_manager, self); - g_clear_object (&priv->ppp_manager); - } + g_clear_object (&priv->ppp_manager); if (device) { g_return_if_fail (NM_IS_DEVICE (device)); @@ -1151,12 +1114,11 @@ deactivate_cleanup (NMModem *self, NMDevice *device) } } } - - nm_clear_g_free (&priv->data_port); - priv->mm_ip_timeout = 0; priv->ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; priv->ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; - _set_ip_ifindex (self, -1, NULL); + + g_free (priv->ppp_iface); + priv->ppp_iface = NULL; } /*****************************************************************************/ @@ -1407,117 +1369,17 @@ nm_modem_get_control_port (NMModem *self) return NM_MODEM_GET_PRIVATE (self)->control_port; } -int -nm_modem_get_ip_ifindex (NMModem *self) -{ - NMModemPrivate *priv; - - g_return_val_if_fail (NM_IS_MODEM (self), 0); - - priv = NM_MODEM_GET_PRIVATE (self); - - /* internally we track an unset ip_ifindex as -1. - * For the caller of nm_modem_get_ip_ifindex(), this - * shall be zero too. */ - return priv->ip_ifindex != -1 ? priv->ip_ifindex : 0; -} - -static void -_set_ip_ifindex (NMModem *self, int ifindex, const char *ifname) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - - nm_assert (ifindex >= -1); - nm_assert ((ifindex > 0) == !!ifname); - - if (!nm_streq0 (priv->ip_iface, ifname)) { - g_free (priv->ip_iface); - priv->ip_iface = g_strdup (ifname); - } - - if (priv->ip_ifindex != ifindex) { - priv->ip_ifindex = ifindex; - _notify (self, PROP_IP_IFINDEX); - } -} - -gboolean -nm_modem_set_data_port (NMModem *self, - NMPlatform *platform, - const char *data_port, - NMModemIPMethod ip4_method, - NMModemIPMethod ip6_method, - guint timeout, - GError **error) +const char * +nm_modem_get_data_port (NMModem *self) { - NMModemPrivate *priv; - gboolean is_ppp; - int ifindex = -1; - - g_return_val_if_fail (NM_IS_MODEM (self), FALSE); - g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE); - g_return_val_if_fail (!error || !*error, FALSE); - - priv = NM_MODEM_GET_PRIVATE (self); - - if ( priv->ppp_manager - || priv->data_port - || priv->ip_ifindex != -1) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "cannot set data port in activated state"); - /* this really shouldn't happen. Assert. */ - g_return_val_if_reached (FALSE); - } - - if (!data_port) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "missing data port"); - return FALSE; - } - - is_ppp = (ip4_method == NM_MODEM_IP_METHOD_PPP) - || (ip6_method == NM_MODEM_IP_METHOD_PPP); - if (is_ppp) { - if ( !NM_IN_SET (ip4_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_PPP) - || !NM_IN_SET (ip6_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_PPP)) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "conflicting ip methods"); - return FALSE; - } - } else if ( !NM_IN_SET (ip4_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_STATIC, NM_MODEM_IP_METHOD_AUTO) - || !NM_IN_SET (ip6_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_STATIC, NM_MODEM_IP_METHOD_AUTO) - || ( ip4_method == NM_MODEM_IP_METHOD_UNKNOWN - && ip6_method == NM_MODEM_IP_METHOD_UNKNOWN)) { - g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "invalid ip methods"); - return FALSE; - } - - if (!is_ppp) { - ifindex = nm_platform_if_nametoindex (platform, data_port); - if (ifindex <= 0) { - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "cannot find network interface %s", data_port); - return FALSE; - } - if (!nm_platform_process_events_ensure_link (platform, ifindex, data_port)) { - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, - "cannot find network interface %s in platform cache", data_port); - return FALSE; - } - } + g_return_val_if_fail (NM_IS_MODEM (self), NULL); - priv->mm_ip_timeout = timeout; - priv->ip4_method = ip4_method; - priv->ip6_method = ip6_method; - if (is_ppp) { - priv->data_port = g_strdup (data_port); - _set_ip_ifindex (self, -1, NULL); - } else { - priv->data_port = NULL; - _set_ip_ifindex (self, ifindex, data_port); - } - return TRUE; + /* The ppp_iface takes precedence over the data interface when PPP is used, + * since data_iface is the TTY over which PPP is run, and that TTY can't + * do IP. The caller really wants the thing that's doing IP. + */ + return NM_MODEM_GET_PRIVATE (self)->ppp_iface ? + NM_MODEM_GET_PRIVATE (self)->ppp_iface : NM_MODEM_GET_PRIVATE (self)->data_port; } gboolean @@ -1530,10 +1392,15 @@ nm_modem_owns_port (NMModem *self, const char *iface) if (NM_MODEM_GET_CLASS (self)->owns_port) return NM_MODEM_GET_CLASS (self)->owns_port (self, iface); - return NM_IN_STRSET (iface, - priv->ip_iface, - priv->data_port, - priv->control_port); + /* Fall back to data/control ports */ + if (priv->ppp_iface && (strcmp (priv->ppp_iface, iface) == 0)) + return TRUE; + if (priv->data_port && (strcmp (priv->data_port, iface) == 0)) + return TRUE; + if (priv->control_port && (strcmp (priv->control_port, iface) == 0)) + return TRUE; + + return FALSE; } gboolean @@ -1633,8 +1500,7 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMModem *self = NM_MODEM (object); - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE ((NMModem *) object); switch (prop_id) { case PROP_PATH: @@ -1646,12 +1512,21 @@ get_property (GObject *object, guint prop_id, case PROP_CONTROL_PORT: g_value_set_string (value, priv->control_port); break; - case PROP_IP_IFINDEX: - g_value_set_int (value, nm_modem_get_ip_ifindex (self)); + case PROP_DATA_PORT: + g_value_set_string (value, nm_modem_get_data_port (NM_MODEM (object))); break; case PROP_UID: g_value_set_string (value, priv->uid); break; + case PROP_IP4_METHOD: + g_value_set_uint (value, priv->ip4_method); + break; + case PROP_IP6_METHOD: + g_value_set_uint (value, priv->ip6_method); + break; + case PROP_IP_TIMEOUT: + g_value_set_uint (value, priv->mm_ip_timeout); + break; case PROP_STATE: g_value_set_int (value, priv->state); break; @@ -1694,10 +1569,23 @@ set_property (GObject *object, guint prop_id, /* construct-only */ priv->control_port = g_value_dup_string (value); break; + case PROP_DATA_PORT: + g_free (priv->data_port); + priv->data_port = g_value_dup_string (value); + break; case PROP_UID: /* construct-only */ priv->uid = g_value_dup_string (value); break; + case PROP_IP4_METHOD: + priv->ip4_method = g_value_get_uint (value); + break; + case PROP_IP6_METHOD: + priv->ip6_method = g_value_get_uint (value); + break; + case PROP_IP_TIMEOUT: + priv->mm_ip_timeout = g_value_get_uint (value); + break; case PROP_STATE: /* construct-only */ priv->state = g_value_get_int (value); @@ -1735,7 +1623,6 @@ nm_modem_init (NMModem *self) self->_priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_MODEM, NMModemPrivate); priv = self->_priv; - priv->ip_ifindex = -1; priv->ip4_route_table = RT_TABLE_MAIN; priv->ip4_route_metric = 700; priv->ip6_route_table = RT_TABLE_MAIN; @@ -1751,7 +1638,7 @@ constructed (GObject *object) priv = NM_MODEM_GET_PRIVATE (NM_MODEM (object)); - g_return_if_fail (priv->control_port); + g_return_if_fail (priv->data_port || priv->control_port); } /*****************************************************************************/ @@ -1776,7 +1663,6 @@ finalize (GObject *object) g_free (priv->driver); g_free (priv->control_port); g_free (priv->data_port); - g_free (priv->ip_iface); g_free (priv->device_id); g_free (priv->sim_id); g_free (priv->sim_operator_id); @@ -1825,11 +1711,33 @@ nm_modem_class_init (NMModemClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_IP_IFINDEX] = - g_param_spec_int (NM_MODEM_IP_IFINDEX, "", "", - 0, G_MAXINT, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DATA_PORT] = + g_param_spec_string (NM_MODEM_DATA_PORT, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IP4_METHOD] = + g_param_spec_uint (NM_MODEM_IP4_METHOD, "", "", + NM_MODEM_IP_METHOD_UNKNOWN, + NM_MODEM_IP_METHOD_AUTO, + NM_MODEM_IP_METHOD_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IP6_METHOD] = + g_param_spec_uint (NM_MODEM_IP6_METHOD, "", "", + NM_MODEM_IP_METHOD_UNKNOWN, + NM_MODEM_IP_METHOD_AUTO, + NM_MODEM_IP_METHOD_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IP_TIMEOUT] = + g_param_spec_uint (NM_MODEM_IP_TIMEOUT, "", "", + 0, 360, 20, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_STATE] = g_param_spec_int (NM_MODEM_STATE, "", "", -- cgit 1.3.0-6-gf8a5 From 04bc9e1cd3544445d883ad29ea108c1645c8e7b7 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Mon, 4 Jun 2018 00:07:45 +0200 Subject: New upstream version 1.11.4 --- src/devices/wwan/nm-modem.c | 356 +++++++++++++++++++++++++++++--------------- 1 file changed, 238 insertions(+), 118 deletions(-) (limited to 'src/devices/wwan/nm-modem.c') diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 010a2b60..fbe99cc3 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -44,13 +44,10 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMModem, PROP_CONTROL_PORT, - PROP_DATA_PORT, + PROP_IP_IFINDEX, PROP_PATH, PROP_UID, PROP_DRIVER, - PROP_IP4_METHOD, - PROP_IP6_METHOD, - PROP_IP_TIMEOUT, PROP_STATE, PROP_DEVICE_ID, PROP_SIM_ID, @@ -79,7 +76,12 @@ typedef struct _NMModemPrivate { char *driver; char *control_port; char *data_port; - char *ppp_iface; + + /* TODO: ip_iface is solely used for nm_modem_owns_port(). + * We should rework the code that it's not necessary */ + char *ip_iface; + + int ip_ifindex; NMModemIPMethod ip4_method; NMModemIPMethod ip6_method; NMUtilsIPv6IfaceId iid; @@ -96,7 +98,7 @@ typedef struct _NMModemPrivate { guint32 secrets_tries; NMActRequestGetSecretsCallId *secrets_id; - guint32 mm_ip_timeout; + guint mm_ip_timeout; guint32 ip4_route_table; guint32 ip4_route_metric; @@ -152,6 +154,10 @@ _nmlog_prefix (char *prefix, NMModem *self) _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ } G_STMT_END +/*****************************************************************************/ + +static void _set_ip_ifindex (NMModem *self, int ifindex, const char *ifname); + /*****************************************************************************/ /* State/enabled/connected */ @@ -199,7 +205,7 @@ nm_modem_set_state (NMModem *self, _LOGI ("modem state changed, '%s' --> '%s' (reason: %s)", nm_modem_state_to_string (old_state), nm_modem_state_to_string (new_state), - reason ? reason : "none"); + reason ?: "none"); priv->state = new_state; _notify (self, PROP_STATE); @@ -450,20 +456,28 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ } static void -set_data_port (NMModem *self, const char *new_data_port) +ppp_ifindex_set (NMPPPManager *ppp_manager, + int ifindex, + const char *iface, + gpointer user_data) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMModem *self = NM_MODEM (user_data); + + nm_assert (ifindex >= 0); + nm_assert (NM_MODEM_GET_PRIVATE (self)->ppp_manager == ppp_manager); - if (g_strcmp0 (priv->data_port, new_data_port) != 0) { - g_free (priv->data_port); - priv->data_port = g_strdup (new_data_port); - _notify (self, PROP_DATA_PORT); + if (ifindex <= 0 && iface) { + /* this might happen, if the ifname was already deleted + * and we failed to resolve ifindex. + * + * Forget about the name. */ + iface = NULL; } + _set_ip_ifindex (self, ifindex, iface); } static void ppp_ip4_config (NMPPPManager *ppp_manager, - const char *iface, NMIP4Config *config, gpointer user_data) { @@ -475,9 +489,6 @@ ppp_ip4_config (NMPPPManager *ppp_manager, guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */ gboolean dns_workaround = FALSE; - /* Notify about the new data port to use */ - set_data_port (self, iface); - /* Work around a PPP bug (#1732) which causes many mobile broadband * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers. * Apparently fixed in ppp-2.4.5 but we've had some reports that this is @@ -519,16 +530,12 @@ ppp_ip4_config (NMPPPManager *ppp_manager, static void ppp_ip6_config (NMPPPManager *ppp_manager, - const char *iface, const NMUtilsIPv6IfaceId *iid, NMIP6Config *config, gpointer user_data) { NMModem *self = NM_MODEM (user_data); - /* Notify about the new data port to use */ - set_data_port (self, iface); - NM_MODEM_GET_PRIVATE (self)->iid = *iid; nm_modem_emit_ip6_config_result (self, config, NULL); @@ -557,6 +564,18 @@ port_speed_is_zero (const char *port) { struct termios options; nm_auto_close int fd = -1; + gs_free char *path = NULL; + + nm_assert (port); + + if (port[0] != '/') { + if ( !port[0] + || strchr (port, '/') + || NM_IN_STRSET (port, ".", "..")) + return FALSE; + path = g_build_path ("/sys/class/tty", port, NULL); + port = path; + } fd = open (port, O_RDWR | O_NONBLOCK | O_NOCTTY | O_CLOEXEC); if (fd < 0) @@ -598,6 +617,12 @@ ppp_stage3_ip_config_start (NMModem *self, return NM_ACT_STAGE_RETURN_FAILURE; } + if (!priv->data_port) { + _LOGE ("error starting PPP (no data port)"); + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + /* Check if ModemManager requested a specific IP timeout to be used. If 0 reported, * use the default one (30s) */ if (priv->mm_ip_timeout > 0) { @@ -629,9 +654,7 @@ ppp_stage3_ip_config_start (NMModem *self, ip_timeout, baud_override, &error)) { _LOGE ("error starting PPP: %s", error->message); g_error_free (error); - g_clear_object (&priv->ppp_manager); - NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); return NM_ACT_STAGE_RETURN_FAILURE; } @@ -639,6 +662,9 @@ ppp_stage3_ip_config_start (NMModem *self, g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, G_CALLBACK (ppp_state_changed), self); + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, + G_CALLBACK (ppp_ifindex_set), + self); g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, G_CALLBACK (ppp_ip4_config), self); @@ -1065,12 +1091,20 @@ nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection) gboolean nm_modem_complete_connection (NMModem *self, NMConnection *connection, - const GSList *existing_connections, + NMConnection *const*existing_connections, GError **error) { - if (NM_MODEM_GET_CLASS (self)->complete_connection) - return NM_MODEM_GET_CLASS (self)->complete_connection (self, connection, existing_connections, error); - return FALSE; + NMModemClass *klass; + + klass = NM_MODEM_GET_CLASS (self); + if (!klass->complete_connection) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + "Modem class %s had no complete_connection method", + G_OBJECT_TYPE_NAME (self)); + return FALSE; + } + + return klass->complete_connection (self, connection, existing_connections, error); } /*****************************************************************************/ @@ -1095,7 +1129,11 @@ deactivate_cleanup (NMModem *self, NMDevice *device) priv->in_bytes = priv->out_bytes = 0; - g_clear_object (&priv->ppp_manager); + if (priv->ppp_manager) { + g_signal_handlers_disconnect_by_data (priv->ppp_manager, self); + nm_ppp_manager_stop (priv->ppp_manager, NULL, NULL); + g_clear_object (&priv->ppp_manager); + } if (device) { g_return_if_fail (NM_IS_DEVICE (device)); @@ -1114,11 +1152,12 @@ deactivate_cleanup (NMModem *self, NMDevice *device) } } } + + nm_clear_g_free (&priv->data_port); + priv->mm_ip_timeout = 0; priv->ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; priv->ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; - - g_free (priv->ppp_iface); - priv->ppp_iface = NULL; + _set_ip_ifindex (self, -1, NULL); } /*****************************************************************************/ @@ -1138,11 +1177,19 @@ typedef struct { GSimpleAsyncResult *result; DeactivateContextStep step; NMPPPManager *ppp_manager; + NMPPPManagerStopHandle *ppp_stop_handle; + gulong ppp_stop_cancellable_id; } DeactivateContext; static void deactivate_context_complete (DeactivateContext *ctx) { + if (ctx->ppp_stop_handle) + nm_ppp_manager_stop_cancel (ctx->ppp_stop_handle); + + nm_assert (!ctx->ppp_stop_handle); + nm_assert (ctx->ppp_stop_cancellable_id == 0); + if (ctx->ppp_manager) g_object_unref (ctx->ppp_manager); if (ctx->cancellable) @@ -1184,25 +1231,36 @@ disconnect_ready (NMModem *self, static void ppp_manager_stop_ready (NMPPPManager *ppp_manager, - GAsyncResult *res, - DeactivateContext *ctx) + NMPPPManagerStopHandle *handle, + gboolean was_cancelled, + gpointer user_data) { - NMModem *self = ctx->self; - GError *error = NULL; + DeactivateContext *ctx = user_data; - if (!nm_ppp_manager_stop_finish (ppp_manager, res, &error)) { - _LOGW ("cannot stop PPP manager: %s", - error->message); - g_simple_async_result_take_error (ctx->result, error); - deactivate_context_complete (ctx); - return; + nm_assert (ctx->ppp_stop_handle == handle); + ctx->ppp_stop_handle = NULL; + + if (ctx->ppp_stop_cancellable_id) { + g_cancellable_disconnect (ctx->cancellable, + nm_steal_int (&ctx->ppp_stop_cancellable_id)); } - /* Go on */ + if (was_cancelled) + return; + ctx->step++; deactivate_step (ctx); } +static void +ppp_manager_stop_cancelled (GCancellable *cancellable, + gpointer user_data) +{ + DeactivateContext *ctx = user_data; + + nm_ppp_manager_stop_cancel (ctx->ppp_stop_handle); +} + static void deactivate_step (DeactivateContext *ctx) { @@ -1232,10 +1290,16 @@ deactivate_step (DeactivateContext *ctx) case DEACTIVATE_CONTEXT_STEP_PPP_MANAGER_STOP: /* If we have a PPP manager, stop it */ if (ctx->ppp_manager) { - nm_ppp_manager_stop_async (ctx->ppp_manager, - ctx->cancellable, - (GAsyncReadyCallback) ppp_manager_stop_ready, - ctx); + nm_assert (!ctx->ppp_stop_handle); + if (ctx->cancellable) { + ctx->ppp_stop_cancellable_id = g_cancellable_connect (ctx->cancellable, + G_CALLBACK (ppp_manager_stop_cancelled), + ctx, + NULL); + } + ctx->ppp_stop_handle = nm_ppp_manager_stop (ctx->ppp_manager, + ppp_manager_stop_ready, + ctx); return; } ctx->step++; @@ -1274,7 +1338,9 @@ nm_modem_deactivate_async (NMModem *self, callback, user_data, nm_modem_deactivate_async); - ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + /* FIXME(shutdown): we always require a cancellable, otherwise we cannot + * do a coordinated shutdown. */ + ctx->cancellable = nm_g_object_ref (cancellable); /* Start */ ctx->step = DEACTIVATE_CONTEXT_STEP_FIRST; @@ -1369,17 +1435,117 @@ nm_modem_get_control_port (NMModem *self) return NM_MODEM_GET_PRIVATE (self)->control_port; } -const char * -nm_modem_get_data_port (NMModem *self) +int +nm_modem_get_ip_ifindex (NMModem *self) { - g_return_val_if_fail (NM_IS_MODEM (self), NULL); + NMModemPrivate *priv; - /* The ppp_iface takes precedence over the data interface when PPP is used, - * since data_iface is the TTY over which PPP is run, and that TTY can't - * do IP. The caller really wants the thing that's doing IP. - */ - return NM_MODEM_GET_PRIVATE (self)->ppp_iface ? - NM_MODEM_GET_PRIVATE (self)->ppp_iface : NM_MODEM_GET_PRIVATE (self)->data_port; + g_return_val_if_fail (NM_IS_MODEM (self), 0); + + priv = NM_MODEM_GET_PRIVATE (self); + + /* internally we track an unset ip_ifindex as -1. + * For the caller of nm_modem_get_ip_ifindex(), this + * shall be zero too. */ + return priv->ip_ifindex != -1 ? priv->ip_ifindex : 0; +} + +static void +_set_ip_ifindex (NMModem *self, int ifindex, const char *ifname) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + nm_assert (ifindex >= -1); + nm_assert ((ifindex > 0) == !!ifname); + + if (!nm_streq0 (priv->ip_iface, ifname)) { + g_free (priv->ip_iface); + priv->ip_iface = g_strdup (ifname); + } + + if (priv->ip_ifindex != ifindex) { + priv->ip_ifindex = ifindex; + _notify (self, PROP_IP_IFINDEX); + } +} + +gboolean +nm_modem_set_data_port (NMModem *self, + NMPlatform *platform, + const char *data_port, + NMModemIPMethod ip4_method, + NMModemIPMethod ip6_method, + guint timeout, + GError **error) +{ + NMModemPrivate *priv; + gboolean is_ppp; + int ifindex = -1; + + g_return_val_if_fail (NM_IS_MODEM (self), FALSE); + g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE); + g_return_val_if_fail (!error || !*error, FALSE); + + priv = NM_MODEM_GET_PRIVATE (self); + + if ( priv->ppp_manager + || priv->data_port + || priv->ip_ifindex != -1) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "cannot set data port in activated state"); + /* this really shouldn't happen. Assert. */ + g_return_val_if_reached (FALSE); + } + + if (!data_port) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "missing data port"); + return FALSE; + } + + is_ppp = (ip4_method == NM_MODEM_IP_METHOD_PPP) + || (ip6_method == NM_MODEM_IP_METHOD_PPP); + if (is_ppp) { + if ( !NM_IN_SET (ip4_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_PPP) + || !NM_IN_SET (ip6_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_PPP)) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "conflicting ip methods"); + return FALSE; + } + } else if ( !NM_IN_SET (ip4_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_STATIC, NM_MODEM_IP_METHOD_AUTO) + || !NM_IN_SET (ip6_method, NM_MODEM_IP_METHOD_UNKNOWN, NM_MODEM_IP_METHOD_STATIC, NM_MODEM_IP_METHOD_AUTO) + || ( ip4_method == NM_MODEM_IP_METHOD_UNKNOWN + && ip6_method == NM_MODEM_IP_METHOD_UNKNOWN)) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "invalid ip methods"); + return FALSE; + } + + if (!is_ppp) { + ifindex = nm_platform_if_nametoindex (platform, data_port); + if (ifindex <= 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "cannot find network interface %s", data_port); + return FALSE; + } + if (!nm_platform_process_events_ensure_link (platform, ifindex, data_port)) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "cannot find network interface %s in platform cache", data_port); + return FALSE; + } + } + + priv->mm_ip_timeout = timeout; + priv->ip4_method = ip4_method; + priv->ip6_method = ip6_method; + if (is_ppp) { + priv->data_port = g_strdup (data_port); + _set_ip_ifindex (self, -1, NULL); + } else { + priv->data_port = NULL; + _set_ip_ifindex (self, ifindex, data_port); + } + return TRUE; } gboolean @@ -1392,15 +1558,10 @@ nm_modem_owns_port (NMModem *self, const char *iface) if (NM_MODEM_GET_CLASS (self)->owns_port) return NM_MODEM_GET_CLASS (self)->owns_port (self, iface); - /* Fall back to data/control ports */ - if (priv->ppp_iface && (strcmp (priv->ppp_iface, iface) == 0)) - return TRUE; - if (priv->data_port && (strcmp (priv->data_port, iface) == 0)) - return TRUE; - if (priv->control_port && (strcmp (priv->control_port, iface) == 0)) - return TRUE; - - return FALSE; + return NM_IN_STRSET (iface, + priv->ip_iface, + priv->data_port, + priv->control_port); } gboolean @@ -1500,7 +1661,8 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE ((NMModem *) object); + NMModem *self = NM_MODEM (object); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); switch (prop_id) { case PROP_PATH: @@ -1512,21 +1674,12 @@ get_property (GObject *object, guint prop_id, case PROP_CONTROL_PORT: g_value_set_string (value, priv->control_port); break; - case PROP_DATA_PORT: - g_value_set_string (value, nm_modem_get_data_port (NM_MODEM (object))); + case PROP_IP_IFINDEX: + g_value_set_int (value, nm_modem_get_ip_ifindex (self)); break; case PROP_UID: g_value_set_string (value, priv->uid); break; - case PROP_IP4_METHOD: - g_value_set_uint (value, priv->ip4_method); - break; - case PROP_IP6_METHOD: - g_value_set_uint (value, priv->ip6_method); - break; - case PROP_IP_TIMEOUT: - g_value_set_uint (value, priv->mm_ip_timeout); - break; case PROP_STATE: g_value_set_int (value, priv->state); break; @@ -1569,23 +1722,10 @@ set_property (GObject *object, guint prop_id, /* construct-only */ priv->control_port = g_value_dup_string (value); break; - case PROP_DATA_PORT: - g_free (priv->data_port); - priv->data_port = g_value_dup_string (value); - break; case PROP_UID: /* construct-only */ priv->uid = g_value_dup_string (value); break; - case PROP_IP4_METHOD: - priv->ip4_method = g_value_get_uint (value); - break; - case PROP_IP6_METHOD: - priv->ip6_method = g_value_get_uint (value); - break; - case PROP_IP_TIMEOUT: - priv->mm_ip_timeout = g_value_get_uint (value); - break; case PROP_STATE: /* construct-only */ priv->state = g_value_get_int (value); @@ -1623,6 +1763,7 @@ nm_modem_init (NMModem *self) self->_priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_MODEM, NMModemPrivate); priv = self->_priv; + priv->ip_ifindex = -1; priv->ip4_route_table = RT_TABLE_MAIN; priv->ip4_route_metric = 700; priv->ip6_route_table = RT_TABLE_MAIN; @@ -1638,7 +1779,7 @@ constructed (GObject *object) priv = NM_MODEM_GET_PRIVATE (NM_MODEM (object)); - g_return_if_fail (priv->data_port || priv->control_port); + g_return_if_fail (priv->control_port); } /*****************************************************************************/ @@ -1663,6 +1804,7 @@ finalize (GObject *object) g_free (priv->driver); g_free (priv->control_port); g_free (priv->data_port); + g_free (priv->ip_iface); g_free (priv->device_id); g_free (priv->sim_id); g_free (priv->sim_operator_id); @@ -1711,33 +1853,11 @@ nm_modem_class_init (NMModemClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_DATA_PORT] = - g_param_spec_string (NM_MODEM_DATA_PORT, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_IP4_METHOD] = - g_param_spec_uint (NM_MODEM_IP4_METHOD, "", "", - NM_MODEM_IP_METHOD_UNKNOWN, - NM_MODEM_IP_METHOD_AUTO, - NM_MODEM_IP_METHOD_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_IP6_METHOD] = - g_param_spec_uint (NM_MODEM_IP6_METHOD, "", "", - NM_MODEM_IP_METHOD_UNKNOWN, - NM_MODEM_IP_METHOD_AUTO, - NM_MODEM_IP_METHOD_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_IP_TIMEOUT] = - g_param_spec_uint (NM_MODEM_IP_TIMEOUT, "", "", - 0, 360, 20, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); + obj_properties[PROP_IP_IFINDEX] = + g_param_spec_int (NM_MODEM_IP_IFINDEX, "", "", + 0, G_MAXINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_STATE] = g_param_spec_int (NM_MODEM_STATE, "", "", -- cgit 1.3.0-6-gf8a5