const char * nm_modem_get_data_port (NMModem *self) { g_return_val_if_fail (NM_IS_MODEM (self), NULL); /* 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 nm_modem_get_mm_enabled (NMModem *self) { g_return_val_if_fail (NM_IS_MODEM (self), TRUE); return NM_MODEM_GET_PRIVATE (self)->mm_enabled; }
static void cancel_get_secrets (NMModem *self) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); nm_act_request_cancel_secrets (priv->act_request, priv->secrets_id); }
static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); const char *s; switch (prop_id) { case PROP_PATH: /* Construct only */ priv->path = g_value_dup_string (value); break; case PROP_DRIVER: /* Construct only */ priv->driver = g_value_dup_string (value); break; case PROP_CONTROL_PORT: priv->control_port = g_value_dup_string (value); break; case PROP_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: priv->state = g_value_get_enum (value); break; case PROP_DEVICE_ID: /* construct only */ priv->device_id = g_value_dup_string (value); break; case PROP_SIM_ID: g_free (priv->sim_id); priv->sim_id = g_value_dup_string (value); break; case PROP_IP_TYPES: priv->ip_types = g_value_get_uint (value); break; case PROP_SIM_OPERATOR_ID: g_clear_pointer (&priv->sim_operator_id, g_free); s = g_value_get_string (value); if (s && s[0]) priv->sim_operator_id = g_strdup (s); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) { NMModem *self = NM_MODEM (user_data); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); GValueArray *ret_array = NULL; GError *error = NULL; NMIP4Config *config = NULL; priv->call = NULL; if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_VALUE_ARRAY, &ret_array, G_TYPE_INVALID)) { 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); for (i = 0; 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); } g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, NULL, config, error); g_clear_error (&error); }
void nm_modem_set_mm_enabled (NMModem *self, gboolean enabled) { NMModemPrivate *priv; g_return_if_fail (self != NULL); g_return_if_fail (NM_IS_MODEM (self)); priv = NM_MODEM_GET_PRIVATE (self); /* FIXME: For now this just toggles the ModemManager enabled state. In the * future we want to tie this into rfkill state instead so that the user can * toggle rfkill status of the WWAN modem. */ if (priv->mm_enabled != enabled) { DBusGProxy *proxy; proxy = nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM); dbus_g_proxy_begin_call (proxy, "Enable", set_mm_enabled_done, self, NULL, G_TYPE_BOOLEAN, enabled, G_TYPE_INVALID); /* If we are disabling the modem, stop saying that it's enabled. */ if (!enabled) update_mm_enabled (self, enabled); } }
static void nm_modem_init (NMModem *self) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); priv->dbus_mgr = nm_dbus_manager_get (); }
void nm_modem_emit_ip6_config_result (NMModem *self, NMIP6Config *config, GError *error) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); guint i, num; gboolean do_slaac = TRUE; if (error) { g_signal_emit (self, signals[IP6_CONFIG_RESULT], 0, NULL, FALSE, error); return; } if (config) { /* If the IPv6 configuration only included a Link-Local address, then * we have to run SLAAC to get the full IPv6 configuration. */ num = nm_ip6_config_get_num_addresses (config); g_assert (num > 0); for (i = 0; i < num; i++) { const NMPlatformIP6Address * addr = nm_ip6_config_get_address (config, i); if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) { if (!priv->iid.id) priv->iid.id = ((guint64 *)(&addr->address.s6_addr))[1]; } else do_slaac = FALSE; } } g_assert (config || do_slaac); g_signal_emit (self, signals[IP6_CONFIG_RESULT], 0, config, do_slaac, NULL); }
static GObject* constructor (GType type, guint n_construct_params, GObjectConstructParam *construct_params) { GObject *object; NMModemPrivate *priv; object = G_OBJECT_CLASS (nm_modem_parent_class)->constructor (type, n_construct_params, construct_params); if (!object) return NULL; priv = NM_MODEM_GET_PRIVATE (object); if (!priv->data_port && !priv->control_port) { nm_log_err (LOGD_HW, "neither modem command nor data interface provided"); goto err; } if (!priv->path) { nm_log_err (LOGD_HW, "D-Bus path not provided"); goto err; } return object; err: g_object_unref (object); return NULL; }
static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); switch (prop_id) { case PROP_PATH: g_value_set_string (value, priv->path); break; 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; case PROP_ENABLED: g_value_set_boolean (value, priv->mm_enabled); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); switch (prop_id) { case PROP_PATH: /* Construct only */ priv->path = g_value_dup_string (value); break; case PROP_DEVICE: /* 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; case PROP_ENABLED: break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
const char * nm_modem_get_control_port (NMModem *self) { g_return_val_if_fail (NM_IS_MODEM (self), NULL); return NM_MODEM_GET_PRIVATE (self)->control_port; }
const char * nm_modem_get_driver (NMModem *self) { g_return_val_if_fail (NM_IS_MODEM (self), NULL); return NM_MODEM_GET_PRIVATE (self)->driver; }
const char * nm_modem_get_path (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)->path; }
gboolean nm_modem_get_iid (NMModem *self, NMUtilsIPv6IfaceId *out_iid) { g_return_val_if_fail (NM_IS_MODEM (self), FALSE); *out_iid = NM_MODEM_GET_PRIVATE (self)->iid; return TRUE; }
static void ppp_ip4_config (NMPPPManager *ppp_manager, const char *iface, NMIP4Config *config, gpointer 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 */ gboolean dns_workaround = FALSE; /* Notify about the new data port to use */ g_free (priv->ppp_iface); priv->ppp_iface = g_strdup (iface); g_object_notify (G_OBJECT (self), NM_MODEM_DATA_PORT); /* 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 * not the case. * * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=2e09ef6886bbf00bc5a9a641110f801e372ffde6 * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=f8191bf07df374f119a07910a79217c7618f113e */ num = nm_ip4_config_get_num_nameservers (config); if (num == 2) { gboolean found1 = FALSE, found2 = FALSE; for (i = 0; i < num; i++) { guint32 ns = nm_ip4_config_get_nameserver (config, i); if (ns == bad_dns1) found1 = TRUE; else if (ns == bad_dns2) found2 = TRUE; } /* Be somewhat conservative about substitutions; the "bad" nameservers * could actually be valid in some cases, so only substitute if ppp * returns *only* the two bad nameservers. */ dns_workaround = (found1 && found2); } if (!num || dns_workaround) { nm_log_warn (LOGD_PPP, "compensating for invalid PPP-provided nameservers"); nm_ip4_config_reset_nameservers (config); nm_ip4_config_add_nameserver (config, good_dns1); nm_ip4_config_add_nameserver (config, good_dns2); } g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, config, NULL); }
void nm_modem_set_prev_state (NMModem *self, const char *reason) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); /* Reset modem to previous state if the state hasn't already changed */ if (priv->prev_state != NM_MODEM_STATE_UNKNOWN) nm_modem_set_state (self, priv->prev_state, reason); }
static void deactivate_step (DeactivateContext *ctx) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (ctx->self); GError *error = NULL; /* Check cancellable in each step */ if (g_cancellable_set_error_if_cancelled (ctx->cancellable, &error)) { g_simple_async_result_take_error (ctx->result, error); deactivate_context_complete (ctx); return; } switch (ctx->step) { case DEACTIVATE_CONTEXT_STEP_FIRST: ctx->step++; /* Fall down */ case DEACTIVATE_CONTEXT_STEP_CLEANUP: /* Make sure we keep a ref to the PPP manager if there is one */ if (priv->ppp_manager) ctx->ppp_manager = g_object_ref (priv->ppp_manager); /* Run cleanup */ NM_MODEM_GET_CLASS (ctx->self)->deactivate_cleanup (ctx->self, ctx->device); ctx->step++; /* Fall down */ case DEACTIVATE_CONTEXT_STEP_PPP_MANAGER_STOP: /* If we have a PPP manager, stop it */ if (ctx->ppp_manager) { nm_ppp_manager_stop (ctx->ppp_manager, ctx->cancellable, (GAsyncReadyCallback) ppp_manager_stop_ready, ctx); return; } ctx->step++; /* Fall down */ case DEACTIVATE_CONTEXT_STEP_MM_DISCONNECT: /* Disconnect asynchronously */ NM_MODEM_GET_CLASS (ctx->self)->disconnect (ctx->self, FALSE, ctx->cancellable, (GAsyncReadyCallback) disconnect_ready, ctx); return; case DEACTIVATE_CONTEXT_STEP_LAST: nm_log_dbg (LOGD_MB, "(%s): modem deactivation finished", nm_modem_get_uid (ctx->self)); deactivate_context_complete (ctx); return; } g_assert_not_reached (); }
static void query_mm_enabled (NMModem *self) { dbus_g_proxy_begin_call (NM_MODEM_GET_PRIVATE (self)->props_proxy, "Get", get_mm_enabled_done, self, NULL, G_TYPE_STRING, MM_DBUS_INTERFACE_MODEM, G_TYPE_STRING, "Enabled", G_TYPE_INVALID); }
static void update_mm_enabled (NMModem *self, gboolean new_enabled) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); if (priv->mm_enabled != new_enabled) { priv->mm_enabled = new_enabled; g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED); } }
NMActStageReturn nm_modem_stage3_ip4_config_start (NMModem *self, NMDevice *device, NMDeviceClass *device_class, NMDeviceStateReason *reason) { NMModemPrivate *priv; NMActRequest *req; NMConnection *connection; const char *method; NMActStageReturn ret; g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (NM_IS_DEVICE (device), 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); connection = nm_act_request_get_applied_connection (req); g_assert (connection); method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); /* Only Disabled and Auto methods make sense for WWAN */ if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) return NM_ACT_STAGE_RETURN_STOP; if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) != 0) { nm_log_warn (LOGD_MB | LOGD_IP4, "(%s): unhandled WWAN IPv4 method '%s'; will fail", nm_modem_get_uid (self), method); *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; return NM_ACT_STAGE_RETURN_FAILURE; } priv = NM_MODEM_GET_PRIVATE (self); switch (priv->ip4_method) { case NM_MODEM_IP_METHOD_PPP: ret = ppp_stage3_ip_config_start (self, req, reason); break; case NM_MODEM_IP_METHOD_STATIC: ret = NM_MODEM_GET_CLASS (self)->static_stage3_ip4_config_start (self, req, reason); break; case NM_MODEM_IP_METHOD_AUTO: ret = device_class->act_stage3_ip4_config_start (device, NULL, reason); break; default: nm_log_info (LOGD_MB, "(%s): IPv4 configuration disabled", nm_modem_get_uid (self)); ret = NM_ACT_STAGE_RETURN_STOP; break; } return ret; }
static void set_data_port (NMModem *self, const char *new_data_port) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); if (g_strcmp0 (priv->data_port, new_data_port) != 0) { g_free (priv->data_port); priv->data_port = g_strdup (new_data_port); g_object_notify (G_OBJECT (self), NM_MODEM_DATA_PORT); } }
void nm_modem_set_mm_enabled (NMModem *self, gboolean enabled) { NMModemPrivate *priv; priv = NM_MODEM_GET_PRIVATE (self); if (priv->mm_enabled != enabled) NM_MODEM_GET_CLASS (self)->set_mm_enabled (self, enabled); }
static void dispose (GObject *object) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); if (priv->act_request) { g_object_unref (priv->act_request); priv->act_request = NULL; } G_OBJECT_CLASS (nm_modem_parent_class)->dispose (object); }
static void finalize (GObject *object) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); g_free (priv->uid); g_free (priv->path); g_free (priv->control_port); g_free (priv->data_port); G_OBJECT_CLASS (nm_modem_parent_class)->finalize (object); }
NMActStageReturn nm_modem_stage3_ip6_config_start (NMModem *self, NMActRequest *req, NMDeviceStateReason *reason) { NMModemPrivate *priv; NMActStageReturn ret; NMConnection *connection; const char *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 (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); connection = nm_act_request_get_applied_connection (req); g_assert (connection); method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); /* Only Ignore and Auto methods make sense for WWAN */ if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) return NM_ACT_STAGE_RETURN_STOP; if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) != 0) { nm_log_warn (LOGD_MB | LOGD_IP6, "(%s): unhandled WWAN IPv6 method '%s'; will fail", nm_modem_get_uid (self), method); *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE; return NM_ACT_STAGE_RETURN_FAILURE; } priv = NM_MODEM_GET_PRIVATE (self); switch (priv->ip6_method) { case NM_MODEM_IP_METHOD_PPP: ret = ppp_stage3_ip_config_start (self, req, reason); break; case NM_MODEM_IP_METHOD_STATIC: case NM_MODEM_IP_METHOD_AUTO: /* Both static and DHCP/Auto retrieve a base IP config from the modem * which in the static case is the full config, and the DHCP/Auto case * is just the IPv6LL address to use for SLAAC. */ ret = NM_MODEM_GET_CLASS (self)->stage3_ip6_config_request (self, reason); break; default: nm_log_info (LOGD_MB, "(%s): IPv6 configuration disabled", nm_modem_get_uid (self)); ret = NM_ACT_STAGE_RETURN_STOP; break; } return ret; }
static NMActStageReturn ppp_stage3_ip4_config_start (NMModem *self, NMActRequest *req, NMDeviceStateReason *reason) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); const char *ppp_name = NULL; GError *error = NULL; 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 (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); if (NM_MODEM_GET_CLASS (self)->get_user_pass) { NMConnection *connection = nm_act_request_get_connection (req); 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, 20, &error)) { g_signal_connect (priv->ppp_manager, "state-changed", G_CALLBACK (ppp_state_changed), self); g_signal_connect (priv->ppp_manager, "ip4-config", G_CALLBACK (ppp_ip4_config), self); g_signal_connect (priv->ppp_manager, "stats", G_CALLBACK (ppp_stats), self); ret = NM_ACT_STAGE_RETURN_POSTPONE; } else { nm_log_err (LOGD_PPP, "error starting PPP: (%d) %s", error ? error->code : -1, error && error->message ? error->message : "(unknown)"); g_error_free (error); g_object_unref (priv->ppp_manager); priv->ppp_manager = NULL; *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; ret = NM_ACT_STAGE_RETURN_FAILURE; } return ret; }
static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); switch (prop_id) { case PROP_PATH: g_value_set_string (value, priv->path); break; case PROP_DRIVER: g_value_set_string (value, priv->driver); break; 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))); 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_enum (value, priv->state); break; case PROP_DEVICE_ID: g_value_set_string (value, priv->device_id); break; case PROP_SIM_ID: g_value_set_string (value, priv->sim_id); break; case PROP_IP_TYPES: g_value_set_uint (value, priv->ip_types); break; case PROP_SIM_OPERATOR_ID: g_value_set_string (value, priv->sim_operator_id); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void real_deactivate (NMModem *self, NMDevice *device) { NMModemPrivate *priv; int ifindex; 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->act_request) { cancel_get_secrets (self); g_object_unref (priv->act_request); priv->act_request = NULL; } if (priv->call) { dbus_g_proxy_cancel_call (priv->proxy, priv->call); priv->call = NULL; } priv->in_bytes = priv->out_bytes = 0; if (priv->ppp_manager) { g_object_unref (priv->ppp_manager); priv->ppp_manager = NULL; } switch (priv->ip_method) { case MM_MODEM_IP_METHOD_PPP: break; case MM_MODEM_IP_METHOD_STATIC: case MM_MODEM_IP_METHOD_DHCP: ifindex = nm_device_get_ip_ifindex (device); if (ifindex >= 0) { /* FIXME: use AF_UNSPEC here when we have IPv6 support */ nm_system_iface_flush_routes (ifindex, AF_INET); nm_system_iface_flush_addresses (ifindex, AF_UNSPEC); nm_system_iface_set_up (ifindex, FALSE, NULL); } break; default: nm_log_err (LOGD_MB, "unknown IP method %d", priv->ip_method); break; } }
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; }