diff --git a/marshallers/nm-marshal.list b/marshallers/nm-marshal.list index 38669dd32b..85f7158be7 100644 --- a/marshallers/nm-marshal.list +++ b/marshallers/nm-marshal.list @@ -20,6 +20,9 @@ VOID:OBJECT,OBJECT,ENUM VOID:POINTER,STRING VOID:STRING,BOXED BOOLEAN:POINTER,STRING,BOOLEAN,UINT,STRING,STRING +VOID:STRING,BOOLEAN,UINT,STRING,STRING BOOLEAN:VOID VOID:STRING,BOOLEAN +VOID:STRING,OBJECT,POINTER +VOID:BOOLEAN,UINT diff --git a/src/modem-manager/Makefile.am b/src/modem-manager/Makefile.am index fef879ac44..79eab85fa8 100644 --- a/src/modem-manager/Makefile.am +++ b/src/modem-manager/Makefile.am @@ -7,12 +7,12 @@ INCLUDES = \ noinst_LTLIBRARIES = libmodem-manager.la libmodem_manager_la_SOURCES = \ + nm-modem.c \ + nm-modem.h \ nm-modem-cdma.c \ nm-modem-cdma.h \ nm-modem-gsm.c \ nm-modem-gsm.h \ - nm-modem.c \ - nm-modem.h \ nm-modem-manager.h \ nm-modem-manager.c \ nm-modem-types.h diff --git a/src/modem-manager/nm-modem-cdma.c b/src/modem-manager/nm-modem-cdma.c index 9ba0a78279..c69559710d 100644 --- a/src/modem-manager/nm-modem-cdma.c +++ b/src/modem-manager/nm-modem-cdma.c @@ -17,6 +17,12 @@ G_DEFINE_TYPE (NMModemCdma, nm_modem_cdma, NM_TYPE_MODEM) +#define NM_MODEM_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_CDMA, NMModemCdmaPrivate)) + +typedef struct { + DBusGProxyCall *call; +} NMModemCdmaPrivate; + typedef enum { NM_CDMA_ERROR_CONNECTION_NOT_CDMA = 0, @@ -60,41 +66,41 @@ nm_cdma_error_get_type (void) } -NMDevice * +NMModem * nm_modem_cdma_new (const char *path, const char *device, const char *data_device, - const char *driver) + guint32 ip_method) { g_return_val_if_fail (path != NULL, NULL); g_return_val_if_fail (device != NULL, NULL); g_return_val_if_fail (data_device != NULL, NULL); - g_return_val_if_fail (driver != NULL, NULL); - return (NMDevice *) g_object_new (NM_TYPE_MODEM_CDMA, - NM_DEVICE_INTERFACE_UDI, path, - NM_DEVICE_INTERFACE_IFACE, data_device, - NM_DEVICE_INTERFACE_DRIVER, driver, - NM_MODEM_PATH, path, - NM_MODEM_DEVICE, device, - NM_DEVICE_INTERFACE_TYPE_DESC, "CDMA", - NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_CDMA, - NULL); + return (NMModem *) g_object_new (NM_TYPE_MODEM_CDMA, + NM_MODEM_PATH, path, + NM_MODEM_DEVICE, device, + NM_MODEM_IFACE, data_device, + NM_MODEM_IP_METHOD, ip_method, + NULL); } static void -stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) { - NMDevice *device = NM_DEVICE (user_data); + NMModemCdma *self = NM_MODEM_CDMA (user_data); + NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self); GError *error = NULL; - dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); - if (!error) - nm_device_activate_schedule_stage2_device_config (device); + priv->call = NULL; + + if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); else { - nm_warning ("CDMA modem connection failed: %s", error->message); + nm_warning ("CDMA connection failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); g_error_free (error); - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_NONE); } } @@ -116,26 +122,41 @@ create_connect_properties (NMConnection *connection) } static NMActStageReturn -real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +real_act_stage1_prepare (NMModem *modem, + NMActRequest *req, + GPtrArray **out_hints, + const char **out_setting_name, + NMDeviceStateReason *reason) { + NMModemCdma *self = NM_MODEM_CDMA (modem); + NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self); NMConnection *connection; - GHashTable *properties; - connection = nm_act_request_get_connection (nm_device_get_act_request (device)); + connection = nm_act_request_get_connection (req); g_assert (connection); - properties = create_connect_properties (connection); - dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE), - "Connect", stage1_prepare_done, - device, NULL, 120000, - DBUS_TYPE_G_MAP_OF_VARIANT, properties, - G_TYPE_INVALID); + *out_setting_name = nm_connection_need_secrets (connection, out_hints); + if (!*out_setting_name) { + DBusGProxy *proxy; + GHashTable *properties; + + properties = create_connect_properties (connection); + proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE); + priv->call = dbus_g_proxy_begin_call_with_timeout (proxy, + "Connect", stage1_prepare_done, + self, NULL, 120000, + DBUS_TYPE_G_MAP_OF_VARIANT, properties, + G_TYPE_INVALID); + g_hash_table_destroy (properties); + } else { + /* NMModem will handle requesting secrets... */ + } return NM_ACT_STAGE_RETURN_POSTPONE; } static NMConnection * -real_get_best_auto_connection (NMDevice *dev, +real_get_best_auto_connection (NMModem *modem, GSList *connections, char **specific_object) { @@ -159,69 +180,8 @@ real_get_best_auto_connection (NMDevice *dev, return NULL; } -static void -real_connection_secrets_updated (NMDevice *dev, - NMConnection *connection, - GSList *updated_settings, - RequestSecretsCaller caller) -{ - NMActRequest *req; - gboolean found = FALSE; - GSList *iter; - - if (caller == SECRETS_CALLER_PPP) { - NMPPPManager *ppp_manager; - NMSettingCdma *s_cdma = NULL; - - ppp_manager = nm_modem_get_ppp_manager (NM_MODEM (dev)); - g_return_if_fail (ppp_manager != NULL); - - s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA); - if (!s_cdma) { - /* Shouldn't ever happen */ - nm_ppp_manager_update_secrets (ppp_manager, - nm_device_get_iface (dev), - NULL, - NULL, - "missing CDMA setting; no secrets could be found."); - } else { - const char *username = nm_setting_cdma_get_username (s_cdma); - const char *password = nm_setting_cdma_get_password (s_cdma); - - nm_ppp_manager_update_secrets (ppp_manager, - nm_device_get_iface (dev), - username ? username : "", - password ? password : "", - NULL); - } - return; - } - - g_return_if_fail (caller == SECRETS_CALLER_CDMA); - g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH); - - for (iter = updated_settings; iter; iter = g_slist_next (iter)) { - const char *setting_name = (const char *) iter->data; - - if (!strcmp (setting_name, NM_SETTING_CDMA_SETTING_NAME)) - found = TRUE; - else - nm_warning ("Ignoring updated secrets for setting '%s'.", setting_name); - } - - if (!found) - return; - - req = nm_device_get_act_request (dev); - g_assert (req); - - g_return_if_fail (nm_act_request_get_connection (req) == connection); - - nm_device_activate_schedule_stage1_device_prepare (dev); -} - static gboolean -real_check_connection_compatible (NMDevice *device, +real_check_connection_compatible (NMModem *modem, NMConnection *connection, GError **error) { @@ -249,15 +209,46 @@ real_check_connection_compatible (NMDevice *device, return TRUE; } -static const char * -real_get_ppp_name (NMModem *device, NMConnection *connection) +static gboolean +real_get_user_pass (NMModem *modem, + NMConnection *connection, + const char **user, + const char **pass) { NMSettingCdma *s_cdma; s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA); - g_assert (s_cdma); + if (!s_cdma) + return FALSE; - return nm_setting_cdma_get_username (s_cdma); + if (user) + *user = nm_setting_cdma_get_username (s_cdma); + if (pass) + *pass = nm_setting_cdma_get_password (s_cdma); + + return TRUE; +} + +static const char * +real_get_setting_name (NMModem *modem) +{ + return NM_SETTING_CDMA_SETTING_NAME; +} + +static void +real_deactivate_quickly (NMModem *modem, NMDevice *device) +{ + NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (modem); + + if (priv->call) { + DBusGProxy *proxy; + + proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE); + dbus_g_proxy_cancel_call (proxy, priv->call); + priv->call = NULL; + } + + NM_MODEM_CLASS (nm_modem_cdma_parent_class)->deactivate_quickly (modem, device); } /*****************************************************************************/ @@ -270,19 +261,18 @@ nm_modem_cdma_init (NMModemCdma *self) static void nm_modem_cdma_class_init (NMModemCdmaClass *klass) { - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); NMModemClass *modem_class = NM_MODEM_CLASS (klass); + g_type_class_add_private (object_class, sizeof (NMModemCdmaPrivate)); + /* Virtual methods */ - device_class->get_best_auto_connection = real_get_best_auto_connection; - device_class->connection_secrets_updated = real_connection_secrets_updated; - device_class->act_stage1_prepare = real_act_stage1_prepare; - device_class->check_connection_compatible = real_check_connection_compatible; - - modem_class->get_ppp_name = real_get_ppp_name; - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_cdma_object_info); + modem_class->get_user_pass = real_get_user_pass; + modem_class->get_setting_name = real_get_setting_name; + modem_class->get_best_auto_connection = real_get_best_auto_connection; + modem_class->check_connection_compatible = real_check_connection_compatible; + modem_class->act_stage1_prepare = real_act_stage1_prepare; + modem_class->deactivate_quickly = real_deactivate_quickly; dbus_g_error_domain_register (NM_CDMA_ERROR, NULL, NM_TYPE_CDMA_ERROR); } diff --git a/src/modem-manager/nm-modem-cdma.h b/src/modem-manager/nm-modem-cdma.h index 25dd9dcb1d..96606a735a 100644 --- a/src/modem-manager/nm-modem-cdma.h +++ b/src/modem-manager/nm-modem-cdma.h @@ -27,10 +27,10 @@ typedef struct { GType nm_modem_cdma_get_type (void); -NMDevice *nm_modem_cdma_new (const char *path, - const char *device, - const char *data_device, - const char *driver); +NMModem *nm_modem_cdma_new (const char *path, + const char *device, + const char *data_device, + guint32 ip_method); G_END_DECLS diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c index 8f5b3b2db0..b178590c00 100644 --- a/src/modem-manager/nm-modem-gsm.c +++ b/src/modem-manager/nm-modem-gsm.c @@ -31,10 +31,14 @@ typedef enum { } MMModemGsmMode; -#define GSM_SECRETS_TRIES "gsm-secrets-tries" - G_DEFINE_TYPE (NMModemGsm, nm_modem_gsm, NM_TYPE_MODEM) +#define NM_MODEM_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_GSM, NMModemGsmPrivate)) + +typedef struct { + DBusGProxyCall *call; +} NMModemGsmPrivate; + typedef enum { NM_GSM_ERROR_CONNECTION_NOT_GSM = 0, @@ -78,28 +82,22 @@ nm_gsm_error_get_type (void) } -NMDevice * +NMModem * nm_modem_gsm_new (const char *path, const char *device, const char *data_device, - const char *driver, guint32 ip_method) { g_return_val_if_fail (path != NULL, NULL); g_return_val_if_fail (device != NULL, NULL); g_return_val_if_fail (data_device != NULL, NULL); - g_return_val_if_fail (driver != NULL, NULL); - return (NMDevice *) g_object_new (NM_TYPE_MODEM_GSM, - NM_DEVICE_INTERFACE_UDI, path, - NM_DEVICE_INTERFACE_IFACE, data_device, - NM_DEVICE_INTERFACE_DRIVER, driver, - NM_MODEM_PATH, path, - NM_MODEM_IP_METHOD, ip_method, - NM_MODEM_DEVICE, device, - NM_DEVICE_INTERFACE_TYPE_DESC, "GSM", - NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_GSM, - NULL); + return (NMModem *) g_object_new (NM_TYPE_MODEM_GSM, + NM_MODEM_PATH, path, + NM_MODEM_DEVICE, device, + NM_MODEM_IFACE, data_device, + NM_MODEM_IP_METHOD, ip_method, + NULL); } static NMDeviceStateReason @@ -138,31 +136,16 @@ translate_mm_error (GError *error) } static void -clear_pin (NMDevice *device) +stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) { - NMActRequest *req; - NMConnection *connection; - NMSettingGsm *setting; - - req = nm_device_get_act_request (device); - g_assert (req); - connection = nm_act_request_get_connection (req); - g_assert (connection); - setting = NM_SETTING_GSM (nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM)); - g_assert (setting); - - g_object_set (G_OBJECT (setting), NM_SETTING_GSM_PIN, NULL, NULL); -} - -static void -stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); + NMModemGsm *self = NM_MODEM_GSM (user_data); + NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); GError *error = NULL; - dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); - if (!error) - nm_device_activate_schedule_stage2_device_config (device); + priv->call = NULL; + + if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); else { const char *required_secret = NULL; gboolean retry_secret = FALSE; @@ -170,22 +153,23 @@ stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_d if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN)) required_secret = NM_SETTING_GSM_PIN; else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_WRONG)) { - clear_pin (device); required_secret = NM_SETTING_GSM_PIN; retry_secret = TRUE; - } else - nm_warning ("GSM modem connection failed: %s", error->message); + } else { + nm_warning ("GSM connection failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + } if (required_secret) { - nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); - nm_act_request_get_secrets (nm_device_get_act_request (device), - NM_SETTING_GSM_SETTING_NAME, - retry_secret, - SECRETS_CALLER_GSM, - required_secret, - NULL); + g_signal_emit_by_name (self, NM_MODEM_NEED_AUTH, + NM_SETTING_GSM_SETTING_NAME, + retry_secret, + SECRETS_CALLER_MOBILE_BROADBAND, + required_secret, + NULL); } else - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, translate_mm_error (error)); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); g_error_free (error); } @@ -248,60 +232,41 @@ create_connect_properties (NMConnection *connection) } static NMActStageReturn -real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +real_act_stage1_prepare (NMModem *modem, + NMActRequest *req, + GPtrArray **out_hints, + const char **out_setting_name, + NMDeviceStateReason *reason) { - NMActRequest *req; + NMModemGsm *self = NM_MODEM_GSM (modem); + NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); NMConnection *connection; - const char *setting_name; - GPtrArray *hints = NULL; - const char *hint1 = NULL, *hint2 = NULL; - guint32 tries; - req = nm_device_get_act_request (device); - g_assert (req); connection = nm_act_request_get_connection (req); g_assert (connection); - setting_name = nm_connection_need_secrets (connection, &hints); - if (!setting_name) { + *out_setting_name = nm_connection_need_secrets (connection, out_hints); + if (!*out_setting_name) { + DBusGProxy *proxy; GHashTable *properties; properties = create_connect_properties (connection); - dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE), - "Connect", stage1_prepare_done, - device, NULL, 120000, - DBUS_TYPE_G_MAP_OF_VARIANT, properties, - G_TYPE_INVALID); - - return NM_ACT_STAGE_RETURN_POSTPONE; + proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE); + priv->call = dbus_g_proxy_begin_call_with_timeout (proxy, + "Connect", stage1_prepare_done, + self, NULL, 120000, + DBUS_TYPE_G_MAP_OF_VARIANT, properties, + G_TYPE_INVALID); + g_hash_table_destroy (properties); + } else { + /* NMModem will handle requesting secrets... */ } - if (hints) { - if (hints->len > 0) - hint1 = g_ptr_array_index (hints, 0); - if (hints->len > 1) - hint2 = g_ptr_array_index (hints, 1); - } - - nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); - - tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), GSM_SECRETS_TRIES)); - nm_act_request_get_secrets (req, - setting_name, - tries ? TRUE : FALSE, - SECRETS_CALLER_GSM, - hint1, - hint2); - g_object_set_data (G_OBJECT (connection), GSM_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); - - if (hints) - g_ptr_array_free (hints, TRUE); - return NM_ACT_STAGE_RETURN_POSTPONE; } static NMConnection * -real_get_best_auto_connection (NMDevice *dev, +real_get_best_auto_connection (NMModem *modem, GSList *connections, char **specific_object) { @@ -325,109 +290,8 @@ real_get_best_auto_connection (NMDevice *dev, return NULL; } -static void -real_connection_secrets_updated (NMDevice *dev, - NMConnection *connection, - GSList *updated_settings, - RequestSecretsCaller caller) -{ - NMActRequest *req; - gboolean found = FALSE; - GSList *iter; - - if (caller == SECRETS_CALLER_PPP) { - NMPPPManager *ppp_manager; - NMSettingGsm *s_gsm = NULL; - - ppp_manager = nm_modem_get_ppp_manager (NM_MODEM (dev)); - g_return_if_fail (ppp_manager != NULL); - - s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM); - if (!s_gsm) { - /* Shouldn't ever happen */ - nm_ppp_manager_update_secrets (ppp_manager, - nm_device_get_iface (dev), - NULL, - NULL, - "missing GSM setting; no secrets could be found."); - } else { - const char *username = nm_setting_gsm_get_username (s_gsm); - const char *password = nm_setting_gsm_get_password (s_gsm); - - nm_ppp_manager_update_secrets (ppp_manager, - nm_device_get_iface (dev), - username ? username : "", - password ? password : "", - NULL); - } - return; - } - - g_return_if_fail (caller == SECRETS_CALLER_GSM); - g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH); - - for (iter = updated_settings; iter; iter = g_slist_next (iter)) { - const char *setting_name = (const char *) iter->data; - - if (!strcmp (setting_name, NM_SETTING_GSM_SETTING_NAME)) - found = TRUE; - else - nm_warning ("Ignoring updated secrets for setting '%s'.", setting_name); - } - - if (!found) - return; - - req = nm_device_get_act_request (dev); - g_assert (req); - - g_return_if_fail (nm_act_request_get_connection (req) == connection); - - nm_device_activate_schedule_stage1_device_prepare (dev); -} - -static NMActStageReturn -real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) -{ - NMActRequest *req; - NMConnection *connection; - - req = nm_device_get_act_request (device); - g_assert (req); - - /* Clear secrets tries counter since secrets were successfully used - * already if we get here. - */ - connection = nm_act_request_get_connection (req); - g_assert (connection); - g_object_set_data (G_OBJECT (connection), GSM_SECRETS_TRIES, NULL); - - if (NM_DEVICE_CLASS (nm_modem_gsm_parent_class)->act_stage2_config) - return NM_DEVICE_CLASS (nm_modem_gsm_parent_class)->act_stage2_config (device, reason); - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static void -real_deactivate_quickly (NMDevice *device) -{ - NMActRequest *req; - NMConnection *connection; - - req = nm_device_get_act_request (device); - if (req) { - /* Clear the secrets attempts counter */ - connection = nm_act_request_get_connection (req); - g_assert (connection); - g_object_set_data (G_OBJECT (connection), GSM_SECRETS_TRIES, NULL); - } - - if (NM_DEVICE_CLASS (nm_modem_gsm_parent_class)->deactivate_quickly) - NM_DEVICE_CLASS (nm_modem_gsm_parent_class)->deactivate_quickly (device); -} - static gboolean -real_check_connection_compatible (NMDevice *device, +real_check_connection_compatible (NMModem *modem, NMConnection *connection, GError **error) { @@ -455,17 +319,49 @@ real_check_connection_compatible (NMDevice *device, return TRUE; } -static const char * -real_get_ppp_name (NMModem *device, NMConnection *connection) +static gboolean +real_get_user_pass (NMModem *modem, + NMConnection *connection, + const char **user, + const char **pass) { NMSettingGsm *s_gsm; s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM); - g_assert (s_gsm); + if (!s_gsm) + return FALSE; - return nm_setting_gsm_get_username (s_gsm); + if (user) + *user = nm_setting_gsm_get_username (s_gsm); + if (pass) + *pass = nm_setting_gsm_get_password (s_gsm); + + return TRUE; } +static const char * +real_get_setting_name (NMModem *modem) +{ + return NM_SETTING_GSM_SETTING_NAME; +} + +static void +real_deactivate_quickly (NMModem *modem, NMDevice *device) +{ + NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (modem); + + if (priv->call) { + DBusGProxy *proxy; + + proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE); + dbus_g_proxy_cancel_call (proxy, priv->call); + priv->call = NULL; + } + + NM_MODEM_CLASS (nm_modem_gsm_parent_class)->deactivate_quickly (modem, device); +} + + /*****************************************************************************/ static void @@ -476,21 +372,20 @@ nm_modem_gsm_init (NMModemGsm *self) static void nm_modem_gsm_class_init (NMModemGsmClass *klass) { - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); NMModemClass *modem_class = NM_MODEM_CLASS (klass); + g_type_class_add_private (object_class, sizeof (NMModemGsmPrivate)); + /* Virtual methods */ - device_class->get_best_auto_connection = real_get_best_auto_connection; - device_class->connection_secrets_updated = real_connection_secrets_updated; - device_class->act_stage1_prepare = real_act_stage1_prepare; - device_class->act_stage2_config = real_act_stage2_config; - device_class->deactivate_quickly = real_deactivate_quickly; - device_class->check_connection_compatible = real_check_connection_compatible; + modem_class->get_user_pass = real_get_user_pass; + modem_class->get_setting_name = real_get_setting_name; + modem_class->get_best_auto_connection = real_get_best_auto_connection; + modem_class->check_connection_compatible = real_check_connection_compatible; + modem_class->act_stage1_prepare = real_act_stage1_prepare; + modem_class->deactivate_quickly = real_deactivate_quickly; - modem_class->get_ppp_name = real_get_ppp_name; - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_gsm_object_info); +// device_class->act_stage2_config = real_act_stage2_config; dbus_g_error_domain_register (NM_GSM_ERROR, NULL, NM_TYPE_GSM_ERROR); } diff --git a/src/modem-manager/nm-modem-gsm.h b/src/modem-manager/nm-modem-gsm.h index 4e45811641..41e9094d29 100644 --- a/src/modem-manager/nm-modem-gsm.h +++ b/src/modem-manager/nm-modem-gsm.h @@ -27,11 +27,10 @@ typedef struct { GType nm_modem_gsm_get_type (void); -NMDevice *nm_modem_gsm_new (const char *path, - const char *device, - const char *data_device, - const char *driver, - guint32 ip_method); +NMModem *nm_modem_gsm_new (const char *path, + const char *device, + const char *data_device, + guint32 ip_method); G_END_DECLS diff --git a/src/modem-manager/nm-modem-manager.c b/src/modem-manager/nm-modem-manager.c index 3b9f6438a6..cb43c7b725 100644 --- a/src/modem-manager/nm-modem-manager.c +++ b/src/modem-manager/nm-modem-manager.c @@ -8,6 +8,7 @@ #include "nm-dbus-manager.h" #include "nm-utils.h" #include "nm-modem-types.h" +#include "nm-marshal.h" #define MODEM_POKE_INTERVAL 120 @@ -24,8 +25,8 @@ typedef struct { } NMModemManagerPrivate; enum { - DEVICE_ADDED, - DEVICE_REMOVED, + MODEM_ADDED, + MODEM_REMOVED, LAST_SIGNAL }; @@ -58,9 +59,10 @@ nm_modem_manager_has_modem_for_iface (NMModemManager *manager, g_assert (iface); for (iter = g_hash_table_get_values(priv->modems); iter != NULL; iter = iter->next) { - NMDevice *device = NM_DEVICE(iter->data); - const gchar *device_iface = nm_device_get_iface (device); - if (!g_strcmp0 (iface, device_iface)) + NMModem *modem = NM_MODEM (iter->data); + const char *modem_iface = nm_modem_get_iface (modem); + + if (!g_strcmp0 (iface, modem_iface)) return TRUE; } return FALSE; @@ -162,7 +164,7 @@ static void create_modem (NMModemManager *manager, const char *path) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (manager); - NMDevice *device; + NMModem *modem; char *data_device = NULL, *driver = NULL, *master_device = NULL; uint modem_type = MM_MODEM_TYPE_UNKNOWN; uint ip_method = MM_MODEM_IP_METHOD_PPP; @@ -198,19 +200,20 @@ create_modem (NMModemManager *manager, const char *path) } if (modem_type == MM_MODEM_TYPE_GSM) - device = nm_modem_gsm_new (path, master_device, data_device, driver, ip_method); + modem = nm_modem_gsm_new (path, master_device, data_device, ip_method); else if (modem_type == MM_MODEM_TYPE_CDMA) - device = nm_modem_cdma_new (path, master_device, data_device, driver); + modem = nm_modem_cdma_new (path, master_device, data_device, ip_method); else g_error ("Invalid modem type"); g_free (data_device); - g_free (driver); - if (device) { - g_hash_table_insert (priv->modems, g_strdup (path), device); - g_signal_emit (manager, signals[DEVICE_ADDED], 0, device); + if (modem) { + g_hash_table_insert (priv->modems, g_strdup (path), modem); + g_signal_emit (manager, signals[MODEM_ADDED], 0, modem, driver); } + + g_free (driver); } static void @@ -227,7 +230,7 @@ modem_removed (DBusGProxy *proxy, const char *path, gpointer user_data) modem = (NMModem *) g_hash_table_lookup (priv->modems, path); if (modem) { - g_signal_emit (user_data, signals[DEVICE_REMOVED], 0, modem); + g_signal_emit (user_data, signals[MODEM_REMOVED], 0, modem); g_hash_table_remove (priv->modems, path); } } @@ -310,7 +313,7 @@ modem_manager_appeared (NMModemManager *self, gboolean enumerate_devices) static gboolean remove_one_modem (gpointer key, gpointer value, gpointer user_data) { - g_signal_emit (user_data, signals[DEVICE_REMOVED], 0, value); + g_signal_emit (user_data, signals[MODEM_REMOVED], 0, value); return TRUE; } @@ -420,23 +423,21 @@ nm_modem_manager_class_init (NMModemManagerClass *klass) object_class->dispose = dispose; /* signals */ - signals[DEVICE_ADDED] = - g_signal_new ("device-added", + signals[MODEM_ADDED] = + g_signal_new ("modem-added", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMModemManagerClass, device_added), + G_STRUCT_OFFSET (NMModemManagerClass, modem_added), NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); + _nm_marshal_VOID__OBJECT_STRING, + G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_STRING); - signals[DEVICE_REMOVED] = - g_signal_new ("device-removed", + signals[MODEM_REMOVED] = + g_signal_new ("modem-removed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMModemManagerClass, device_removed), + G_STRUCT_OFFSET (NMModemManagerClass, modem_removed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); + G_TYPE_NONE, 1, G_TYPE_OBJECT); } diff --git a/src/modem-manager/nm-modem-manager.h b/src/modem-manager/nm-modem-manager.h index 34e99f1ec8..7402f534d0 100644 --- a/src/modem-manager/nm-modem-manager.h +++ b/src/modem-manager/nm-modem-manager.h @@ -4,7 +4,7 @@ #define NM_MODEM_MANAGER_H #include -#include "nm-device.h" +#include "nm-modem.h" #define NM_TYPE_MODEM_MANAGER (nm_modem_manager_get_type ()) #define NM_MODEM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_MANAGER, NMModemManager)) @@ -21,11 +21,9 @@ typedef struct { GObjectClass parent; /* Signals */ - void (*device_added) (NMModemManager *manager, - NMDevice *device); + void (*modem_added) (NMModemManager *manager, NMModem *modem, const char *driver); - void (*device_removed) (NMModemManager *manager, - NMDevice *device); + void (*modem_removed) (NMModemManager *manager, NMModem *modem); } NMModemManagerClass; GType nm_modem_manager_get_type (void); diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 508ff6a44e..fa39bc8ecc 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -2,27 +2,25 @@ #include #include "nm-modem.h" -#include "nm-device-private.h" #include "NetworkManagerSystem.h" -#include "nm-device-interface.h" #include "nm-dbus-manager.h" #include "nm-setting-connection.h" -#include "nm-setting-gsm.h" -#include "nm-setting-cdma.h" #include "nm-marshal.h" #include "nm-properties-changed-signal.h" #include "nm-modem-types.h" #include "nm-utils.h" -#include "nm-serial-device-glue.h" #include "NetworkManagerUtils.h" +#include "nm-device-private.h" +#include "nm-device-interface.h" -G_DEFINE_TYPE (NMModem, nm_modem, NM_TYPE_DEVICE) +G_DEFINE_TYPE (NMModem, nm_modem, G_TYPE_OBJECT) #define NM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM, NMModemPrivate)) enum { PROP_0, PROP_DEVICE, + PROP_IFACE, PROP_PATH, PROP_IP_METHOD, @@ -37,6 +35,11 @@ typedef struct { NMIP4Config *pending_ip4_config; guint32 ip_method; char *device; + char *iface; + + guint32 secrets_tries; + + DBusGProxyCall *call; /* PPP stats */ guint32 in_bytes; @@ -45,7 +48,10 @@ typedef struct { enum { PPP_STATS, - PROPERTIES_CHANGED, + PPP_FAILED, + PREPARE_RESULT, + IP4_CONFIG_RESULT, + NEED_AUTH, LAST_SIGNAL }; @@ -81,17 +87,19 @@ nm_modem_get_proxy (NMModem *self, return priv->proxy; } -const char * -nm_modem_get_ppp_name (NMModem *self, - NMConnection *connection) +static void +merge_ip4_config (NMActRequest *req, NMIP4Config *config) { - g_return_val_if_fail (NM_IS_MODEM (self), NULL); - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + NMConnection *connection; + NMSettingIP4Config *s_ip4; - if (NM_MODEM_GET_CLASS (self)->get_ppp_name) - return NM_MODEM_GET_CLASS (self)->get_ppp_name (self, connection); + /* Merge user-defined overrides into the IP4Config to be applied */ + connection = nm_act_request_get_connection (req); + g_assert (connection); - return NULL; + s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); + if (s_ip4) + nm_utils_merge_ip4_config (config, s_ip4); } /*****************************************************************************/ @@ -100,14 +108,12 @@ nm_modem_get_ppp_name (NMModem *self, static void ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) { - NMDevice *device = NM_DEVICE (user_data); - switch (status) { case NM_PPP_STATUS_DISCONNECT: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); + g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); break; case NM_PPP_STATUS_DEAD: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); + g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_FAILED); break; default: break; @@ -120,17 +126,14 @@ ppp_ip4_config (NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data) { - NMDevice *device = NM_DEVICE (user_data); + NMModem *self = NM_MODEM (user_data); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); guint32 i, num; guint32 bad_dns1 = htonl (0x0A0B0C0D); guint32 good_dns1 = htonl (0x04020201); /* GTE nameserver */ guint32 bad_dns2 = htonl (0x0A0B0C0E); guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */ - /* Ignore PPP IP4 events that come in after initial configuration */ - if (nm_device_get_state (device) != NM_DEVICE_STATE_IP_CONFIG) - return; - /* 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 @@ -164,9 +167,8 @@ ppp_ip4_config (NMPPPManager *ppp_manager, } } - nm_device_set_ip_iface (device, iface); - NM_MODEM_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config); - nm_device_activate_schedule_stage4_ip4_config_get (device); + priv->pending_ip4_config = g_object_ref (config); + g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, iface, config, NULL); } static void @@ -187,36 +189,48 @@ ppp_stats (NMPPPManager *ppp_manager, } static NMActStageReturn -ppp_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) +ppp_stage3_ip4_config_start (NMModem *self, + NMActRequest *req, + NMDeviceStateReason *reason) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device); - NMActRequest *req; + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); const char *ppp_name = NULL; - GError *err = NULL; + GError *error = NULL; NMActStageReturn ret; - req = nm_device_get_act_request (device); - g_assert (req); + g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - ppp_name = nm_modem_get_ppp_name (NM_MODEM (device), - nm_act_request_get_connection (req)); + if (NM_MODEM_GET_CLASS (self)->get_user_pass) { + NMConnection *connection = nm_act_request_get_connection (req); - priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (device)); - if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, &err)) { + g_assert (connection); + if (!NM_MODEM_GET_CLASS (self)->get_user_pass (self, connection, &ppp_name, NULL)) + return NM_ACT_STAGE_RETURN_FAILURE; + } + + priv->ppp_manager = nm_ppp_manager_new (priv->iface); + if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, &error)) { g_signal_connect (priv->ppp_manager, "state-changed", G_CALLBACK (ppp_state_changed), - device); + self); g_signal_connect (priv->ppp_manager, "ip4-config", G_CALLBACK (ppp_ip4_config), - device); + self); g_signal_connect (priv->ppp_manager, "stats", G_CALLBACK (ppp_stats), - device); + self); ret = NM_ACT_STAGE_RETURN_POSTPONE; } else { - nm_warning ("%s", err->message); - g_error_free (err); + nm_warning ("%s: error starting PPP: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_error_free (error); g_object_unref (priv->ppp_manager); priv->ppp_manager = NULL; @@ -229,20 +243,17 @@ ppp_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) } static NMActStageReturn -ppp_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason) +ppp_stage4 (NMModem *self, + NMActRequest *req, + NMIP4Config **config, + NMDeviceStateReason *reason) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device); - NMConnection *connection; - NMSettingIP4Config *s_ip4; + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); *config = priv->pending_ip4_config; priv->pending_ip4_config = NULL; - /* Merge user-defined overrides into the IP4Config to be applied */ - connection = nm_act_request_get_connection (nm_device_get_act_request (device)); - g_assert (connection); - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - nm_utils_merge_ip4_config (*config, s_ip4); + merge_ip4_config (req, *config); return NM_ACT_STAGE_RETURN_SUCCESS; } @@ -251,57 +262,80 @@ ppp_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason) /* IP method static */ static void -static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) { - NMDevice *device = NM_DEVICE (user_data); + NMModem *self = NM_MODEM (user_data); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); GValueArray *ret_array = NULL; GError *error = NULL; - if (dbus_g_proxy_end_call (proxy, call_id, &error, + priv->call = NULL; + + if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_VALUE_ARRAY, &ret_array, G_TYPE_INVALID)) { - - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device); + NMIP4Config *config; NMIP4Address *addr; int i; + config = nm_ip4_config_new (); + addr = nm_ip4_address_new (); nm_ip4_address_set_address (addr, g_value_get_uint (g_value_array_get_nth (ret_array, 0))); nm_ip4_address_set_prefix (addr, 32); + nm_ip4_config_take_address (config, addr); - priv->pending_ip4_config = nm_ip4_config_new (); - nm_ip4_config_take_address (priv->pending_ip4_config, addr); - - for (i = 1; i < ret_array->n_values; i++) - nm_ip4_config_add_nameserver (priv->pending_ip4_config, - g_value_get_uint (g_value_array_get_nth (ret_array, i))); + for (i = 1; i < ret_array->n_values; i++) { + GValue *value = g_value_array_get_nth (ret_array, i); + nm_ip4_config_add_nameserver (config, g_value_get_uint (value)); + } g_value_array_free (ret_array); - nm_device_activate_schedule_stage4_ip4_config_get (device); + + priv->pending_ip4_config = g_object_ref (config); + g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, NULL, config, NULL); } else { - nm_warning ("Retrieving IP4 configuration failed: %s", error->message); + nm_warning ("%s: retrieving IP4 configuration failed: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + + g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, NULL, NULL, error); g_error_free (error); - nm_device_state_changed (device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } } static NMActStageReturn -static_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) +static_stage3_ip4_config_start (NMModem *self, + NMActRequest *req, + NMDeviceStateReason *reason) { - dbus_g_proxy_begin_call (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM), - "GetIP4Config", static_stage3_done, - device, NULL, - G_TYPE_INVALID); + NMModemPrivate *priv; + + g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + priv = NM_MODEM_GET_PRIVATE (self); + + priv->call = dbus_g_proxy_begin_call (nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM), + "GetIP4Config", static_stage3_done, + self, NULL, + G_TYPE_INVALID); return NM_ACT_STAGE_RETURN_POSTPONE; } static NMActStageReturn -static_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason) +static_stage4 (NMModem *self, + NMActRequest *req, + NMDevice *device, + NMIP4Config **config, + NMDeviceStateReason *reason) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); gboolean no_firmware = FALSE; if (!nm_device_hw_bring_up (device, TRUE, &no_firmware)) { @@ -315,25 +349,42 @@ static_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reas *config = priv->pending_ip4_config; priv->pending_ip4_config = NULL; + merge_ip4_config (req, *config); + return NM_ACT_STAGE_RETURN_SUCCESS; } /*****************************************************************************/ -static NMActStageReturn -real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) +NMActStageReturn +nm_modem_stage3_ip4_config_start (NMModem *self, + NMDevice *device, + NMDeviceClass *device_class, + NMDeviceStateReason *reason) { + NMActRequest *req; NMActStageReturn ret; + g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (device != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_DEVICE (device), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (device_class != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_DEVICE_CLASS (device_class), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + req = nm_device_get_act_request (device); + g_assert (req); + switch (NM_MODEM_GET_PRIVATE (device)->ip_method) { case MM_MODEM_IP_METHOD_PPP: - ret = ppp_stage3_ip4_config_start (device, reason); + ret = ppp_stage3_ip4_config_start (self, req, reason); break; case MM_MODEM_IP_METHOD_STATIC: - ret = static_stage3_ip4_config_start (device, reason); + ret = static_stage3_ip4_config_start (self, req, reason); break; case MM_MODEM_IP_METHOD_DHCP: - ret = NM_DEVICE_CLASS (nm_modem_parent_class)->act_stage3_ip4_config_start (device, reason); + ret = device_class->act_stage3_ip4_config_start (device, reason); break; default: g_warning ("Invalid IP method"); @@ -344,22 +395,36 @@ real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) return ret; } -static NMActStageReturn -real_act_stage4_get_ip4_config (NMDevice *device, +NMActStageReturn +nm_modem_stage4_get_ip4_config (NMModem *self, + NMDevice *device, + NMDeviceClass *device_class, NMIP4Config **config, NMDeviceStateReason *reason) { + NMActRequest *req; NMActStageReturn ret; - switch (NM_MODEM_GET_PRIVATE (device)->ip_method) { + g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (device != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_DEVICE (device), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (device_class != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (NM_IS_DEVICE_CLASS (device_class), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + req = nm_device_get_act_request (device); + g_assert (req); + + switch (NM_MODEM_GET_PRIVATE (self)->ip_method) { case MM_MODEM_IP_METHOD_PPP: - ret = ppp_stage4 (device, config, reason); + ret = ppp_stage4 (self, req, config, reason); break; case MM_MODEM_IP_METHOD_STATIC: - ret = static_stage4 (device, config, reason); + ret = static_stage4 (self, req, device, config, reason); break; case MM_MODEM_IP_METHOD_DHCP: - ret = NM_DEVICE_CLASS (nm_modem_parent_class)->act_stage4_get_ip4_config (device, config, reason); + ret = device_class->act_stage4_get_ip4_config (device, config, reason); break; default: g_warning ("Invalid IP method"); @@ -370,12 +435,155 @@ real_act_stage4_get_ip4_config (NMDevice *device, return ret; } -static void -real_deactivate_quickly (NMDevice *device) +gboolean +nm_modem_connection_secrets_updated (NMModem *self, + NMActRequest *req, + NMConnection *connection, + GSList *updated_settings, + RequestSecretsCaller caller) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device); + NMModemPrivate *priv; + gboolean found = FALSE; + const char *setting_name; + GSList *iter; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (NM_IS_MODEM (self), FALSE); + g_return_val_if_fail (req != NULL, FALSE); + g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE); + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE); + + priv = NM_MODEM_GET_PRIVATE (self); + + if (caller == SECRETS_CALLER_PPP) { + const char *user = NULL; + const char *pass = NULL; + + g_return_val_if_fail (priv->ppp_manager != NULL, FALSE); + + if (!NM_MODEM_GET_CLASS (self)->get_user_pass (self, connection, &user, &pass)) { + /* Shouldn't ever happen */ + nm_ppp_manager_update_secrets (priv->ppp_manager, + priv->iface, + NULL, + NULL, + "missing GSM/CDMA setting; no secrets could be found."); + } else { + nm_ppp_manager_update_secrets (priv->ppp_manager, + priv->iface, + user ? user : "", + pass ? pass : "", + NULL); + } + return TRUE; + } + + g_return_val_if_fail (caller == SECRETS_CALLER_MOBILE_BROADBAND, FALSE); + + g_assert (NM_MODEM_GET_CLASS (self)->get_setting_name); + setting_name = NM_MODEM_GET_CLASS (self)->get_setting_name (self); + + for (iter = updated_settings; iter; iter = g_slist_next (iter)) { + const char *candidate_setting_name = (const char *) iter->data; + + if (!strcmp (candidate_setting_name, setting_name)) + found = TRUE; + else { + nm_warning ("Ignoring updated secrets for setting '%s'.", + candidate_setting_name); + } + } + + return found; +} + +static NMActStageReturn +real_act_stage1_prepare (NMModem *modem, + NMActRequest *req, + GPtrArray **out_hints, + const char **out_setting_name, + NMDeviceStateReason *reason) +{ + *reason = NM_DEVICE_STATE_REASON_UNKNOWN; + return NM_ACT_STAGE_RETURN_FAILURE; +} + +NMActStageReturn +nm_modem_act_stage1_prepare (NMModem *self, + NMActRequest *req, + NMDeviceStateReason *reason) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMActStageReturn ret; + GPtrArray *hints = NULL; + const char *setting_name = NULL; + + ret = NM_MODEM_GET_CLASS (self)->act_stage1_prepare (self, + req, + &hints, + &setting_name, + reason); + if ((ret == NM_ACT_STAGE_RETURN_POSTPONE) && setting_name) { + const char *hint1 = NULL, *hint2 = NULL; + + /* Need some secrets */ + if (hints) { + if (hints->len > 0) + hint1 = g_ptr_array_index (hints, 0); + if (hints->len > 1) + hint2 = g_ptr_array_index (hints, 1); + } + + g_signal_emit (self, signals[NEED_AUTH], 0, + setting_name, + priv->secrets_tries++ ? TRUE : FALSE, + SECRETS_CALLER_MOBILE_BROADBAND, + hint1, + hint2); + + if (hints) + g_ptr_array_free (hints, TRUE); + } + + return ret; +} + +NMActStageReturn +nm_modem_act_stage2_config (NMModem *self, + NMActRequest *req, + NMDeviceStateReason *reason) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + /* Clear secrets tries counter since secrets were successfully used + * already if we get here. + */ + priv->secrets_tries = 0; + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static void +real_deactivate_quickly (NMModem *self, NMDevice *device) +{ + NMModemPrivate *priv; const char *iface; + g_return_if_fail (self != NULL); + g_return_if_fail (NM_IS_MODEM (self)); + g_return_if_fail (device != NULL); + g_return_if_fail (NM_IS_DEVICE (device)); + + priv = NM_MODEM_GET_PRIVATE (self); + + priv->secrets_tries = 0; + + if (priv->call) { + dbus_g_proxy_cancel_call (priv->proxy, priv->call); + priv->call = NULL; + } + if (priv->pending_ip4_config) { g_object_unref (priv->pending_ip4_config); priv->pending_ip4_config = NULL; @@ -383,7 +591,7 @@ real_deactivate_quickly (NMDevice *device) priv->in_bytes = priv->out_bytes = 0; - switch (NM_MODEM_GET_PRIVATE (device)->ip_method) { + switch (priv->ip_method) { case MM_MODEM_IP_METHOD_PPP: if (priv->ppp_manager) { g_object_unref (priv->ppp_manager); @@ -392,8 +600,7 @@ real_deactivate_quickly (NMDevice *device) break; case MM_MODEM_IP_METHOD_STATIC: case MM_MODEM_IP_METHOD_DHCP: - iface = nm_device_get_iface (device); - + iface = nm_device_get_ip_iface (device); nm_system_device_flush_routes_with_iface (iface); nm_system_device_flush_addresses_with_iface (iface); nm_system_device_set_up_down_with_iface (iface, FALSE, NULL); @@ -402,38 +609,34 @@ real_deactivate_quickly (NMDevice *device) g_warning ("Invalid IP method"); break; } - - if (NM_DEVICE_CLASS (nm_modem_parent_class)->deactivate) - NM_DEVICE_CLASS (nm_modem_parent_class)->deactivate (device); } -static guint32 -real_get_generic_capabilities (NMDevice *dev) +void +nm_modem_deactivate_quickly (NMModem *self, NMDevice *device) { - return NM_DEVICE_CAP_NM_SUPPORTED; + NM_MODEM_GET_CLASS (self)->deactivate_quickly (self, device); } -static void -device_state_changed (NMDeviceInterface *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason, - gpointer user_data) +void +nm_modem_device_state_changed (NMModem *self, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) { - NMModem *self = NM_MODEM (user_data); - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + g_return_if_fail (self != NULL); + g_return_if_fail (NM_IS_MODEM (self)); /* Make sure we don't leave the serial device open */ switch (new_state) { case NM_DEVICE_STATE_NEED_AUTH: - if (priv->ppp_manager) + if (NM_MODEM_GET_PRIVATE (self)->ppp_manager) break; /* else fall through */ case NM_DEVICE_STATE_UNMANAGED: case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_FAILED: case NM_DEVICE_STATE_DISCONNECTED: - dbus_g_proxy_call_no_reply (nm_modem_get_proxy (self, NULL), + dbus_g_proxy_call_no_reply (nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM), "Enable", G_TYPE_BOOLEAN, FALSE, G_TYPE_INVALID); @@ -443,13 +646,13 @@ device_state_changed (NMDeviceInterface *device, } } -static gboolean -real_hw_is_up (NMDevice *device) +gboolean +nm_modem_hw_is_up (NMModem *self, NMDevice *device) { - guint32 ip_method = NM_MODEM_GET_PRIVATE (device)->ip_method; + guint32 ip_method = NM_MODEM_GET_PRIVATE (self)->ip_method; if (ip_method == MM_MODEM_IP_METHOD_STATIC || ip_method == MM_MODEM_IP_METHOD_DHCP) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); NMDeviceState state; state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); @@ -460,13 +663,13 @@ real_hw_is_up (NMDevice *device) return TRUE; } -static gboolean -real_hw_bring_up (NMDevice *device, gboolean *no_firmware) +gboolean +nm_modem_hw_bring_up (NMModem *self, NMDevice *device, gboolean *no_firmware) { - guint32 ip_method = NM_MODEM_GET_PRIVATE (device)->ip_method; + guint32 ip_method = NM_MODEM_GET_PRIVATE (self)->ip_method; if (ip_method == MM_MODEM_IP_METHOD_STATIC || ip_method == MM_MODEM_IP_METHOD_DHCP) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); NMDeviceState state; state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); @@ -477,6 +680,15 @@ real_hw_bring_up (NMDevice *device, gboolean *no_firmware) return TRUE; } +const char * +nm_modem_get_iface (NMModem *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (NM_IS_MODEM (self), NULL); + + return NM_MODEM_GET_PRIVATE (self)->iface; +} + /*****************************************************************************/ static void @@ -504,7 +716,12 @@ constructor (GType type, priv = NM_MODEM_GET_PRIVATE (object); if (!priv->device) { - g_warning ("Modem device not provided"); + g_warning ("Modem parent device not provided"); + goto err; + } + + if (!priv->device) { + g_warning ("Modem command interface not provided"); goto err; } @@ -516,8 +733,6 @@ constructor (GType type, priv->proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), MM_DBUS_SERVICE, priv->path, MM_DBUS_INTERFACE_MODEM); - g_signal_connect (object, "state-changed", G_CALLBACK (device_state_changed), object); - return object; err: @@ -538,6 +753,9 @@ get_property (GObject *object, guint prop_id, case PROP_DEVICE: g_value_set_string (value, priv->device); break; + case PROP_IFACE: + g_value_set_string (value, priv->iface); + break; case PROP_IP_METHOD: g_value_set_uint (value, priv->ip_method); break; @@ -563,7 +781,12 @@ set_property (GObject *object, guint prop_id, /* Construct only */ priv->device = g_value_dup_string (value); break; + case PROP_IFACE: + /* Construct only */ + priv->iface = g_value_dup_string (value); + break; case PROP_IP_METHOD: + /* Construct only */ priv->ip_method = g_value_get_uint (value); break; default: @@ -582,6 +805,7 @@ finalize (GObject *object) g_object_unref (priv->dbus_mgr); + g_free (priv->iface); g_free (priv->path); g_free (priv->device); @@ -592,7 +816,6 @@ static void nm_modem_class_init (NMModemClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); g_type_class_add_private (object_class, sizeof (NMModemPrivate)); @@ -602,12 +825,8 @@ nm_modem_class_init (NMModemClass *klass) object_class->get_property = get_property; object_class->finalize = finalize; - device_class->get_generic_capabilities = real_get_generic_capabilities; - device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start; - device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; - device_class->deactivate_quickly = real_deactivate_quickly; - device_class->hw_is_up = real_hw_is_up; - device_class->hw_bring_up = real_hw_bring_up; + klass->act_stage1_prepare = real_act_stage1_prepare; + klass->deactivate_quickly = real_deactivate_quickly; /* Properties */ g_object_class_install_property @@ -616,7 +835,7 @@ nm_modem_class_init (NMModemClass *klass) "DBus path", "DBus path", NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_DEVICE, @@ -624,7 +843,15 @@ nm_modem_class_init (NMModemClass *klass) "Device", "Master modem parent device", NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_IFACE, + g_param_spec_string (NM_MODEM_IFACE, + "Interface", + "Modem command interface", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_IP_METHOD, @@ -634,7 +861,7 @@ nm_modem_class_init (NMModemClass *klass) MM_MODEM_IP_METHOD_PPP, MM_MODEM_IP_METHOD_DHCP, MM_MODEM_IP_METHOD_PPP, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); /* Signals */ signals[PPP_STATS] = @@ -647,10 +874,41 @@ nm_modem_class_init (NMModemClass *klass) G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMModemClass, properties_changed)); + signals[PPP_FAILED] = + g_signal_new ("ppp-failed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, ppp_failed), + NULL, NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_serial_device_object_info); + signals[IP4_CONFIG_RESULT] = + g_signal_new (NM_MODEM_IP4_CONFIG_RESULT, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, ip4_config_result), + NULL, NULL, + _nm_marshal_VOID__STRING_OBJECT_POINTER, + G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_OBJECT, G_TYPE_POINTER); + + signals[PREPARE_RESULT] = + g_signal_new (NM_MODEM_PREPARE_RESULT, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, prepare_result), + NULL, NULL, + _nm_marshal_VOID__BOOLEAN_UINT, + G_TYPE_NONE, 2, G_TYPE_BOOLEAN, G_TYPE_UINT); + + signals[NEED_AUTH] = + g_signal_new (NM_MODEM_NEED_AUTH, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemClass, need_auth), + NULL, NULL, + _nm_marshal_VOID__STRING_BOOLEAN_UINT_STRING_STRING, + G_TYPE_NONE, 5, + G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING); } + diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h index cd638039f7..ec4f91fac1 100644 --- a/src/modem-manager/nm-modem.h +++ b/src/modem-manager/nm-modem.h @@ -4,8 +4,9 @@ #define NM_MODEM_H #include -#include +#include #include "ppp-manager/nm-ppp-manager.h" +#include "nm-device.h" G_BEGIN_DECLS @@ -18,33 +19,101 @@ G_BEGIN_DECLS #define NM_MODEM_PATH "path" #define NM_MODEM_DEVICE "device" +#define NM_MODEM_IFACE "iface" #define NM_MODEM_IP_METHOD "ip-method" +#define NM_MODEM_PREPARE_RESULT "prepare-result" +#define NM_MODEM_IP4_CONFIG_RESULT "ip4-config-result" +#define NM_MODEM_NEED_AUTH "need-auth" + typedef struct { - NMDevice parent; + GObject parent; } NMModem; typedef struct { - NMDeviceClass parent; + GObjectClass parent; - const char *(*get_ppp_name) (NMModem *self, - NMConnection *connection); + gboolean (*get_user_pass) (NMModem *modem, + NMConnection *connection, + const char **user, + const char **pass); + + const char * (*get_setting_name) (NMModem *modem); + + gboolean (*check_connection_compatible) (NMModem *modem, + NMConnection *connection, + GError **error); + + NMConnection * (*get_best_auto_connection) (NMModem *modem, + GSList *connections, + char **specific_object); + + NMActStageReturn (*act_stage1_prepare) (NMModem *modem, + NMActRequest *req, + GPtrArray **out_hints, + const char **out_setting_name, + NMDeviceStateReason *reason); + + void (*deactivate_quickly) (NMModem *self, NMDevice *device); /* Signals */ - void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes); - void (*properties_changed) (NMModem *self, GHashTable *properties); + void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes); + void (*ppp_failed) (NMModem *self, NMDeviceStateReason reason); + + void (*prepare_result) (NMModem *self, gboolean success, NMDeviceStateReason reason); + void (*ip4_config_result) (NMModem *self, const char *iface, NMIP4Config *config, GError *error); + + void (*need_auth) (NMModem *self, + const char *setting_name, + gboolean retry, + RequestSecretsCaller caller, + const char *hint1, + const char *hint2); } NMModemClass; GType nm_modem_get_type (void); /* Protected */ -NMPPPManager *nm_modem_get_ppp_manager (NMModem *self); -DBusGProxy *nm_modem_get_proxy (NMModem *self, - const char *interface); +NMPPPManager *nm_modem_get_ppp_manager (NMModem *modem); +DBusGProxy * nm_modem_get_proxy (NMModem *modem, const char *interface); +const char * nm_modem_get_iface (NMModem *modem); -const char *nm_modem_get_ppp_name (NMModem *self, - NMConnection *connection); +NMActStageReturn nm_modem_act_stage1_prepare (NMModem *modem, + NMActRequest *req, + NMDeviceStateReason *reason); + +NMActStageReturn nm_modem_act_stage2_config (NMModem *modem, + NMActRequest *req, + NMDeviceStateReason *reason); + +NMActStageReturn nm_modem_stage3_ip4_config_start (NMModem *modem, + NMDevice *device, + NMDeviceClass *device_class, + NMDeviceStateReason *reason); + +NMActStageReturn nm_modem_stage4_get_ip4_config (NMModem *modem, + NMDevice *device, + NMDeviceClass *device_class, + NMIP4Config **config, + NMDeviceStateReason *reason); + +void nm_modem_deactivate_quickly (NMModem *modem, NMDevice *device); + +void nm_modem_device_state_changed (NMModem *modem, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason); + +gboolean nm_modem_hw_is_up (NMModem *modem, NMDevice *device); + +gboolean nm_modem_hw_bring_up (NMModem *modem, NMDevice *device, gboolean *no_firmware); + +gboolean nm_modem_connection_secrets_updated (NMModem *modem, + NMActRequest *req, + NMConnection *connection, + GSList *updated_settings, + RequestSecretsCaller caller); G_END_DECLS diff --git a/src/nm-secrets-provider-interface.h b/src/nm-secrets-provider-interface.h index 299e8c2dc8..3d9e08b186 100644 --- a/src/nm-secrets-provider-interface.h +++ b/src/nm-secrets-provider-interface.h @@ -28,8 +28,7 @@ typedef enum { SECRETS_CALLER_NONE = 0, SECRETS_CALLER_ETHERNET, SECRETS_CALLER_WIFI, - SECRETS_CALLER_GSM, - SECRETS_CALLER_CDMA, + SECRETS_CALLER_MOBILE_BROADBAND, SECRETS_CALLER_PPP, SECRETS_CALLER_VPN } RequestSecretsCaller;