diff options
| author | Michael Biebl <biebl@debian.org> | 2022-02-14 19:23:28 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2022-02-14 19:23:28 +0100 |
| commit | 2f94dba7385fd0e0ef19a06eb4a2fcf6c43d7946 (patch) | |
| tree | e2222f5577115985dd52044d2991253403cdd952 /src/core/devices/wwan | |
| parent | 88c227d90a6b7b388c5c85d72802a0ca8f05ed5c (diff) | |
New upstream version 1.35.91 upstream/1.35.91
Diffstat (limited to 'src/core/devices/wwan')
| -rw-r--r-- | src/core/devices/wwan/libnm-wwan.ver | 5 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-device-modem.c | 296 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem-broadband.c | 606 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem-manager.c | 92 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem-ofono.c | 278 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem.c | 985 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem.h | 137 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-service-providers.c | 82 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-service-providers.h | 18 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-wwan-factory.c | 20 | ||||
| -rw-r--r-- | src/core/devices/wwan/tests/test-service-providers.c | 36 |
11 files changed, 1195 insertions, 1360 deletions
diff --git a/src/core/devices/wwan/libnm-wwan.ver b/src/core/devices/wwan/libnm-wwan.ver index c368a590..640df36d 100644 --- a/src/core/devices/wwan/libnm-wwan.ver +++ b/src/core/devices/wwan/libnm-wwan.ver @@ -14,7 +14,6 @@ global: nm_modem_get_control_port; nm_modem_get_device_id; nm_modem_get_driver; - nm_modem_get_iid; nm_modem_get_ip_ifindex; nm_modem_get_operator_code; nm_modem_get_path; @@ -22,7 +21,6 @@ global: nm_modem_get_state; nm_modem_get_type; nm_modem_get_uid; - nm_modem_ip4_pre_commit; nm_modem_is_claimed; nm_modem_manager_get; nm_modem_manager_get_modems; @@ -32,8 +30,7 @@ global: nm_modem_manager_name_owner_unref; nm_modem_owns_port; nm_modem_set_mm_enabled; - nm_modem_stage3_ip4_config_start; - nm_modem_stage3_ip6_config_start; + nm_modem_stage3_ip_config_start; nm_modem_state_to_string; nm_modem_unclaim; local: diff --git a/src/core/devices/wwan/nm-device-modem.c b/src/core/devices/wwan/nm-device-modem.c index 1b285469..ef802a44 100644 --- a/src/core/devices/wwan/nm-device-modem.c +++ b/src/core/devices/wwan/nm-device-modem.c @@ -8,7 +8,7 @@ #include "nm-device-modem.h" #include "nm-modem.h" -#include "nm-ip4-config.h" +#include "nm-l3-config-data.h" #include "devices/nm-device-private.h" #include "nm-rfkill-manager.h" #include "settings/nm-settings-connection.h" @@ -30,14 +30,16 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceModem, PROP_APN, ); typedef struct { - NMModem * modem; + NMModem *modem; NMDeviceModemCapabilities caps; NMDeviceModemCapabilities current_caps; - char * device_id; - char * operator_code; - char * apn; + NMUtilsIPv6IfaceId iid; + char *device_id; + char *operator_code; + char *apn; bool rf_enabled : 1; NMDeviceStageState stage1_state : 3; + NMDeviceStageState stage2_state : 3; } NMDeviceModemPrivate; struct _NMDeviceModem { @@ -59,52 +61,18 @@ G_DEFINE_TYPE(NMDeviceModem, nm_device_modem, NM_TYPE_DEVICE) static void ppp_failed(NMModem *modem, guint i_reason, gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); + NMDevice *device = NM_DEVICE(user_data); NMDeviceStateReason reason = i_reason; - switch (nm_device_get_state(device)) { - case NM_DEVICE_STATE_PREPARE: - case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: - nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason); - break; - case NM_DEVICE_STATE_IP_CONFIG: - case NM_DEVICE_STATE_IP_CHECK: - case NM_DEVICE_STATE_SECONDARIES: - case NM_DEVICE_STATE_ACTIVATED: - if (nm_device_activate_ip4_state_in_conf(device)) - nm_device_activate_schedule_ip_config_timeout(device, AF_INET); - else if (nm_device_activate_ip6_state_in_conf(device)) - nm_device_activate_schedule_ip_config_timeout(device, AF_INET6); - else if (nm_device_activate_ip4_state_done(device)) { - nm_device_ip_method_failed(device, - AF_INET, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else if (nm_device_activate_ip6_state_done(device)) { - nm_device_ip_method_failed(device, - AF_INET6, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else { - _LOGW(LOGD_MB, - "PPP failure in unexpected state %u", - (guint) nm_device_get_state(device)); - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - break; - default: - break; - } + nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason); } static void modem_prepare_result(NMModem *modem, gboolean success, guint i_reason, gpointer user_data) { - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); + NMDeviceModem *self = NM_DEVICE_MODEM(user_data); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); NMDeviceStateReason reason = i_reason; if (nm_device_get_state(device) != NM_DEVICE_STATE_PREPARE @@ -173,7 +141,7 @@ modem_auth_requested(NMModem *modem, gpointer user_data) static void modem_auth_result(NMModem *modem, GError *error, gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); + NMDevice *device = NM_DEVICE(user_data); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); g_return_if_fail(nm_device_get_state(device) == NM_DEVICE_STATE_NEED_AUTH); @@ -188,102 +156,50 @@ modem_auth_result(NMModem *modem, GError *error, gpointer user_data) } static void -modem_ip4_config_result(NMModem *modem, NMIP4Config *config, GError *error, gpointer user_data) -{ - NMDeviceModem *self = NM_DEVICE_MODEM(user_data); - NMDevice * device = NM_DEVICE(self); - - if (!nm_device_activate_ip4_state_in_conf(device)) { - _LOGD(LOGD_MB | LOGD_IP4, - "retrieving IPv4 configuration while no longer in state IPv4 conf"); +modem_new_config(NMModem *modem, + int addr_family, + const NML3ConfigData *l3cd, + gboolean do_auto, + const NMUtilsIPv6IfaceId *iid, + int failure_reason_i, + GError *error, + gpointer user_data) +{ + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDeviceModem *self = NM_DEVICE_MODEM(user_data); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); + NMDevice *device = NM_DEVICE(self); + + if (nm_device_devip_get_state(device, addr_family) != NM_DEVICE_IP_STATE_PENDING) { + _LOGD(LOGD_MB, "retrieving IP configuration while no longer in pending state"); return; } if (error) { - _LOGW(LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: %s", error->message); - nm_device_ip_method_failed(device, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } - - nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG_CAST(config)); - nm_device_activate_schedule_ip_config_result(device, AF_INET, NULL); -} - -static void -modem_ip6_config_result(NMModem * modem, - NMIP6Config *config, - gboolean do_slaac, - GError * error, - gpointer user_data) -{ - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); - NMDevice * device = NM_DEVICE(self); - NMActStageReturn ret; - NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - gs_unref_object NMIP6Config *ignored = NULL; - gboolean got_config = !!config; - - if (!nm_device_activate_ip6_state_in_conf(device)) { - _LOGD(LOGD_MB | LOGD_IP6, - "retrieving IPv6 configuration while no longer in state IPv6 conf"); + _LOGW(LOGD_MB, "retrieving IP configuration failed: %s", error->message); + nm_device_devip_set_failed(device, addr_family, failure_reason_i); return; } - if (error) { - _LOGW(LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: %s", error->message); - nm_device_ip_method_failed(device, AF_INET6, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } + if (!IS_IPv4) + priv->iid = iid ? *iid : ((NMUtilsIPv6IfaceId) NM_UTILS_IPV6_IFACE_ID_INIT); - /* Re-enable IPv6 on the interface */ - nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "0"); - - if (config) - nm_device_set_dev2_ip_config(device, AF_INET6, NM_IP_CONFIG_CAST(config)); - - if (do_slaac == FALSE) { - if (got_config) - nm_device_activate_schedule_ip_config_result(device, AF_INET6, NULL); - else { - _LOGW(LOGD_MB | LOGD_IP6, - "retrieving IPv6 configuration failed: SLAAC not requested and no addresses"); - nm_device_ip_method_failed(device, - AF_INET6, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - return; + if (do_auto) { + if (IS_IPv4) + nm_device_ip_method_dhcp4_start(device); + else + nm_device_ip_method_autoconf6_start(device); } - /* Start SLAAC now that we have a link-local address from the modem */ - ret = - NM_DEVICE_CLASS(nm_device_modem_parent_class) - ->act_stage3_ip_config_start(device, AF_INET6, (gpointer *) &ignored, &failure_reason); - - nm_assert(ignored == NULL); - - switch (ret) { - case NM_ACT_STAGE_RETURN_FAILURE: - nm_device_ip_method_failed(device, AF_INET6, failure_reason); - break; - case NM_ACT_STAGE_RETURN_IP_FAIL: - /* all done */ - nm_device_activate_schedule_ip_config_result(device, AF_INET6, NULL); - break; - case NM_ACT_STAGE_RETURN_POSTPONE: - /* let SLAAC run */ - break; - default: - /* Should never get here since we've assured that the IPv6 method - * will either be "auto" or "ignored" when starting IPv6 configuration. - */ - nm_assert_not_reached(); - } + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, l3cd); } static void ip_ifindex_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) { - NMDevice *device = NM_DEVICE(user_data); + NMDevice *device = NM_DEVICE(user_data); + NMDeviceModem *self = NM_DEVICE_MODEM(device); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); if (!nm_device_is_activating(device)) return; @@ -300,14 +216,19 @@ ip_ifindex_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) * RA handling code to run before NM is ready. */ nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "1"); + + if (priv->stage2_state == NM_DEVICE_STAGE_STATE_PENDING) { + priv->stage2_state = NM_DEVICE_STAGE_STATE_COMPLETED; + nm_device_activate_schedule_stage2_device_config(device, FALSE); + } } static void operator_code_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) { - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); + NMDeviceModem *self = NM_DEVICE_MODEM(user_data); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - const char * operator_code = nm_modem_get_operator_code(modem); + const char *operator_code = nm_modem_get_operator_code(modem); if (g_strcmp0(priv->operator_code, operator_code) != 0) { g_free(priv->operator_code); @@ -319,9 +240,9 @@ operator_code_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) static void apn_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) { - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); + NMDeviceModem *self = NM_DEVICE_MODEM(user_data); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - const char * apn = nm_modem_get_apn(modem); + const char *apn = nm_modem_get_apn(modem); if (g_strcmp0(priv->apn, apn) != 0) { g_free(priv->apn); @@ -341,7 +262,7 @@ modem_state_cb(NMModem *modem, int new_state_i, int old_state_i, gpointer user_d { NMModemState new_state = new_state_i; NMModemState old_state = old_state_i; - NMDevice * device = NM_DEVICE(user_data); + NMDevice *device = NM_DEVICE(user_data); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); NMDeviceState dev_state = nm_device_get_state(device); @@ -413,12 +334,12 @@ owns_iface(NMDevice *device, const char *iface) /*****************************************************************************/ static void -device_state_changed(NMDevice * device, +device_state_changed(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason) { - NMDeviceModem * self = NM_DEVICE_MODEM(device); + NMDeviceModem *self = NM_DEVICE_MODEM(device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); g_return_if_fail(priv->modem); @@ -480,13 +401,13 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -check_connection_available(NMDevice * device, - NMConnection * connection, +check_connection_available(NMDevice *device, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error) + const char *specific_object, + GError **error) { - NMDeviceModem * self = NM_DEVICE_MODEM(device); + NMDeviceModem *self = NM_DEVICE_MODEM(device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); NMModemState state; @@ -525,11 +446,11 @@ check_connection_available(NMDevice * device, } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); @@ -547,6 +468,7 @@ deactivate(NMDevice *device) nm_modem_deactivate(priv->modem, device); priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT; + priv->stage2_state = NM_DEVICE_STAGE_STATE_INIT; } /*****************************************************************************/ @@ -554,7 +476,7 @@ deactivate(NMDevice *device) static void modem_deactivate_async_cb(NMModem *modem, GError *error, gpointer user_data) { - gs_unref_object NMDevice * self = NULL; + gs_unref_object NMDevice *self = NULL; NMDeviceDeactivateCallback callback; gpointer callback_user_data; @@ -563,8 +485,8 @@ modem_deactivate_async_cb(NMModem *modem, GError *error, gpointer user_data) } static void -deactivate_async(NMDevice * self, - GCancellable * cancellable, +deactivate_async(NMDevice *self, + GCancellable *cancellable, NMDeviceDeactivateCallback callback, gpointer user_data) { @@ -584,7 +506,7 @@ static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - NMActRequest * req; + NMActRequest *req; req = nm_device_get_act_request(device); g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); @@ -606,51 +528,44 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - nm_modem_act_stage2_config(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem); - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - gboolean autoip4 = FALSE; - NMActStageReturn ret; - - if (!NM_IS_IPv4(addr_family)) - return nm_modem_stage3_ip6_config_start(priv->modem, device, out_failure_reason); - - ret = nm_modem_stage3_ip4_config_start(priv->modem, device, &autoip4, out_failure_reason); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS || !autoip4) - return ret; + if (priv->stage2_state == NM_DEVICE_STAGE_STATE_INIT) { + priv->stage2_state = NM_DEVICE_STAGE_STATE_PENDING; + return nm_modem_act_stage2_config(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, + device, + out_failure_reason); + } + if (priv->stage2_state == NM_DEVICE_STAGE_STATE_PENDING) + return NM_ACT_STAGE_RETURN_POSTPONE; - return NM_DEVICE_CLASS(nm_device_modem_parent_class) - ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); + nm_assert(priv->stage2_state == NM_DEVICE_STAGE_STATE_COMPLETED); + return NM_ACT_STAGE_RETURN_SUCCESS; } static void -ip4_config_pre_commit(NMDevice *device, NMIP4Config *config) +act_stage3_ip_config(NMDevice *device, int addr_family) { - nm_modem_ip4_pre_commit(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, device, config); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); + + if (nm_modem_stage3_ip_config_start(priv->modem, addr_family, device)) + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL); } static gboolean get_ip_iface_identifier(NMDevice *device, NMUtilsIPv6IfaceId *out_iid) { - NMDeviceModem * self = NM_DEVICE_MODEM(device); + NMDeviceModem *self = NM_DEVICE_MODEM(device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - gboolean success; g_return_val_if_fail(priv->modem, FALSE); - success = nm_modem_get_iid(priv->modem, out_iid); - if (!success) - success = - NM_DEVICE_CLASS(nm_device_modem_parent_class)->get_ip_iface_identifier(device, out_iid); - return success; + + if (priv->iid.id != 0) { + *out_iid = priv->iid; + return TRUE; + } + + return NM_DEVICE_CLASS(nm_device_modem_parent_class)->get_ip_iface_identifier(device, out_iid); } /*****************************************************************************/ @@ -667,7 +582,7 @@ get_enabled(NMDevice *device) static void set_enabled(NMDevice *device, gboolean enabled) { - NMDeviceModem * self = NM_DEVICE_MODEM(device); + NMDeviceModem *self = NM_DEVICE_MODEM(device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); /* Called only by the Manager in response to rfkill switch changes or @@ -688,7 +603,7 @@ set_enabled(NMDevice *device, gboolean enabled) static gboolean is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) { - NMDeviceModem * self = NM_DEVICE_MODEM(device); + NMDeviceModem *self = NM_DEVICE_MODEM(device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); NMModemState modem_state; @@ -703,6 +618,16 @@ is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) return TRUE; } +static gboolean +ready_for_ip_config(NMDevice *device) +{ + /* Tell NMDevice to only run device-specific IP + * configuration (devip) and skip other methods + * (manual, dhcp, etc). + */ + return FALSE; +} + /*****************************************************************************/ static void @@ -716,8 +641,7 @@ set_modem(NMDeviceModem *self, NMModem *modem) g_signal_connect(modem, NM_MODEM_PPP_FAILED, G_CALLBACK(ppp_failed), self); g_signal_connect(modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK(modem_prepare_result), self); - g_signal_connect(modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK(modem_ip4_config_result), self); - g_signal_connect(modem, NM_MODEM_IP6_CONFIG_RESULT, G_CALLBACK(modem_ip6_config_result), self); + g_signal_connect(modem, NM_MODEM_NEW_CONFIG, G_CALLBACK(modem_new_config), self); g_signal_connect(modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK(modem_auth_requested), self); g_signal_connect(modem, NM_MODEM_AUTH_RESULT, G_CALLBACK(modem_auth_result), self); g_signal_connect(modem, NM_MODEM_STATE_CHANGED, G_CALLBACK(modem_state_cb), self); @@ -838,9 +762,9 @@ nm_device_modem_new(NMModem *modem) NM_DEVICE_MODEM_MODEM, modem, NM_DEVICE_MODEM_CAPABILITIES, - caps, + (guint) ((guint32) caps), NM_DEVICE_MODEM_CURRENT_CAPABILITIES, - current_caps, + (guint) ((guint32) current_caps), NM_DEVICE_MODEM_DEVICE_ID, nm_modem_get_device_id(modem), NULL); @@ -885,9 +809,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_modem = { static void nm_device_modem_class_init(NMDeviceModemClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->dispose = dispose; object_class->get_property = get_property; @@ -904,8 +828,7 @@ nm_device_modem_class_init(NMDeviceModemClass *klass) device_class->deactivate = deactivate; device_class->act_stage1_prepare = act_stage1_prepare; device_class->act_stage2_config = act_stage2_config; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; - device_class->ip4_config_pre_commit = ip4_config_pre_commit; + device_class->act_stage3_ip_config = act_stage3_ip_config; device_class->get_enabled = get_enabled; device_class->set_enabled = set_enabled; device_class->owns_iface = owns_iface; @@ -913,6 +836,7 @@ nm_device_modem_class_init(NMDeviceModemClass *klass) device_class->get_ip_iface_identifier = get_ip_iface_identifier; device_class->get_configured_mtu = nm_modem_get_configured_mtu; device_class->get_dhcp_timeout_for_device = get_dhcp_timeout_for_device; + device_class->ready_for_ip_config = ready_for_ip_config; device_class->state_changed = device_state_changed; diff --git a/src/core/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c index a5139f08..f5336d37 100644 --- a/src/core/devices/wwan/nm-modem-broadband.c +++ b/src/core/devices/wwan/nm-modem-broadband.c @@ -16,29 +16,20 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" #include "libnm-platform/nm-platform.h" -#include "nm-ip4-config.h" -#include "nm-ip6-config.h" +#include "nm-l3-config-data.h" #define NM_MODEM_BROADBAND_MODEM "modem" -static gboolean -MODEM_CAPS_3GPP(MMModemCapability caps) -{ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - /* MM_MODEM_CAPABILITY_LTE_ADVANCED is marked as deprecated since ModemManager 1.14.0. - * - * The flag probably was never used, it certainly isn't used since 1.14.0. - * - * Still, just to be sure, there is no harm in checking it here. Suppress the - * warning, it should have no bad effect. - */ - return NM_FLAGS_ANY(caps, - (MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_LTE - | MM_MODEM_CAPABILITY_LTE_ADVANCED)); - G_GNUC_END_IGNORE_DEPRECATIONS -} +#if !MM_CHECK_VERSION(1, 14, 0) +#define MM_MODEM_CAPABILITY_5GNR ((MMModemCapability) (1 << 6)) +#endif + +#define MODEM_CAPS_3GPP(caps) \ + NM_FLAGS_ANY( \ + caps, \ + (MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_LTE | MM_MODEM_CAPABILITY_5GNR)) -#define MODEM_CAPS_3GPP2(caps) (caps & (MM_MODEM_CAPABILITY_CDMA_EVDO)) +#define MODEM_CAPS_3GPP2(caps) NM_FLAGS_ANY((caps), MM_MODEM_CAPABILITY_CDMA_EVDO) /* Maximum time to keep the DBus call waiting for a connection result. * This value is greater than the default timeout in ModemManager (180s since @@ -62,13 +53,13 @@ typedef struct { ConnectStep step; MMModemCapability caps; - NMConnection * connection; - GCancellable * cancellable; + NMConnection *connection; + GCancellable *cancellable; MMSimpleConnectProperties *connect_properties; - GArray * ip_types; + GArray *ip_types; guint ip_types_i; guint ip_type_tries; - GError * first_error; + GError *first_error; } ConnectContext; /*****************************************************************************/ @@ -79,21 +70,18 @@ typedef struct { /* The modem object from dbus */ MMObject *modem_object; /* Per-interface objects */ - MMModem * modem_iface; - MMModem3gpp * modem_3gpp_iface; + MMModem *modem_iface; + MMModem3gpp *modem_3gpp_iface; MMModemSimple *simple_iface; - MMSim * sim_iface; + MMSim *sim_iface; /* Connection setup */ ConnectContext *ctx; - MMBearer * bearer; + MMBearer *bearer; MMBearerIpConfig *ipv4_config; MMBearerIpConfig *ipv6_config; - guint idle_id_ip4; - guint idle_id_ip6; - guint32 pin_tries; } NMModemBroadbandPrivate; @@ -123,7 +111,7 @@ G_DEFINE_TYPE(NMModemBroadband, nm_modem_broadband, NM_TYPE_MODEM) if (nm_logging_enabled(_level, (_NMLOG_DOMAIN))) { \ NMModemBroadband *const __self = (self); \ char __prefix_name[128]; \ - const char * __uid; \ + const char *__uid; \ \ _nm_log(_level, \ (_NMLOG_DOMAIN), \ @@ -199,24 +187,28 @@ translate_mm_error(NMModemBroadband *self, GError *error) /*****************************************************************************/ static void -get_capabilities(NMModem * _self, +get_capabilities(NMModem *_self, NMDeviceModemCapabilities *modem_caps, NMDeviceModemCapabilities *current_caps) { - NMModemBroadband * self = NM_MODEM_BROADBAND(_self); - MMModemCapability all_supported = MM_MODEM_CAPABILITY_NONE; - MMModemCapability *supported; - guint n_supported; + NMModemBroadband *self = NM_MODEM_BROADBAND(_self); + MMModemCapability all_supported = MM_MODEM_CAPABILITY_NONE; + gs_free MMModemCapability *supported = NULL; + guint n_supported; + guint i; + + G_STATIC_ASSERT(MM_MODEM_CAPABILITY_POTS == (guint64) NM_DEVICE_MODEM_CAPABILITY_POTS); + G_STATIC_ASSERT(MM_MODEM_CAPABILITY_CDMA_EVDO + == (guint64) NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO); + G_STATIC_ASSERT(MM_MODEM_CAPABILITY_GSM_UMTS == (guint64) NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS); + G_STATIC_ASSERT(MM_MODEM_CAPABILITY_LTE == (guint64) NM_DEVICE_MODEM_CAPABILITY_LTE); + G_STATIC_ASSERT(MM_MODEM_CAPABILITY_5GNR == (guint64) NM_DEVICE_MODEM_CAPABILITY_5GNR); /* For now, we don't care about the capability combinations, just merge all * combinations in a single mask */ if (mm_modem_get_supported_capabilities(self->_priv.modem_iface, &supported, &n_supported)) { - guint i; - for (i = 0; i < n_supported; i++) all_supported |= supported[i]; - - g_free(supported); } *modem_caps = (NMDeviceModemCapabilities) all_supported; @@ -227,7 +219,7 @@ get_capabilities(NMModem * _self, static gboolean owns_port(NMModem *_self, const char *iface) { - NMModemBroadband * self = NM_MODEM_BROADBAND(_self); + NMModemBroadband *self = NM_MODEM_BROADBAND(_self); const MMModemPortInfo *ports = NULL; guint n_ports = 0, i; @@ -278,7 +270,7 @@ create_cdma_connect_properties(NMConnection *connection) #if !MM_CHECK_VERSION(1, 9, 1) { NMSettingCdma *setting; - const char * str; + const char *str; setting = nm_connection_get_setting_cdma(connection); str = nm_setting_cdma_get_number(setting); @@ -292,14 +284,14 @@ create_cdma_connect_properties(NMConnection *connection) static MMSimpleConnectProperties * create_gsm_connect_properties(NMConnection *connection, - const char * apn, - const char * username, - const char * password) + const char *apn, + const char *username, + const char *password) { - NMSettingGsm * setting; - NMSettingPpp * s_ppp; + NMSettingGsm *setting; + NMSettingPpp *s_ppp; MMSimpleConnectProperties *properties; - const char * str; + const char *str; setting = nm_connection_get_setting_gsm(connection); @@ -369,11 +361,11 @@ static void connect_context_step(NMModemBroadband *self); static void connect_ready(MMModemSimple *simple_iface, GAsyncResult *res, NMModemBroadband *self) { - ConnectContext *ctx; - GError * error = NULL; - NMModemIPMethod ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; - NMModemIPMethod ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; - gs_unref_object MMBearer *bearer = NULL; + ConnectContext *ctx; + GError *error = NULL; + NMModemIPMethod ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; + NMModemIPMethod ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; + gs_unref_object MMBearer *bearer = NULL; bearer = mm_modem_simple_connect_finish(simple_iface, res, &error); @@ -480,18 +472,18 @@ send_pin_ready(MMSim *sim, GAsyncResult *result, NMModemBroadband *self) } static void -find_gsm_apn_cb(const char * apn, - const char * username, - const char * password, - const char * gateway, - const char * auth_method, +find_gsm_apn_cb(const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, const GSList *dns, - GError * error, + GError *error, gpointer user_data) { - NMModemBroadband * self = user_data; + NMModemBroadband *self = user_data; NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self); - ConnectContext * ctx = priv->ctx; + ConnectContext *ctx = priv->ctx; if (error) { _LOGW("failed to connect '%s': APN not found: %s", @@ -514,14 +506,14 @@ static gboolean try_create_connect_properties(NMModemBroadband *self) { NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self); - ConnectContext * ctx = priv->ctx; + ConnectContext *ctx = priv->ctx; if (MODEM_CAPS_3GPP(ctx->caps)) { NMSettingGsm *s_gsm = nm_connection_get_setting_gsm(ctx->connection); if (!s_gsm || nm_setting_gsm_get_auto_config(s_gsm)) { gs_unref_object MMModem3gpp *modem_3gpp = NULL; - const char * network_id = NULL; + const char *network_id = NULL; s_gsm = nm_connection_get_setting_gsm(ctx->connection); if (s_gsm) @@ -590,7 +582,7 @@ connect_context_step(NMModemBroadband *self) if (MODEM_CAPS_3GPP(ctx->caps) && mm_modem_get_unlock_required(self->_priv.modem_iface) == MM_MODEM_LOCK_SIM_PIN) { NMSettingGsm *s_gsm = nm_connection_get_setting_gsm(ctx->connection); - const char * pin = nm_setting_gsm_get_pin(s_gsm); + const char *pin = nm_setting_gsm_get_pin(s_gsm); /* If we have a PIN already, send it. If we don't, get it. */ if (pin) { @@ -698,8 +690,8 @@ connect_context_step(NMModemBroadband *self) } static NMActStageReturn -modem_act_stage1_prepare(NMModem * _self, - NMConnection * connection, +modem_act_stage1_prepare(NMModem *_self, + NMConnection *connection, NMDeviceStateReason *out_failure_reason) { NMModemBroadband *self = NM_MODEM_BROADBAND(_self); @@ -772,15 +764,15 @@ check_connection_compatible_with_modem(NMModem *_self, NMConnection *connection, /*****************************************************************************/ static gboolean -complete_connection(NMModem * modem, - const char * iface, - NMConnection * connection, +complete_connection(NMModem *modem, + const char *iface, + NMConnection *connection, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMModemBroadband *self = NM_MODEM_BROADBAND(modem); MMModemCapability modem_caps; - NMSettingPpp * s_ppp; + NMSettingPpp *s_ppp; modem_caps = mm_modem_get_current_capabilities(self->_priv.modem_iface); @@ -860,7 +852,7 @@ complete_connection(NMModem * modem, static gboolean get_user_pass(NMModem *modem, NMConnection *connection, const char **user, const char **pass) { - NMSettingGsm * s_gsm; + NMSettingGsm *s_gsm; NMSettingCdma *s_cdma; s_gsm = nm_connection_get_setting_gsm(connection); @@ -958,259 +950,257 @@ set_mm_enabled(NMModem *_self, gboolean enabled) } /*****************************************************************************/ -/* IPv4 method static */ -static gboolean -static_stage3_ip4_done(NMModemBroadband *self) +static void +stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_method) { - GError * error = NULL; - gs_unref_object NMIP4Config *config = NULL; - const char * data_port; - const char * address_string; - const char * gw_string; - guint32 address_network; - guint32 gw = 0; - NMPlatformIP4Address address; - const char ** dns; - guint i; - guint32 ip4_route_table, ip4_route_metric; - NMPlatformIP4Route * r; - guint32 mtu_n; - - g_return_val_if_fail(self->_priv.ipv4_config, FALSE); - g_return_val_if_fail(self->_priv.bearer, FALSE); - - self->_priv.idle_id_ip4 = 0; - - _LOGI("IPv4 static configuration:"); - - /* Fully fail if invalid IP address retrieved */ - address_string = mm_bearer_ip_config_get_address(self->_priv.ipv4_config); - if (!address_string - || !nm_utils_parse_inaddr_bin(AF_INET, address_string, NULL, &address_network)) { - error = - g_error_new(NM_DEVICE_ERROR, + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMModemBroadband *self = NM_MODEM_BROADBAND(modem); + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + gs_free_error GError *error = NULL; + const char *data_port; + const char *address_string; + const char **dns; + guint i; + gboolean do_auto = FALSE; + int ifindex; + NMUtilsIPv6IfaceId iid_data; + const NMUtilsIPv6IfaceId *iid = NULL; + + if (IS_IPv4) { + g_return_if_fail(self->_priv.ipv4_config); + g_return_if_fail(self->_priv.bearer); + + if (ip_method == NM_MODEM_IP_METHOD_AUTO) { + do_auto = TRUE; + goto out; + } + } else { + g_return_if_fail(self->_priv.ipv6_config); + } + + if (IS_IPv4) { + guint32 address_network; + guint32 gw = 0; + NMPlatformIP4Address address; + NMPlatformIP4Route route; + guint32 mtu_n; + const char *gw_string; + + _LOGI("IPv4 static configuration:"); + + /* Fully fail if invalid IP address retrieved */ + address_string = mm_bearer_ip_config_get_address(self->_priv.ipv4_config); + if (!address_string + || !nm_utils_parse_inaddr_bin(AF_INET, address_string, NULL, &address_network)) { + g_set_error(&error, + NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, "(%s) retrieving IP4 configuration failed: invalid address given %s%s%s", nm_modem_get_uid(NM_MODEM(self)), NM_PRINT_FMT_QUOTE_STRING(address_string)); - goto out; - } + goto out; + } - /* Missing gateway not a hard failure */ - gw_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv4_config); - if (gw_string && !nm_utils_parse_inaddr_bin(AF_INET, gw_string, NULL, &gw)) { - error = - g_error_new(NM_DEVICE_ERROR, + /* Missing gateway not a hard failure */ + gw_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv4_config); + if (gw_string && !nm_utils_parse_inaddr_bin(AF_INET, gw_string, NULL, &gw)) { + g_set_error(&error, + NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, "(%s) retrieving IP4 configuration failed: invalid gateway address \"%s\"", nm_modem_get_uid(NM_MODEM(self)), gw_string); - goto out; - } - - data_port = mm_bearer_get_interface(self->_priv.bearer); - g_return_val_if_fail(data_port, FALSE); - config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), - nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port)); - - memset(&address, 0, sizeof(address)); - address.address = address_network; - address.peer_address = address_network; - address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv4_config); - address.addr_source = NM_IP_CONFIG_SOURCE_WWAN; - if (address.plen <= 32) - nm_ip4_config_add_address(config, &address); - - _LOGI(" address %s/%d", address_string, address.plen); - - nm_modem_get_route_parameters(NM_MODEM(self), &ip4_route_table, &ip4_route_metric, NULL, NULL); - r = &(NMPlatformIP4Route){ - .rt_source = NM_IP_CONFIG_SOURCE_WWAN, - .gateway = gw, - .table_coerced = nm_platform_route_table_coerce(ip4_route_table), - .metric = ip4_route_metric, - }; - nm_ip4_config_add_route(config, r, NULL); - _LOGI(" gateway %s", gw_string); - - /* DNS servers */ - dns = mm_bearer_ip_config_get_dns(self->_priv.ipv4_config); - for (i = 0; dns && dns[i]; i++) { - if (nm_utils_parse_inaddr_bin(AF_INET, dns[i], NULL, &address_network) - && address_network > 0) { - nm_ip4_config_add_nameserver(config, address_network); - _LOGI(" DNS %s", dns[i]); + goto out; } - } -#if MM_CHECK_VERSION(1, 4, 0) - mtu_n = mm_bearer_ip_config_get_mtu(self->_priv.ipv4_config); - if (mtu_n) { - nm_ip4_config_set_mtu(config, mtu_n, NM_IP_CONFIG_SOURCE_WWAN); - _LOGI(" MTU %u", mtu_n); - } -#endif - -out: - g_signal_emit_by_name(self, NM_MODEM_IP4_CONFIG_RESULT, config, error); - g_clear_error(&error); - return FALSE; -} + data_port = mm_bearer_get_interface(self->_priv.bearer); + g_return_if_fail(data_port); -static NMActStageReturn -static_stage3_ip4_config_start(NMModem * modem, - NMActRequest * req, - NMDeviceStateReason *out_failure_reason) -{ - NMModemBroadband * self = NM_MODEM_BROADBAND(modem); - NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self); + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port); + if (ifindex <= 0) { + g_set_error(&error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "(%s) data port %s not found", + nm_modem_get_uid(NM_MODEM(self)), + data_port); + goto out; + } - /* We schedule it in an idle just to follow the same logic as in the - * generic modem implementation. */ - nm_clear_g_source(&priv->idle_id_ip4); - priv->idle_id_ip4 = g_idle_add((GSourceFunc) static_stage3_ip4_done, self); + l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), + ifindex, + NM_IP_CONFIG_SOURCE_WWAN); + + address = (NMPlatformIP4Address){ + .address = address_network, + .peer_address = address_network, + .plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv4_config), + .addr_source = NM_IP_CONFIG_SOURCE_WWAN, + }; + if (address.plen <= 32) + nm_l3_config_data_add_address_4(l3cd, &address); + + _LOGI(" address %s", nm_platform_ip4_address_to_string(&address, sbuf, sizeof(sbuf))); + + route = (NMPlatformIP4Route){ + .rt_source = NM_IP_CONFIG_SOURCE_WWAN, + .gateway = gw, + .table_any = TRUE, + .table_coerced = 0, + .metric_any = TRUE, + .metric = 0, + }; + nm_l3_config_data_add_route_4(l3cd, &route); + _LOGI(" gateway %s", gw_string); + + dns = mm_bearer_ip_config_get_dns(self->_priv.ipv4_config); + for (i = 0; dns && dns[i]; i++) { + if (nm_utils_parse_inaddr_bin(AF_INET, dns[i], NULL, &address_network) + && address_network > 0) { + nm_l3_config_data_add_nameserver(l3cd, AF_INET, &address_network); + _LOGI(" DNS %s", dns[i]); + } + } - return NM_ACT_STAGE_RETURN_POSTPONE; -} +#if MM_CHECK_VERSION(1, 4, 0) + mtu_n = mm_bearer_ip_config_get_mtu(self->_priv.ipv4_config); + if (mtu_n) { + nm_l3_config_data_set_mtu(l3cd, mtu_n); + _LOGI(" MTU %u", mtu_n); + } +#endif + } else { + NMPlatformIP6Address address; + + address_string = mm_bearer_ip_config_get_address(self->_priv.ipv6_config); + if (!address_string) { + /* DHCP/SLAAC is allowed to skip addresses; other methods require it */ + if (ip_method != NM_MODEM_IP_METHOD_AUTO) { + g_set_error(&error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "(%s) retrieving IPv6 configuration failed: no address given", + nm_modem_get_uid(NM_MODEM(self))); + } + goto out; + } -/*****************************************************************************/ -/* IPv6 method static */ + address = (NMPlatformIP6Address){}; -static gboolean -stage3_ip6_done(NMModemBroadband *self) -{ - GError * error = NULL; - NMIP6Config * config = NULL; - const char * data_port; - const char * address_string; - NMPlatformIP6Address address; - NMModemIPMethod ip_method; - const char ** dns; - guint i; - - g_return_val_if_fail(self->_priv.ipv6_config, FALSE); - - self->_priv.idle_id_ip6 = 0; - memset(&address, 0, sizeof(address)); - - ip_method = get_bearer_ip_method(self->_priv.ipv6_config); - - address_string = mm_bearer_ip_config_get_address(self->_priv.ipv6_config); - if (!address_string) { - /* DHCP/SLAAC is allowed to skip addresses; other methods require it */ - if (ip_method != NM_MODEM_IP_METHOD_AUTO) { - error = g_error_new(NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "(%s) retrieving IPv6 configuration failed: no address given", - nm_modem_get_uid(NM_MODEM(self))); + if (!inet_pton(AF_INET6, address_string, &address.address)) { + g_set_error(&error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "(%s) retrieving IPv6 configuration failed: invalid address given '%s'", + nm_modem_get_uid(NM_MODEM(self)), + address_string); + goto out; } - goto out; - } - /* Fail if invalid IP address retrieved */ - if (!inet_pton(AF_INET6, address_string, (void *) &(address.address))) { - error = g_error_new(NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "(%s) retrieving IPv6 configuration failed: invalid address given '%s'", - nm_modem_get_uid(NM_MODEM(self)), - address_string); - goto out; - } + data_port = mm_bearer_get_interface(self->_priv.bearer); + g_return_if_fail(data_port); - _LOGI("IPv6 base configuration:"); + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port); + if (ifindex <= 0) { + g_set_error(&error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "(%s) data port %s not found", + nm_modem_get_uid(NM_MODEM(self)), + data_port); + goto out; + } - data_port = mm_bearer_get_interface(self->_priv.bearer); - g_return_val_if_fail(data_port, FALSE); + _LOGI("IPv6 base configuration:"); - config = nm_ip6_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), - nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port)); + l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), + ifindex, + NM_IP_CONFIG_SOURCE_WWAN); - address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv6_config); - if (address.plen <= 128) - nm_ip6_config_add_address(config, &address); + do_auto = TRUE; - _LOGI(" address %s/%d", address_string, address.plen); + address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv6_config); + if (address.plen <= 128) { + if (IN6_IS_ADDR_LINKLOCAL(&address.address)) { + iid_data.id = ((guint64 *) (&address.address.s6_addr))[1]; + iid = &iid_data; + } else + do_auto = FALSE; + nm_l3_config_data_add_address_6(l3cd, &address); + } - address_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv6_config); - if (address_string) { - guint32 ip6_route_table, ip6_route_metric; + _LOGI(" address %s (slaac %s)", + nm_platform_ip6_address_to_string(&address, sbuf, sizeof(sbuf)), + do_auto ? "enabled" : "disabled"); - if (inet_pton(AF_INET6, address_string, &address.address) != 1) { - error = - g_error_new(NM_DEVICE_ERROR, + address_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv6_config); + if (address_string) { + if (inet_pton(AF_INET6, address_string, &address.address) != 1) { + g_set_error(&error, + NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, "(%s) retrieving IPv6 configuration failed: invalid gateway given '%s'", nm_modem_get_uid(NM_MODEM(self)), address_string); - goto out; - } + goto out; + } - nm_modem_get_route_parameters(NM_MODEM(self), - NULL, - NULL, - &ip6_route_table, - &ip6_route_metric); - { - const NMPlatformIP6Route r = { - .rt_source = NM_IP_CONFIG_SOURCE_WWAN, - .gateway = address.address, - .table_coerced = nm_platform_route_table_coerce(ip6_route_table), - .metric = ip6_route_metric, - }; - - _LOGI(" gateway %s", address_string); - nm_ip6_config_add_route(config, &r, NULL); + { + const NMPlatformIP6Route r = { + .rt_source = NM_IP_CONFIG_SOURCE_WWAN, + .gateway = address.address, + .table_any = TRUE, + .table_coerced = 0, + .metric_any = TRUE, + .metric = 0, + }; + + _LOGI(" gateway %s", address_string); + nm_l3_config_data_add_route_6(l3cd, &r); + } + } else if (ip_method == NM_MODEM_IP_METHOD_STATIC) { + /* Gateway required for the 'static' method */ + g_set_error(&error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "(%s) retrieving IPv6 configuration failed: missing gateway", + nm_modem_get_uid(NM_MODEM(self))); + goto out; } - } else if (ip_method == NM_MODEM_IP_METHOD_STATIC) { - /* Gateway required for the 'static' method */ - error = g_error_new(NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "(%s) retrieving IPv6 configuration failed: missing gateway", - nm_modem_get_uid(NM_MODEM(self))); - goto out; - } - /* DNS servers */ - dns = mm_bearer_ip_config_get_dns(self->_priv.ipv6_config); - for (i = 0; dns && dns[i]; i++) { - struct in6_addr addr; + dns = mm_bearer_ip_config_get_dns(self->_priv.ipv6_config); + for (i = 0; dns && dns[i]; i++) { + struct in6_addr addr; - if (inet_pton(AF_INET6, dns[i], &addr)) { - nm_ip6_config_add_nameserver(config, &addr); - _LOGI(" DNS %s", dns[i]); + if (inet_pton(AF_INET6, dns[i], &addr)) { + nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &addr); + _LOGI(" DNS %s", dns[i]); + } } } out: - nm_modem_emit_ip6_config_result(NM_MODEM(self), config, error); - g_clear_object(&config); - g_clear_error(&error); - return FALSE; -} - -static NMActStageReturn -stage3_ip6_config_request(NMModem *modem, NMDeviceStateReason *out_failure_reason) -{ - NMModemBroadband * self = NM_MODEM_BROADBAND(modem); - NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self); - - /* We schedule it in an idle just to follow the same logic as in the - * generic modem implementation. */ - nm_clear_g_source(&priv->idle_id_ip6); - priv->idle_id_ip6 = g_idle_add((GSourceFunc) stage3_ip6_done, self); + if (error) { + nm_modem_emit_signal_new_config_failure(modem, + addr_family, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE, + error); + return; + } - return NM_ACT_STAGE_RETURN_POSTPONE; + nm_modem_emit_signal_new_config_success(modem, addr_family, l3cd, do_auto, iid); } /*****************************************************************************/ /* Disconnect */ typedef struct { - NMModemBroadband * self; + NMModemBroadband *self; _NMModemDisconnectCallback callback; gpointer callback_user_data; - GCancellable * cancellable; + GCancellable *cancellable; gboolean warn; } DisconnectContext; @@ -1227,7 +1217,7 @@ disconnect_context_complete(DisconnectContext *ctx, GError *error) static void disconnect_context_complete_on_idle(gpointer user_data, GCancellable *cancellable) { - DisconnectContext *ctx = user_data; + DisconnectContext *ctx = user_data; gs_free_error GError *cancelled_error = NULL; g_cancellable_set_error_if_cancelled(cancellable, &cancelled_error); @@ -1237,9 +1227,9 @@ disconnect_context_complete_on_idle(gpointer user_data, GCancellable *cancellabl static void simple_disconnect_ready(GObject *source_object, GAsyncResult *res, gpointer user_data) { - MMModemSimple * modem_iface = MM_MODEM_SIMPLE(source_object); - DisconnectContext *ctx = user_data; - gs_free_error GError *error = NULL; + MMModemSimple *modem_iface = MM_MODEM_SIMPLE(source_object); + DisconnectContext *ctx = user_data; + gs_free_error GError *error = NULL; if (!mm_modem_simple_disconnect_finish(modem_iface, res, &error)) { if (ctx->warn && !g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { @@ -1253,13 +1243,13 @@ simple_disconnect_ready(GObject *source_object, GAsyncResult *res, gpointer user } static void -disconnect(NMModem * modem, +disconnect(NMModem *modem, gboolean warn, - GCancellable * cancellable, + GCancellable *cancellable, _NMModemDisconnectCallback callback, gpointer user_data) { - NMModemBroadband * self = NM_MODEM_BROADBAND(modem); + NMModemBroadband *self = NM_MODEM_BROADBAND(modem); DisconnectContext *ctx; connect_context_clear(self); @@ -1336,11 +1326,11 @@ mm_state_to_nm(MMModemState mm_state) } static void -modem_state_changed(MMModem * modem, +modem_state_changed(MMModem *modem, MMModemState old_state, MMModemState new_state, MMModemStateChangeReason reason, - NMModemBroadband * self) + NMModemBroadband *self) { /* After the SIM is unlocked MM1 will move the device to INITIALIZING which * is an unavailable state. That makes state handling confusing here, so @@ -1378,7 +1368,7 @@ static void get_sim_ready(MMModem *modem, GAsyncResult *res, NMModemBroadband *self) { GError *error = NULL; - MMSim * new_sim; + MMSim *new_sim; new_sim = mm_modem_get_sim_finish(modem, res, &error); if (new_sim != self->_priv.sim_iface) { @@ -1512,12 +1502,12 @@ nm_modem_broadband_init(NMModemBroadband *self) NMModem * nm_modem_broadband_new(GObject *object, GError **error) { - MMObject * modem_object; - MMModem * modem_iface; - MMModem3gpp * modem_3gpp_iface; + MMObject *modem_object; + MMModem *modem_iface; + MMModem3gpp *modem_3gpp_iface; const char *const *drivers; - const char * operator_code = NULL; - gs_free char * driver = NULL; + const char *operator_code = NULL; + gs_free char *driver = NULL; g_return_val_if_fail(MM_IS_OBJECT(object), NULL); modem_object = MM_OBJECT(object); @@ -1561,30 +1551,27 @@ nm_modem_broadband_new(GObject *object, GError **error) static void dispose(GObject *object) { - NMModemBroadband * self = NM_MODEM_BROADBAND(object); + NMModemBroadband *self = NM_MODEM_BROADBAND(object); NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self); - nm_clear_g_source(&priv->idle_id_ip4); - nm_clear_g_source(&priv->idle_id_ip6); - connect_context_clear(self); - g_clear_object(&self->_priv.ipv4_config); - g_clear_object(&self->_priv.ipv6_config); - g_clear_object(&self->_priv.bearer); + g_clear_object(&priv->ipv4_config); + g_clear_object(&priv->ipv6_config); + g_clear_object(&priv->bearer); - if (self->_priv.modem_iface) { - g_signal_handlers_disconnect_by_data(self->_priv.modem_iface, self); - g_clear_object(&self->_priv.modem_iface); + if (priv->modem_iface) { + g_signal_handlers_disconnect_by_data(priv->modem_iface, self); + g_clear_object(&priv->modem_iface); } - if (self->_priv.modem_3gpp_iface) { - g_signal_handlers_disconnect_by_data(self->_priv.modem_3gpp_iface, self); - g_clear_object(&self->_priv.modem_3gpp_iface); + if (priv->modem_3gpp_iface) { + g_signal_handlers_disconnect_by_data(priv->modem_3gpp_iface, self); + g_clear_object(&priv->modem_3gpp_iface); } - g_clear_object(&self->_priv.simple_iface); - g_clear_object(&self->_priv.sim_iface); - g_clear_object(&self->_priv.modem_object); + g_clear_object(&priv->simple_iface); + g_clear_object(&priv->sim_iface); + g_clear_object(&priv->modem_object); G_OBJECT_CLASS(nm_modem_broadband_parent_class)->dispose(object); } @@ -1600,8 +1587,7 @@ nm_modem_broadband_class_init(NMModemBroadbandClass *klass) object_class->set_property = set_property; modem_class->get_capabilities = get_capabilities; - modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start; - modem_class->stage3_ip6_config_request = stage3_ip6_config_request; + modem_class->stage3_ip_config_start = stage3_ip_config_start; modem_class->disconnect = disconnect; modem_class->deactivate_cleanup = deactivate_cleanup; modem_class->set_mm_enabled = set_mm_enabled; diff --git a/src/core/devices/wwan/nm-modem-manager.c b/src/core/devices/wwan/nm-modem-manager.c index 8d087d13..4a89f38e 100644 --- a/src/core/devices/wwan/nm-modem-manager.c +++ b/src/core/devices/wwan/nm-modem-manager.c @@ -45,7 +45,7 @@ typedef struct { GCancellable *main_cancellable; struct { - MMManager * manager; + MMManager *manager; GCancellable *poke_cancellable; gulong handle_name_owner_changed_id; gulong handle_object_added_id; @@ -61,15 +61,15 @@ typedef struct { LOG_AVAILABLE_NO, } log_available : 3; - GDBusProxy * proxy; + GDBusProxy *proxy; GCancellable *proxy_cancellable; guint proxy_ref_count; - char * proxy_name_owner; + char *proxy_name_owner; } modm; #if WITH_OFONO struct { - GDBusProxy * proxy; + GDBusProxy *proxy; GCancellable *cancellable; } ofono; #endif @@ -111,7 +111,7 @@ static void handle_new_modem(NMModemManager *self, NMModem *modem) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - const char * path; + const char *path; path = nm_modem_get_path(modem); if (g_hash_table_lookup(priv->modems, path)) { @@ -163,10 +163,10 @@ static void modm_handle_object_added(MMManager *modem_manager, MMObject *modem_object, NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - const char * path; - MMModem * modem_iface; - NMModem * modem; - GError * error = NULL; + const char *path; + MMModem *modem_iface; + NMModem *modem; + GError *error = NULL; /* Ensure we don't have the same modem already */ path = mm_object_get_path(modem_object); @@ -201,8 +201,8 @@ static void modm_handle_object_removed(MMManager *manager, MMObject *modem_object, NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - NMModem * modem; - const char * path; + NMModem *modem; + const char *path; path = mm_object_get_path(modem_object); modem = (NMModem *) g_hash_table_lookup(priv->modems, path); @@ -217,7 +217,7 @@ static void modm_manager_available(NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - GList * modems, *l; + GList *modems, *l; if (priv->modm.log_available != LOG_AVAILABLE_YES) { _LOGI("ModemManager %savailable", priv->modm.log_available ? "now " : ""); @@ -235,7 +235,7 @@ static void modm_handle_name_owner_changed(MMManager *modem_manager, GParamSpec *pspec, NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - char * name_owner; + char *name_owner; /* Quit poking, if any */ nm_clear_g_source(&priv->modm.relaunch_id); @@ -273,9 +273,9 @@ modm_handle_name_owner_changed(MMManager *modem_manager, GParamSpec *pspec, NMMo static void modm_manager_poke_cb(GObject *connection, GAsyncResult *res, gpointer user_data) { - NMModemManager * self; - NMModemManagerPrivate *priv; - gs_free_error GError *error = NULL; + NMModemManager *self; + NMModemManagerPrivate *priv; + gs_free_error GError *error = NULL; gs_unref_variant GVariant *result = NULL; result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(connection), res, &error); @@ -327,7 +327,7 @@ static void modm_manager_check_name_owner(NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - gs_free char * name_owner = NULL; + gs_free char *name_owner = NULL; name_owner = g_dbus_object_manager_client_get_name_owner( G_DBUS_OBJECT_MANAGER_CLIENT(priv->modm.manager)); @@ -344,10 +344,10 @@ modm_manager_check_name_owner(NMModemManager *self) static void modm_manager_new_cb(GObject *source, GAsyncResult *res, gpointer user_data) { - NMModemManager * self; + NMModemManager *self; NMModemManagerPrivate *priv; - gs_free_error GError *error = NULL; - MMManager * modem_manager; + gs_free_error GError *error = NULL; + MMManager *modem_manager; modem_manager = mm_manager_new_finish(res, &error); if (!modem_manager && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -445,7 +445,7 @@ static void modm_proxy_name_owner_reset(NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - char * name = NULL; + char *name = NULL; if (priv->modm.proxy) name = g_dbus_proxy_get_name_owner(priv->modm.proxy); @@ -469,10 +469,10 @@ modm_proxy_name_owner_changed_cb(GObject *object, GParamSpec *pspec, gpointer us static void modm_proxy_new_cb(GObject *source_object, GAsyncResult *result, gpointer user_data) { - NMModemManager * self; + NMModemManager *self; NMModemManagerPrivate *priv; - GDBusProxy * proxy; - gs_free_error GError *error = NULL; + GDBusProxy *proxy; + gs_free_error GError *error = NULL; proxy = g_dbus_proxy_new_for_bus_finish(result, &error); if (!proxy && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -567,7 +567,7 @@ static void ofono_create_modem(NMModemManager *self, const char *path) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - NMModem * modem = NULL; + NMModem *modem = NULL; /* Ensure duplicate modems aren't created. Because we're not using the * ObjectManager interface there's a race during oFono startup where we @@ -585,15 +585,15 @@ ofono_create_modem(NMModemManager *self, const char *path) static void ofono_signal_cb(GDBusProxy *proxy, - char * sender_name, - char * signal_name, - GVariant * parameters, + char *sender_name, + char *signal_name, + GVariant *parameters, gpointer user_data) { - NMModemManager * self = NM_MODEM_MANAGER(user_data); + NMModemManager *self = NM_MODEM_MANAGER(user_data); NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - char * object_path; - NMModem * modem; + char *object_path; + NMModem *modem; if (g_strcmp0(signal_name, "ModemAdded") == 0) { g_variant_get(parameters, "(oa{sv})", &object_path, NULL); @@ -619,12 +619,12 @@ ofono_signal_cb(GDBusProxy *proxy, static void ofono_enumerate_devices_done(GObject *proxy, GAsyncResult *res, gpointer user_data) { - NMModemManager * self; + NMModemManager *self; NMModemManagerPrivate *priv; - gs_free_error GError *error = NULL; - GVariant * results; - GVariantIter * iter; - const char * path; + gs_free_error GError *error = NULL; + GVariant *results; + GVariantIter *iter; + const char *path; results = g_dbus_proxy_call_finish(G_DBUS_PROXY(proxy), res, &error); if (!results && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -651,7 +651,7 @@ static void ofono_check_name_owner(NMModemManager *self, gboolean first_invocation) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - gs_free char * name_owner = NULL; + gs_free char *name_owner = NULL; name_owner = g_dbus_proxy_get_name_owner(G_DBUS_PROXY(priv->ofono.proxy)); if (name_owner) { @@ -670,7 +670,7 @@ ofono_check_name_owner(NMModemManager *self, gboolean first_invocation) self); } else { GHashTableIter iter; - NMModem * modem; + NMModem *modem; _LOGI("oFono is %savailable", first_invocation ? "not " : "no longer "); @@ -694,10 +694,10 @@ ofono_name_owner_changed(GDBusProxy *ofono_proxy, GParamSpec *pspec, NMModemMana static void ofono_proxy_new_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - NMModemManager * self; + NMModemManager *self; NMModemManagerPrivate *priv; - gs_free_error GError *error = NULL; - GDBusProxy * proxy; + gs_free_error GError *error = NULL; + GDBusProxy *proxy; proxy = g_dbus_proxy_new_finish(res, &error); if (!proxy && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -752,10 +752,10 @@ ofono_init_proxy(NMModemManager *self) static void bus_get_ready(GObject *source, GAsyncResult *res, gpointer user_data) { - NMModemManager * self; + NMModemManager *self; NMModemManagerPrivate *priv; - gs_free_error GError *error = NULL; - GDBusConnection * connection; + gs_free_error GError *error = NULL; + GDBusConnection *connection; connection = g_bus_get_finish(res, &error); if (!connection && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -782,7 +782,7 @@ bus_get_ready(GObject *source, GAsyncResult *res, gpointer user_data) static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMModemManager * self = NM_MODEM_MANAGER(object); + NMModemManager *self = NM_MODEM_MANAGER(object); NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); switch (prop_id) { @@ -812,7 +812,7 @@ nm_modem_manager_init(NMModemManager *self) static void dispose(GObject *object) { - NMModemManager * self = NM_MODEM_MANAGER(object); + NMModemManager *self = NM_MODEM_MANAGER(object); NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); nm_clear_g_cancellable(&priv->main_cancellable); diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c index 78ad7b68..cac90d32 100644 --- a/src/core/devices/wwan/nm-modem-ofono.c +++ b/src/core/devices/wwan/nm-modem-ofono.c @@ -11,7 +11,7 @@ #include "devices/nm-device-private.h" #include "nm-modem.h" #include "libnm-platform/nm-platform.h" -#include "nm-ip4-config.h" +#include "nm-l3-config-data.h" #define VARIANT_IS_OF_TYPE_BOOLEAN(v) \ ((v) != NULL && (g_variant_is_of_type((v), G_VARIANT_TYPE_BOOLEAN))) @@ -47,7 +47,7 @@ typedef struct { gboolean modem_online; gboolean gprs_attached; - NMIP4Config *ip4_config; + NML3ConfigData *l3cd_4; } NMModemOfonoPrivate; struct _NMModemOfono { @@ -75,7 +75,7 @@ G_DEFINE_TYPE(NMModemOfono, nm_modem_ofono, NM_TYPE_MODEM) if (nm_logging_enabled(_level, (_NMLOG_DOMAIN))) { \ NMModemOfono *const __self = (self); \ char __prefix_name[128]; \ - const char * __uid; \ + const char *__uid; \ \ _nm_log(_level, \ (_NMLOG_DOMAIN), \ @@ -97,7 +97,7 @@ G_DEFINE_TYPE(NMModemOfono, nm_modem_ofono, NM_TYPE_MODEM) /*****************************************************************************/ static void -get_capabilities(NMModem * _self, +get_capabilities(NMModem *_self, NMDeviceModemCapabilities *modem_caps, NMDeviceModemCapabilities *current_caps) { @@ -112,7 +112,7 @@ update_modem_state(NMModemOfono *self) NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); NMModemState state = nm_modem_get_state(NM_MODEM(self)); NMModemState new_state = NM_MODEM_STATE_DISABLED; - const char * reason = NULL; + const char *reason = NULL; _LOGI("'Attached': %s 'Online': %s 'IMSI': %s", priv->gprs_attached ? "true" : "false", @@ -137,10 +137,10 @@ update_modem_state(NMModemOfono *self) /* Disconnect */ typedef struct { - NMModemOfono * self; + NMModemOfono *self; _NMModemDisconnectCallback callback; gpointer callback_user_data; - GCancellable * cancellable; + GCancellable *cancellable; gboolean warn; } DisconnectContext; @@ -157,7 +157,7 @@ disconnect_context_complete(DisconnectContext *ctx, GError *error) static void disconnect_context_complete_on_idle(gpointer user_data, GCancellable *cancellable) { - DisconnectContext *ctx = user_data; + DisconnectContext *ctx = user_data; gs_free_error GError *error = NULL; if (!g_cancellable_set_error_if_cancelled(cancellable, &error)) { @@ -172,10 +172,10 @@ disconnect_context_complete_on_idle(gpointer user_data, GCancellable *cancellabl static void disconnect_done(GObject *source, GAsyncResult *result, gpointer user_data) { - DisconnectContext *ctx = user_data; - NMModemOfono * self = ctx->self; - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *v = NULL; + DisconnectContext *ctx = user_data; + NMModemOfono *self = ctx->self; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *v = NULL; v = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), result, &error); if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { @@ -193,15 +193,15 @@ disconnect_done(GObject *source, GAsyncResult *result, gpointer user_data) } static void -disconnect(NMModem * modem, +disconnect(NMModem *modem, gboolean warn, - GCancellable * cancellable, + GCancellable *cancellable, _NMModemDisconnectCallback callback, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(modem); + NMModemOfono *self = NM_MODEM_OFONO(modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); - DisconnectContext * ctx; + DisconnectContext *ctx; NMModemState state = nm_modem_get_state(NM_MODEM(self)); _LOGD("warn: %s modem_state: %s", warn ? "TRUE" : "FALSE", nm_modem_state_to_string(state)); @@ -235,12 +235,12 @@ disconnect(NMModem * modem, static void deactivate_cleanup(NMModem *modem, NMDevice *device, gboolean stop_ppp_manager) { - NMModemOfono * self = NM_MODEM_OFONO(modem); + NMModemOfono *self = NM_MODEM_OFONO(modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); /* TODO: cancel SimpleConnect() if any */ - g_clear_object(&priv->ip4_config); + nm_clear_l3cd(&priv->l3cd_4); NM_MODEM_CLASS(nm_modem_ofono_parent_class) ->deactivate_cleanup(modem, device, stop_ppp_manager); @@ -249,9 +249,9 @@ deactivate_cleanup(NMModem *modem, NMDevice *device, gboolean stop_ppp_manager) static gboolean check_connection_compatible_with_modem(NMModem *modem, NMConnection *connection, GError **error) { - NMModemOfono * self = NM_MODEM_OFONO(modem); + NMModemOfono *self = NM_MODEM_OFONO(modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); - const char * id; + const char *id; if (!_nm_connection_check_main_setting(connection, NM_SETTING_GSM_SETTING_NAME, NULL)) { nm_utils_error_set(error, @@ -290,7 +290,7 @@ check_connection_compatible_with_modem(NMModem *modem, NMConnection *connection, static void handle_sim_property(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(user_data); + NMModemOfono *self = NM_MODEM_OFONO(user_data); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); if (g_strcmp0(property, "SubscriberIdentity") == 0 && VARIANT_IS_OF_TYPE_STRING(v)) { @@ -324,14 +324,14 @@ sim_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, gpoin static void sim_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; - gs_free_error GError *error = NULL; + NMModemOfono *self; + NMModemOfonoPrivate *priv; + gs_free_error GError *error = NULL; gs_unref_variant GVariant *v_properties = NULL; gs_unref_variant GVariant *v_dict = NULL; gs_unref_variant GVariant *v = NULL; GVariantIter i; - const char * property; + const char *property; v_properties = _nm_dbus_proxy_call_finish(G_DBUS_PROXY(source), result, G_VARIANT_TYPE("(a{sv})"), &error); @@ -377,10 +377,10 @@ sim_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_dat static void _sim_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; + NMModemOfono *self; + NMModemOfonoPrivate *priv; gs_free_error GError *error = NULL; - GDBusProxy * proxy; + GDBusProxy *proxy; proxy = g_dbus_proxy_new_for_bus_finish(result, &error); if (!proxy && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -451,7 +451,7 @@ handle_sim_iface(NMModemOfono *self, gboolean found) static void handle_connman_property(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(user_data); + NMModemOfono *self = NM_MODEM_OFONO(user_data); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); if (g_strcmp0(property, "Attached") == 0 && VARIANT_IS_OF_TYPE_BOOLEAN(v)) { @@ -483,14 +483,14 @@ connman_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, g static void connman_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; - gs_free_error GError *error = NULL; + NMModemOfono *self; + NMModemOfonoPrivate *priv; + gs_free_error GError *error = NULL; gs_unref_variant GVariant *v_properties = NULL; gs_unref_variant GVariant *v_dict = NULL; gs_unref_variant GVariant *v = NULL; GVariantIter i; - const char * property; + const char *property; v_properties = _nm_dbus_proxy_call_finish(G_DBUS_PROXY(source), result, G_VARIANT_TYPE("(a{sv})"), &error); @@ -528,10 +528,10 @@ connman_get_properties_done(GObject *source, GAsyncResult *result, gpointer user static void _connman_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; + NMModemOfono *self; + NMModemOfonoPrivate *priv; gs_free_error GError *error = NULL; - GDBusProxy * proxy; + GDBusProxy *proxy; proxy = g_dbus_proxy_new_for_bus_finish(result, &error); if (!proxy && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -606,7 +606,7 @@ handle_connman_iface(NMModemOfono *self, gboolean found) static void handle_modem_property(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(user_data); + NMModemOfono *self = NM_MODEM_OFONO(user_data); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); if ((g_strcmp0(property, "Online") == 0) && VARIANT_IS_OF_TYPE_BOOLEAN(v)) { @@ -655,14 +655,14 @@ modem_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, gpo static void modem_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; - gs_free_error GError *error = NULL; + NMModemOfono *self; + NMModemOfonoPrivate *priv; + gs_free_error GError *error = NULL; gs_unref_variant GVariant *v_properties = NULL; gs_unref_variant GVariant *v_dict = NULL; - GVariant * v; + GVariant *v; GVariantIter i; - const char * property; + const char *property; v_properties = _nm_dbus_proxy_call_finish(G_DBUS_PROXY(source), result, G_VARIANT_TYPE("(a{sv})"), &error); @@ -704,10 +704,10 @@ modem_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_d static void stage1_prepare_done(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *v = NULL; + NMModemOfono *self; + NMModemOfonoPrivate *priv; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *v = NULL; v = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), result, &error); if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -732,17 +732,17 @@ stage1_prepare_done(GObject *source, GAsyncResult *result, gpointer user_data) static void handle_settings(GVariant *v_dict, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(user_data); + NMModemOfono *self = NM_MODEM_OFONO(user_data); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); - NMPlatformIP4Address addr; + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + NMPlatformIP4Address address; gboolean ret = FALSE; - const char * interface; - const char * s; - const char ** array, **iter; + const char *interface; + const char *s; + const char **array; guint32 address_network, gateway_network; - guint32 ip4_route_table, ip4_route_metric; int ifindex; - GError * error = NULL; + GError *error = NULL; //_LOGD("PropertyChanged: %s", property); @@ -773,12 +773,14 @@ handle_settings(GVariant *v_dict, gpointer user_data) } ifindex = nm_modem_get_ip_ifindex(NM_MODEM(self)); - nm_assert(ifindex > 0); + g_return_if_fail(ifindex > 0); - /* TODO: verify handling of ip4_config; check other places it's used... */ - g_clear_object(&priv->ip4_config); + /* TODO: verify handling of l3cd_4; check other places it's used... */ + nm_clear_l3cd(&priv->l3cd_4); - priv->ip4_config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), ifindex); + priv->l3cd_4 = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), + ifindex, + NM_IP_CONFIG_SOURCE_WWAN); if (!g_variant_lookup(v_dict, "Address", "&s", &s)) { _LOGW("Settings 'Address' missing"); @@ -788,10 +790,12 @@ handle_settings(GVariant *v_dict, gpointer user_data) _LOGW("can't convert 'Address' %s to addr", s ?: ""); goto out; } - memset(&addr, 0, sizeof(addr)); - addr.ifindex = ifindex; - addr.address = address_network; - addr.addr_source = NM_IP_CONFIG_SOURCE_WWAN; + + address = (NMPlatformIP4Address){ + .ifindex = ifindex, + .address = address_network, + .addr_source = NM_IP_CONFIG_SOURCE_WWAN, + }; if (!g_variant_lookup(v_dict, "Netmask", "&s", &s)) { _LOGW("Settings 'Netmask' missing"); @@ -801,10 +805,10 @@ handle_settings(GVariant *v_dict, gpointer user_data) _LOGW("invalid 'Netmask': %s", s ?: ""); goto out; } - addr.plen = nm_utils_ip4_netmask_to_prefix(address_network); + address.plen = nm_utils_ip4_netmask_to_prefix(address_network); - _LOGI("Address: %s", nm_platform_ip4_address_to_string(&addr, NULL, 0)); - nm_ip4_config_add_address(priv->ip4_config, &addr); + _LOGI("Address: %s", nm_platform_ip4_address_to_string(&address, sbuf, sizeof(sbuf))); + nm_l3_config_data_add_address_4(priv->l3cd_4, &address); if (!g_variant_lookup(v_dict, "Gateway", "&s", &s) || !s) { _LOGW("Settings 'Gateway' missing"); @@ -814,17 +818,18 @@ handle_settings(GVariant *v_dict, gpointer user_data) _LOGW("invalid 'Gateway': %s", s); goto out; } - nm_modem_get_route_parameters(NM_MODEM(self), &ip4_route_table, &ip4_route_metric, NULL, NULL); { const NMPlatformIP4Route r = { .rt_source = NM_IP_CONFIG_SOURCE_WWAN, .gateway = gateway_network, - .table_coerced = nm_platform_route_table_coerce(ip4_route_table), - .metric = ip4_route_metric, + .table_any = TRUE, + .table_coerced = 0, + .metric_any = TRUE, + .metric = 0, }; _LOGI("Gateway: %s", s); - nm_ip4_config_add_route(priv->ip4_config, &r, NULL); + nm_l3_config_data_add_route_4(priv->l3cd_4, &r); } if (!g_variant_lookup(v_dict, "DomainNameServers", "^a&s", &array)) { @@ -832,52 +837,48 @@ handle_settings(GVariant *v_dict, gpointer user_data) goto out; } if (array) { - for (iter = array; *iter; iter++) { - if (nm_utils_parse_inaddr_bin(AF_INET, *iter, NULL, &address_network) - && address_network) { - _LOGI("DNS: %s", *iter); - nm_ip4_config_add_nameserver(priv->ip4_config, address_network); - } else { - _LOGW("invalid NameServer: %s", *iter); + gboolean any_good = FALSE; + + for (; array[0]; array++) { + if (!nm_utils_parse_inaddr_bin(AF_INET, *array, NULL, &address_network) + || !address_network) { + _LOGW("invalid NameServer: %s", *array); + continue; } + any_good = TRUE; + _LOGI("DNS: %s", *array); + nm_l3_config_data_add_nameserver(priv->l3cd_4, AF_INET, &address_network); } - - if (iter == array) { + if (!any_good) { _LOGW("Settings: 'DomainNameServers': none specified"); - g_free(array); goto out; } - g_free(array); } if (g_variant_lookup(v_dict, "MessageProxy", "&s", &s)) { _LOGI("MessageProxy: %s", s); if (s && nm_utils_parse_inaddr_bin(AF_INET, s, NULL, &address_network)) { - nm_modem_get_route_parameters(NM_MODEM(self), - &ip4_route_table, - &ip4_route_metric, - NULL, - NULL); - - { - const NMPlatformIP4Route mms_route = { - .network = address_network, - .plen = 32, - .gateway = gateway_network, - .table_coerced = nm_platform_route_table_coerce(ip4_route_table), - .metric = ip4_route_metric, - }; - - nm_ip4_config_add_route(priv->ip4_config, &mms_route, NULL); - } - } else { + const NMPlatformIP4Route mms_route = { + .network = address_network, + .plen = 32, + .gateway = gateway_network, + .table_any = TRUE, + .table_coerced = 0, + .metric_any = TRUE, + .metric = 0, + }; + + nm_l3_config_data_add_route_4(priv->l3cd_4, &mms_route); + } else _LOGW("invalid MessageProxy: %s", s); - } } ret = TRUE; out: + if (priv->l3cd_4) + nm_l3_config_data_seal(priv->l3cd_4); + if (nm_modem_get_state(NM_MODEM(self)) != NM_MODEM_STATE_CONNECTED) { _LOGI("emitting PREPARE_RESULT: %s", ret ? "TRUE" : "FALSE"); nm_modem_emit_prepare_result(NM_MODEM(self), @@ -893,7 +894,7 @@ out: static void context_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(user_data); + NMModemOfono *self = NM_MODEM_OFONO(user_data); gs_unref_variant GVariant *v_dict = NULL; _LOGD("PropertyChanged: %s", property); @@ -912,38 +913,43 @@ context_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, g handle_settings(v_dict, user_data); } -static NMActStageReturn -static_stage3_ip4_config_start(NMModem * modem, - NMActRequest * req, - NMDeviceStateReason *out_failure_reason) +static void +stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_method) { - NMModemOfono * self = NM_MODEM_OFONO(modem); - NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); - GError * error = NULL; + NMModemOfono *self = NM_MODEM_OFONO(modem); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); + gs_free_error GError *error = NULL; - if (!priv->ip4_config) { - _LOGD("IP4 config not ready(?)"); - return NM_ACT_STAGE_RETURN_FAILURE; + _LOGD("IP4 config is done; setting modem_state -> CONNECTED"); + + if (!NM_IS_IPv4(addr_family) || ip_method == NM_MODEM_IP_METHOD_AUTO) { + nm_modem_emit_signal_new_config_success(modem, addr_family, NULL, TRUE, NULL); + goto out; } - _LOGD("IP4 config is done; setting modem_state -> CONNECTED"); - g_signal_emit_by_name(self, NM_MODEM_IP4_CONFIG_RESULT, priv->ip4_config, error); + if (!priv->l3cd_4) { + nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "IP config not received"); + nm_modem_emit_signal_new_config_failure(modem, + addr_family, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE, + error); + goto out; + } - /* Signal listener takes ownership of the IP4Config */ - priv->ip4_config = NULL; + nm_modem_emit_signal_new_config_success(modem, addr_family, priv->l3cd_4, FALSE, NULL); +out: nm_modem_set_state(NM_MODEM(self), NM_MODEM_STATE_CONNECTED, nm_modem_state_to_string(NM_MODEM_STATE_CONNECTED)); - return NM_ACT_STAGE_RETURN_POSTPONE; } static void context_properties_cb(GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; - gs_free_error GError *error = NULL; + NMModemOfono *self; + NMModemOfonoPrivate *priv; + gs_free_error GError *error = NULL; gs_unref_variant GVariant *properties = NULL; gs_unref_variant GVariant *settings = NULL; gs_unref_variant GVariant *v_dict = NULL; @@ -1007,10 +1013,10 @@ error: static void context_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; + NMModemOfono *self; + NMModemOfonoPrivate *priv; gs_free_error GError *error = NULL; - GDBusProxy * proxy; + GDBusProxy *proxy; proxy = g_dbus_proxy_new_for_bus_finish(result, &error); if (!proxy || g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1040,7 +1046,7 @@ context_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) * clear it so that we can gate getting the IP config from oFono * on whether or not we have already received them */ - g_clear_object(&priv->ip4_config); + nm_clear_l3cd(&priv->l3cd_4); /* We need to directly query ConnectionContextinteface to get the current * property values */ @@ -1081,8 +1087,8 @@ static GHashTable * create_connect_properties(NMConnection *connection) { NMSettingGsm *setting; - GHashTable * properties; - const char * str; + GHashTable *properties; + const char *str; setting = nm_connection_get_setting_gsm(connection); properties = g_hash_table_new(nm_str_hash, g_str_equal); @@ -1103,14 +1109,14 @@ create_connect_properties(NMConnection *connection) } static NMActStageReturn -modem_act_stage1_prepare(NMModem * modem, - NMConnection * connection, +modem_act_stage1_prepare(NMModem *modem, + NMConnection *connection, NMDeviceStateReason *out_failure_reason) { - NMModemOfono * self = NM_MODEM_OFONO(modem); + NMModemOfono *self = NM_MODEM_OFONO(modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); - const char * context_id; - char ** id = NULL; + const char *context_id; + char **id = NULL; context_id = nm_connection_get_id(connection); id = g_strsplit(context_id, "/", 0); @@ -1149,10 +1155,10 @@ modem_act_stage1_prepare(NMModem * modem, static void modem_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; + NMModemOfono *self; + NMModemOfonoPrivate *priv; gs_free_error GError *error = NULL; - GDBusProxy * proxy; + GDBusProxy *proxy; proxy = g_dbus_proxy_new_for_bus_finish(result, &error); if (!proxy && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1194,7 +1200,7 @@ nm_modem_ofono_init(NMModemOfono *self) static void constructed(GObject *object) { - NMModemOfono * self = NM_MODEM_OFONO(object); + NMModemOfono *self = NM_MODEM_OFONO(object); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); priv->modem_proxy_cancellable = g_cancellable_new(); @@ -1245,7 +1251,7 @@ nm_modem_ofono_new(const char *path) static void dispose(GObject *object) { - NMModemOfono * self = NM_MODEM_OFONO(object); + NMModemOfono *self = NM_MODEM_OFONO(object); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); nm_clear_g_cancellable(&priv->modem_proxy_cancellable); @@ -1258,7 +1264,7 @@ dispose(GObject *object) priv->connect_properties = NULL; } - g_clear_object(&priv->ip4_config); + nm_clear_l3cd(&priv->l3cd_4); if (priv->modem_proxy) { g_signal_handlers_disconnect_by_data(priv->modem_proxy, self); @@ -1300,6 +1306,6 @@ nm_modem_ofono_class_init(NMModemOfonoClass *klass) modem_class->deactivate_cleanup = deactivate_cleanup; modem_class->check_connection_compatible_with_modem = check_connection_compatible_with_modem; - modem_class->modem_act_stage1_prepare = modem_act_stage1_prepare; - modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start; + modem_class->modem_act_stage1_prepare = modem_act_stage1_prepare; + modem_class->stage3_ip_config_start = stage3_ip_config_start; } diff --git a/src/core/devices/wwan/nm-modem.c b/src/core/devices/wwan/nm-modem.c index ccea69db..a5ee8ce8 100644 --- a/src/core/devices/wwan/nm-modem.c +++ b/src/core/devices/wwan/nm-modem.c @@ -13,16 +13,16 @@ #include <linux/if.h> #include <linux/rtnetlink.h> -#include "libnm-core-intern/nm-core-internal.h" -#include "libnm-platform/nm-platform.h" -#include "nm-setting-connection.h" #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" -#include "nm-netns.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-platform/nm-platform.h" #include "nm-act-request.h" -#include "nm-ip4-config.h" -#include "nm-ip6-config.h" +#include "nm-l3-config-data.h" +#include "nm-netns.h" +#include "nm-setting-connection.h" #include "ppp/nm-ppp-manager-call.h" +#include "ppp/nm-ppp-mgr.h" #include "ppp/nm-ppp-status.h" /*****************************************************************************/ @@ -45,8 +45,7 @@ enum { PPP_STATS, PPP_FAILED, PREPARE_RESULT, - IP4_CONFIG_RESULT, - IP6_CONFIG_RESULT, + NEW_CONFIG, AUTH_REQUESTED, AUTH_RESULT, REMOVED, @@ -56,6 +55,11 @@ enum { static guint signals[LAST_SIGNAL] = {0}; +typedef struct { + GSource *stage3_on_idle_source; + bool stage3_started : 1; +} IPData; + typedef struct _NMModemPrivate { char *uid; char *path; @@ -63,41 +67,38 @@ typedef struct _NMModemPrivate { 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; - NMModemIPMethod ip4_method; - NMModemIPMethod ip6_method; - NMUtilsIPv6IfaceId iid; - NMModemState state; - NMModemState prev_state; /* revert to this state if enable/disable fails */ - char * device_id; - char * sim_id; - NMModemIPType ip_types; - char * sim_operator_id; - char * operator_code; - char * apn; + int ip_ifindex; + NMModemIPMethod ip4_method; + NMModemIPMethod ip6_method; + NMModemState state; + NMModemState prev_state; /* revert to this state if enable/disable fails */ + char *device_id; + char *sim_id; + NMModemIPType ip_types; + char *sim_operator_id; + char *operator_code; + char *apn; NMPPPManager *ppp_manager; + NMPppMgr *ppp_mgr; - NMActRequest * act_request; + NMActRequest *act_req; + NMDevice *device; guint32 secrets_tries; NMActRequestGetSecretsCallId *secrets_id; guint mm_ip_timeout; - guint32 ip4_route_table; - guint32 ip4_route_metric; - guint32 ip6_route_table; - guint32 ip6_route_metric; + bool claimed : 1; - /* PPP stats */ - guint32 in_bytes; - guint32 out_bytes; + union { + struct { + IPData ip_data_6; + IPData ip_data_4; + }; + IPData ip_data_x[2]; + }; - bool claimed : 1; } NMModemPrivate; G_DEFINE_TYPE(NMModem, nm_modem, G_TYPE_OBJECT) @@ -149,7 +150,7 @@ _nmlog_prefix(char *prefix, NMModem *self) /*****************************************************************************/ -static void _set_ip_ifindex(NMModem *self, int ifindex, const char *ifname); +static void _set_ip_ifindex(NMModem *self, int ifindex); /*****************************************************************************/ /* State/enabled/connected */ @@ -180,6 +181,91 @@ nm_modem_state_to_string(NMModemState state) /*****************************************************************************/ +static NMPlatform * +_get_platform(NMModem *self) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + + if (!priv->device) + return NULL; + + return nm_device_get_platform(priv->device); +} + +/*****************************************************************************/ + +void +nm_modem_emit_signal_new_config(NMModem *self, + int addr_family, + const NML3ConfigData *l3cd, + gboolean do_auto, + const NMUtilsIPv6IfaceId *iid, + NMDeviceStateReason failure_reason, + GError *error) +{ + nm_assert(NM_IS_MODEM(self)); + nm_assert_addr_family(addr_family); + nm_assert(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd)); + nm_assert(!do_auto || addr_family == AF_INET6); + nm_assert(!iid || addr_family == AF_INET6); + nm_assert(!error || (!l3cd && !do_auto && !iid)); + + if (error) { + _LOGD("signal: new-config: IPv%c, failed '%s', %s", + nm_utils_addr_family_to_char(addr_family), + nm_device_state_reason_to_string_a(failure_reason), + error->message); + } else { + gs_free char *str_to_free = NULL; + + _LOGD( + "signal: new-config: IPv%c%s%s%s%s", + nm_utils_addr_family_to_char(addr_family), + l3cd ? ", has-l3cd" : "", + do_auto ? ", do-auto" : "", + NM_PRINT_FMT_QUOTED2(iid, + ", iid=", + nm_utils_bin2hexstr_a(iid, sizeof(*iid), ':', FALSE, &str_to_free), + "")); + } + + g_signal_emit(self, + signals[NEW_CONFIG], + 0, + addr_family, + nm_l3_config_data_seal(l3cd), + do_auto, + iid, + (int) failure_reason, + error); +} + +void +nm_modem_emit_signal_new_config_success(NMModem *self, + int addr_family, + const NML3ConfigData *l3cd, + gboolean do_auto, + const NMUtilsIPv6IfaceId *iid) +{ + nm_modem_emit_signal_new_config(self, + addr_family, + l3cd, + do_auto, + iid, + NM_DEVICE_STATE_REASON_NONE, + NULL); +} + +void +nm_modem_emit_signal_new_config_failure(NMModem *self, + int addr_family, + NMDeviceStateReason failure_reason, + GError *error) +{ + nm_assert(error); + nm_modem_emit_signal_new_config(self, addr_family, NULL, FALSE, NULL, failure_reason, error); +} + gboolean nm_modem_is_claimed(NMModem *self) { @@ -240,10 +326,10 @@ nm_modem_set_state(NMModem *self, NMModemState new_state, const char *reason) priv->prev_state = NM_MODEM_STATE_UNKNOWN; if (new_state != old_state) { - _LOGI("modem state changed, '%s' --> '%s' (reason: %s)", + _LOGD("signal: modem state changed, '%s' --> '%s' (reason: %s%s%s)", nm_modem_state_to_string(old_state), nm_modem_state_to_string(new_state), - reason ?: "none"); + NM_PRINT_FMT_QUOTE_STRING(reason)); priv->state = new_state; _notify(self, PROP_STATE); @@ -285,7 +371,7 @@ nm_modem_set_mm_enabled(NMModem *self, gboolean enabled) /* Try to unlock the modem if it's being enabled */ if (enabled) - g_signal_emit(self, signals[AUTH_REQUESTED], 0); + nm_modem_emit_auth_requested(self); return; } @@ -303,14 +389,25 @@ nm_modem_set_mm_enabled(NMModem *self, gboolean enabled) void nm_modem_emit_removed(NMModem *self) { + _LOGD("signal: removed"); g_signal_emit(self, signals[REMOVED], 0); } void +nm_modem_emit_auth_requested(NMModem *self) +{ + _LOGD("signal: auth-requested"); + g_signal_emit(self, signals[AUTH_REQUESTED], 0); +} + +void nm_modem_emit_prepare_result(NMModem *self, gboolean success, NMDeviceStateReason reason) { nm_assert(NM_IS_MODEM(self)); + _LOGD("signal: prepare-result: %s (%s)", + success ? "success" : "failure", + nm_device_state_reason_to_string_a(reason)); g_signal_emit(self, signals[PREPARE_RESULT], 0, success, (guint) reason); } @@ -319,6 +416,7 @@ nm_modem_emit_ppp_failed(NMModem *self, NMDeviceStateReason reason) { nm_assert(NM_IS_MODEM(self)); + _LOGD("signal: ppp-failed (%s)", nm_device_state_reason_to_string_a(reason)); g_signal_emit(self, signals[PPP_FAILED], 0, (guint) reason); } @@ -363,16 +461,16 @@ build_single_ip_type_array(NMModemIPType type) GArray * nm_modem_get_connection_ip_type(NMModem *self, NMConnection *connection, GError **error) { - NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); NMSettingIPConfig *s_ip4, *s_ip6; - const char * method; + const char *method; gboolean ip4 = TRUE, ip6 = TRUE; gboolean ip4_may_fail = TRUE, ip6_may_fail = TRUE; s_ip4 = nm_connection_get_setting_ip4_config(connection); if (s_ip4) { method = nm_setting_ip_config_get_method(s_ip4); - if (g_strcmp0(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) + if (nm_streq0(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) ip4 = FALSE; ip4_may_fail = nm_setting_ip_config_get_may_fail(s_ip4); } @@ -413,7 +511,7 @@ nm_modem_get_connection_ip_type(NMModem *self, NMConnection *connection, GError if (ip4 && ip6) { NMModemIPType type; - GArray * out; + GArray *out; out = g_array_sized_new(FALSE, FALSE, sizeof(NMModemIPType), 3); @@ -487,83 +585,101 @@ nm_modem_get_apn(NMModem *self) } /*****************************************************************************/ -/* IP method PPP */ static void -ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) +_ppp_mgr_cleanup(NMModem *self) { - switch (status) { - case NM_PPP_STATUS_DISCONNECT: - nm_modem_emit_ppp_failed(user_data, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); - break; - case NM_PPP_STATUS_DEAD: - nm_modem_emit_ppp_failed(user_data, NM_DEVICE_STATE_REASON_PPP_FAILED); - break; - default: - break; - } + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + + nm_clear_pointer(&priv->ppp_mgr, nm_ppp_mgr_destroy); } static void -ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data) +_ppp_maybe_emit_new_config(NMModem *self, int addr_family) { - NMModem *self = NM_MODEM(user_data); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + const NMPppMgrIPData *ip_data; + gboolean do_auto; - nm_assert(ifindex >= 0); - nm_assert(NM_MODEM_GET_PRIVATE(self)->ppp_manager == ppp_manager); + ip_data = nm_ppp_mgr_get_ip_data(priv->ppp_mgr, addr_family); - 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 (!ip_data->ip_received) + return; + + if (IS_IPv4) + do_auto = FALSE; + else { + do_auto = !ip_data->l3cd + || (!nm_l3_config_data_get_first_obj(ip_data->l3cd, + NMP_OBJECT_TYPE_IP6_ADDRESS, + nmp_object_ip6_address_is_not_link_local)); } - _set_ip_ifindex(self, ifindex, iface); -} -static void -ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data) -{ - NMModem *self = NM_MODEM(user_data); + nm_assert(!IS_IPv4 || !ip_data->ipv6_iid); - g_signal_emit(self, signals[IP4_CONFIG_RESULT], 0, config, NULL); + nm_modem_emit_signal_new_config_success(self, + addr_family, + ip_data->l3cd, + do_auto, + ip_data->ipv6_iid); } static void -ppp_ip6_config(NMPPPManager * ppp_manager, - const NMUtilsIPv6IfaceId *iid, - NMIP6Config * config, - gpointer user_data) +_ppp_mgr_callback(NMPppMgr *ppp_mgr, const NMPppMgrCallbackData *callback_data, gpointer user_data) { - NMModem *self = NM_MODEM(user_data); + NMModem *self = NM_MODEM(user_data); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + int IS_IPv4; - NM_MODEM_GET_PRIVATE(self)->iid = *iid; + switch (callback_data->callback_type) { + case NM_PPP_MGR_CALLBACK_TYPE_STATE_CHANGED: - nm_modem_emit_ip6_config_result(self, config, NULL); -} + if (callback_data->data.state >= _NM_PPP_MGR_STATE_FAILED_START) { + nm_modem_emit_ppp_failed(self, callback_data->data.reason); + return; + } -static void -ppp_stats(NMPPPManager *ppp_manager, guint i_in_bytes, guint i_out_bytes, gpointer user_data) -{ - NMModem * self = NM_MODEM(user_data); - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); - guint32 in_bytes = i_in_bytes; - guint32 out_bytes = i_out_bytes; + if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IFINDEX) + _set_ip_ifindex(self, callback_data->data.ifindex); + + if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IP_CONFIG) { + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + if (!priv->ip_data_x[IS_IPv4].stage3_started) { + /* stage3 didn't yet start. We don't emit the IP signal yet. + * We will emit it together with stage3. */ + continue; + } + if (priv->ip_data_x[IS_IPv4].stage3_on_idle_source) { + /* We scheduled already a handler. Let it handle the new configuration. */ + continue; + } + if (callback_data->data.ip_changed_x[IS_IPv4]) + _ppp_maybe_emit_new_config(self, IS_IPv4 ? AF_INET : AF_INET6); + } + } + return; - if (priv->in_bytes != in_bytes || priv->out_bytes != out_bytes) { - priv->in_bytes = in_bytes; - priv->out_bytes = out_bytes; - g_signal_emit(self, signals[PPP_STATS], 0, (guint) in_bytes, (guint) out_bytes); + case NM_PPP_MGR_CALLBACK_TYPE_STATS_CHANGED: + g_signal_emit(self, + signals[PPP_STATS], + 0, + (guint) callback_data->data.stats_data->in_bytes, + (guint) callback_data->data.stats_data->out_bytes); + return; } + + nm_assert_not_reached(); } +/*****************************************************************************/ + static gboolean port_speed_is_zero(const char *port) { struct termios options; nm_auto_close int fd = -1; - gs_free char * path = NULL; + gs_free char *path = NULL; nm_assert(port); @@ -585,291 +701,116 @@ port_speed_is_zero(const char *port) return cfgetospeed(&options) == B0; } -static NMActStageReturn -ppp_stage3_ip_config_start(NMModem * self, - NMActRequest * req, - NMDeviceStateReason *out_failure_reason) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); - const char * ppp_name = NULL; - GError * error = NULL; - guint ip_timeout = 30; - guint baud_override = 0; - - g_return_val_if_fail(NM_IS_MODEM(self), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail(NM_IS_ACT_REQUEST(req), NM_ACT_STAGE_RETURN_FAILURE); - - /* If we're already running PPP don't restart it; for example, if both - * IPv4 and IPv6 are requested, IPv4 gets started first, but we use the - * same pppd for both v4 and v6. - */ - if (priv->ppp_manager) - return NM_ACT_STAGE_RETURN_POSTPONE; - - if (NM_MODEM_GET_CLASS(self)->get_user_pass) { - NMConnection *connection = nm_act_request_get_applied_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; - } - - 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) { - _LOGI("using modem-specified IP timeout: %u seconds", priv->mm_ip_timeout); - ip_timeout = priv->mm_ip_timeout; - } - - /* Some tty drivers and modems ignore port speed, but pppd requires the - * port speed to be > 0 or it exits. If the port speed is 0 pass an - * explicit speed to pppd to prevent the exit. - * https://bugzilla.redhat.com/show_bug.cgi?id=1281731 - */ - if (port_speed_is_zero(priv->data_port)) - baud_override = 57600; - - priv->ppp_manager = nm_ppp_manager_create(priv->data_port, &error); - - if (priv->ppp_manager) { - nm_ppp_manager_set_route_parameters(priv->ppp_manager, - priv->ip4_route_table, - priv->ip4_route_metric, - priv->ip6_route_table, - priv->ip6_route_metric); - } - - if (!priv->ppp_manager - || !nm_ppp_manager_start(priv->ppp_manager, - req, - ppp_name, - 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; - } - - 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); - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_IP6_CONFIG, - G_CALLBACK(ppp_ip6_config), - self); - g_signal_connect(priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATS, G_CALLBACK(ppp_stats), self); - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - /*****************************************************************************/ -NMActStageReturn -nm_modem_stage3_ip4_config_start(NMModem * self, - NMDevice * device, - gboolean * out_autoip4, - NMDeviceStateReason *out_failure_reason) +static gboolean +_stage3_ip_config_start_on_idle(NMModem *self, int addr_family) { - NMModemPrivate * priv; - NMActRequest * req; - NMConnection * connection; - const char * method; - NMActStageReturn ret; - - _LOGD("ip4_config_start"); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + NMModemIPMethod ip_method; + NMConnection *connection; + const char *method; + gs_free_error GError *error = NULL; + NMDeviceStateReason failure_reason; - 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); - nm_assert(out_autoip4 && !*out_autoip4); - - req = nm_device_get_act_request(device); - g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_applied_connection(req); - g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + nm_clear_g_source_inst(&priv->ip_data_x[IS_IPv4].stage3_on_idle_source); - nm_modem_set_route_parameters_from_device(self, device); + connection = nm_act_request_get_applied_connection(priv->act_req); + g_return_val_if_fail(connection, G_SOURCE_CONTINUE); - method = nm_utils_get_ip_config_method(connection, AF_INET); + method = nm_utils_get_ip_config_method(connection, addr_family); - /* Only Disabled and Auto methods make sense for WWAN */ - if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) - return NM_ACT_STAGE_RETURN_SUCCESS; + if (IS_IPv4 ? NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) + : NM_IN_STRSET(method, + NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { + nm_modem_emit_signal_new_config_success(self, addr_family, NULL, FALSE, NULL); + return G_SOURCE_CONTINUE; + } - if (!nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { - _LOGE("unhandled WWAN IPv4 method '%s'; will fail", method); - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED); - return NM_ACT_STAGE_RETURN_FAILURE; + if (!nm_streq(method, + IS_IPv4 ? NM_SETTING_IP4_CONFIG_METHOD_AUTO + : NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { + failure_reason = NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED; + nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "ip method unsupported by modem"); + goto out_failure; } - priv = NM_MODEM_GET_PRIVATE(self); - switch (priv->ip4_method) { + ip_method = IS_IPv4 ? priv->ip4_method : priv->ip6_method; + + switch (ip_method) { case NM_MODEM_IP_METHOD_PPP: - ret = ppp_stage3_ip_config_start(self, req, out_failure_reason); - break; + _ppp_maybe_emit_new_config(self, addr_family); + return G_SOURCE_CONTINUE; case NM_MODEM_IP_METHOD_STATIC: - _LOGD("MODEM_IP_METHOD_STATIC"); - ret = - NM_MODEM_GET_CLASS(self)->static_stage3_ip4_config_start(self, req, out_failure_reason); - break; case NM_MODEM_IP_METHOD_AUTO: - _LOGD("MODEM_IP_METHOD_AUTO"); - *out_autoip4 = TRUE; - ret = NM_ACT_STAGE_RETURN_SUCCESS; - break; + NM_MODEM_GET_CLASS(self)->stage3_ip_config_start(self, addr_family, ip_method); + return G_SOURCE_CONTINUE; default: - _LOGI("IPv4 configuration disabled"); - ret = NM_ACT_STAGE_RETURN_IP_FAIL; - break; + failure_reason = NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED; + nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "modem IP method unsupported"); + goto out_failure; } - return ret; -} - -void -nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(modem); + nm_assert_not_reached(); - /* If the modem has an ethernet-type data interface (ie, not PPP and thus - * not point-to-point) and IP config has a /32 prefix, then we assume that - * ARP will be pointless and we turn it off. - */ - if (priv->ip4_method == NM_MODEM_IP_METHOD_STATIC - || priv->ip4_method == NM_MODEM_IP_METHOD_AUTO) { - const NMPlatformIP4Address *address = nm_ip4_config_get_first_address(config); - - g_assert(address); - if (address->plen == 32) - nm_platform_link_change_flags(nm_device_get_platform(device), - nm_device_get_ip_ifindex(device), - IFF_NOARP, - TRUE); - } +out_failure: + nm_modem_emit_signal_new_config_failure(self, addr_family, failure_reason, error); + return G_SOURCE_CONTINUE; } -/*****************************************************************************/ - -void -nm_modem_emit_ip6_config_result(NMModem *self, NMIP6Config *config, GError *error) +static gboolean +_stage3_ip_config_start_on_idle_4(gpointer user_data) { - NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self); - NMDedupMultiIter ipconf_iter; - const NMPlatformIP6Address *addr; - 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. - */ - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, config, &addr) { - 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); + return _stage3_ip_config_start_on_idle(user_data, AF_INET); } -static NMActStageReturn -stage3_ip6_config_request(NMModem *self, NMDeviceStateReason *out_failure_reason) +static gboolean +_stage3_ip_config_start_on_idle_6(gpointer user_data) { - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return NM_ACT_STAGE_RETURN_FAILURE; + return _stage3_ip_config_start_on_idle(user_data, AF_INET6); } -NMActStageReturn -nm_modem_stage3_ip6_config_start(NMModem * self, - NMDevice * device, - NMDeviceStateReason *out_failure_reason) +gboolean +nm_modem_stage3_ip_config_start(NMModem *self, int addr_family, NMDevice *device) { - NMModemPrivate * priv; - NMActRequest * req; - NMActStageReturn ret; - NMConnection * connection; - const char * method; - - g_return_val_if_fail(NM_IS_MODEM(self), NM_ACT_STAGE_RETURN_FAILURE); - - req = nm_device_get_act_request(device); - g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_applied_connection(req); - g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMModemPrivate *priv; - nm_modem_set_route_parameters_from_device(self, device); + g_return_val_if_fail(NM_IS_MODEM(self), FALSE); + g_return_val_if_fail(NM_IS_DEVICE(device), FALSE); - method = nm_utils_get_ip_config_method(connection, AF_INET6); + priv = NM_MODEM_GET_PRIVATE(self); - /* Only Ignore, Disabled and Auto methods make sense for WWAN */ - if (NM_IN_STRSET(method, - NM_SETTING_IP6_CONFIG_METHOD_IGNORE, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) - return NM_ACT_STAGE_RETURN_IP_DONE; + g_return_val_if_fail(priv->device == device, FALSE); - if (!nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { - _LOGW("unhandled WWAN IPv6 method '%s'; will fail", method); - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return NM_ACT_STAGE_RETURN_FAILURE; + if (priv->ip_data_x[IS_IPv4].stage3_started) { + /* we already started. Nothing to do. */ + return FALSE; } - priv = NM_MODEM_GET_PRIVATE(self); - switch (priv->ip6_method) { - case NM_MODEM_IP_METHOD_PPP: - ret = ppp_stage3_ip_config_start(self, req, out_failure_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, out_failure_reason); - break; - default: - _LOGI("IPv6 configuration disabled"); - ret = NM_ACT_STAGE_RETURN_IP_FAIL; - break; - } + nm_assert(!priv->ppp_mgr + || nm_ppp_mgr_get_state(priv->ppp_mgr) >= NM_PPP_MGR_STATE_HAVE_IFINDEX); + + priv->ip_data_x[IS_IPv4].stage3_started = TRUE; - return ret; + priv->ip_data_x[IS_IPv4].stage3_on_idle_source = nm_g_idle_add_source( + IS_IPv4 ? _stage3_ip_config_start_on_idle_4 : _stage3_ip_config_start_on_idle_6, + self); + return TRUE; } +/*****************************************************************************/ + guint32 nm_modem_get_configured_mtu(NMDevice *self, NMDeviceMtuSource *out_source, gboolean *out_force) { NMConnection *connection; - NMSetting * setting; + NMSetting *setting; gint64 mtu_default; guint mtu = 0; - const char * property_name; + const char *property_name; nm_assert(NM_IS_DEVICE(self)); nm_assert(out_source); @@ -910,17 +851,17 @@ cancel_get_secrets(NMModem *self) NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); if (priv->secrets_id) - nm_act_request_cancel_secrets(priv->act_request, priv->secrets_id); + nm_act_request_cancel_secrets(priv->act_req, priv->secrets_id); } static void -modem_secrets_cb(NMActRequest * req, +modem_secrets_cb(NMActRequest *req, NMActRequestGetSecretsCallId *call_id, - NMSettingsConnection * connection, - GError * error, + NMSettingsConnection *connection, + GError *error, gpointer user_data) { - NMModem * self = NM_MODEM(user_data); + NMModem *self = NM_MODEM(user_data); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); g_return_if_fail(call_id == priv->secrets_id); @@ -934,23 +875,25 @@ modem_secrets_cb(NMActRequest * req, if (error) _LOGW("modem-secrets: %s", error->message); + _LOGD("signal: auth-result: %s%s", + NM_PRINT_FMT_QUOTED2(error, "failed: ", error->message, "success")); g_signal_emit(self, signals[AUTH_RESULT], 0, error); } void -nm_modem_get_secrets(NMModem * self, +nm_modem_get_secrets(NMModem *self, const char *setting_name, gboolean request_new, const char *hint) { - NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; cancel_get_secrets(self); if (request_new) flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; - priv->secrets_id = nm_act_request_get_secrets(priv->act_request, + priv->secrets_id = nm_act_request_get_secrets(priv->act_req, FALSE, setting_name, flags, @@ -958,14 +901,14 @@ nm_modem_get_secrets(NMModem * self, modem_secrets_cb, self); g_return_if_fail(priv->secrets_id); - g_signal_emit(self, signals[AUTH_REQUESTED], 0); + nm_modem_emit_auth_requested(self); } /*****************************************************************************/ static NMActStageReturn -modem_act_stage1_prepare(NMModem * modem, - NMConnection * connection, +modem_act_stage1_prepare(NMModem *modem, + NMConnection *connection, NMDeviceStateReason *out_failure_reason) { NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_UNKNOWN); @@ -973,25 +916,28 @@ modem_act_stage1_prepare(NMModem * modem, } NMActStageReturn -nm_modem_act_stage1_prepare(NMModem * self, - NMActRequest * req, +nm_modem_act_stage1_prepare(NMModem *self, + NMActRequest *req, NMDeviceStateReason *out_failure_reason) { - NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); gs_unref_ptrarray GPtrArray *hints = NULL; - const char * setting_name = NULL; + const char *setting_name = NULL; NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; - NMConnection * connection; + NMConnection *connection; + NMDevice *device; g_return_val_if_fail(NM_IS_ACT_REQUEST(req), NM_ACT_STAGE_RETURN_FAILURE); - if (priv->act_request) - g_object_unref(priv->act_request); - priv->act_request = g_object_ref(req); + nm_g_object_ref_set(&priv->act_req, req); + device = nm_active_connection_get_device(NM_ACTIVE_CONNECTION(priv->act_req)); + g_return_val_if_fail(NM_IS_DEVICE(device), NM_ACT_STAGE_RETURN_FAILURE); connection = nm_act_request_get_applied_connection(req); g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + nm_g_object_ref_set(&priv->device, device); + setting_name = nm_connection_need_secrets(connection, &hints); if (!setting_name) { nm_assert(!hints); @@ -1015,24 +961,99 @@ nm_modem_act_stage1_prepare(NMModem * self, modem_secrets_cb, self); g_return_val_if_fail(priv->secrets_id, NM_ACT_STAGE_RETURN_FAILURE); - g_signal_emit(self, signals[AUTH_REQUESTED], 0); + nm_modem_emit_auth_requested(self); return NM_ACT_STAGE_RETURN_POSTPONE; } /*****************************************************************************/ -void -nm_modem_act_stage2_config(NMModem *self) +NMActStageReturn +nm_modem_act_stage2_config(NMModem *self, NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMModemPrivate *priv; + gboolean needs_ppp; - g_return_if_fail(NM_IS_MODEM(self)); + 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); priv = NM_MODEM_GET_PRIVATE(self); + + g_return_val_if_fail(priv->device == device, NM_ACT_STAGE_RETURN_FAILURE); + /* Clear secrets tries counter since secrets were successfully used * already if we get here. */ priv->secrets_tries = 0; + + needs_ppp = + (priv->ip4_method == NM_MODEM_IP_METHOD_PPP || priv->ip6_method == NM_MODEM_IP_METHOD_PPP); + + if (needs_ppp && !priv->ppp_mgr) { + const char *ppp_name = NULL; + gs_free_error GError *error = NULL; + guint ip_timeout; + guint baud_override; + NMActRequest *req; + + req = nm_device_get_act_request(device); + g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); + + if (NM_MODEM_GET_CLASS(self)->get_user_pass) { + NMConnection *connection = nm_act_request_get_applied_connection(req); + + g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + if (!NM_MODEM_GET_CLASS(self)->get_user_pass(self, connection, &ppp_name, NULL)) + return NM_ACT_STAGE_RETURN_FAILURE; + } + + if (!priv->data_port) { + _LOGW("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) { + _LOGI("using modem-specified IP timeout: %u seconds", priv->mm_ip_timeout); + ip_timeout = priv->mm_ip_timeout; + } else + ip_timeout = 30; + + /* Some tty drivers and modems ignore port speed, but pppd requires the + * port speed to be > 0 or it exits. If the port speed is 0 pass an + * explicit speed to pppd to prevent the exit. + * https://bugzilla.redhat.com/show_bug.cgi?id=1281731 + */ + if (port_speed_is_zero(priv->data_port)) + baud_override = 57600; + else + baud_override = 0; + + priv->ppp_mgr = nm_ppp_mgr_start(&((const NMPppMgrConfig){ + .netns = nm_device_get_netns(device), + .parent_iface = priv->data_port, + .callback = _ppp_mgr_callback, + .user_data = self, + .act_req = req, + .ppp_username = ppp_name, + .timeout_secs = ip_timeout, + .baud_override = baud_override, + }), + &error); + if (!priv->ppp_mgr) { + _LOGW("PPP failed to start: %s", error->message); + *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + return NM_ACT_STAGE_RETURN_POSTPONE; + } + + if (needs_ppp && nm_ppp_mgr_get_state(priv->ppp_mgr) < NM_PPP_MGR_STATE_HAVE_IFINDEX) + return NM_ACT_STAGE_RETURN_POSTPONE; + + return NM_ACT_STAGE_RETURN_SUCCESS; } /*****************************************************************************/ @@ -1044,7 +1065,7 @@ nm_modem_check_connection_compatible(NMModem *self, NMConnection *connection, GE if (nm_streq0(nm_connection_get_connection_type(connection), NM_SETTING_GSM_SETTING_NAME)) { NMSettingGsm *s_gsm; - const char * str; + const char *str; s_gsm = _nm_connection_check_main_setting(connection, NM_SETTING_GSM_SETTING_NAME, error); if (!s_gsm) @@ -1098,11 +1119,11 @@ nm_modem_check_connection_compatible(NMModem *self, NMConnection *connection, GE /*****************************************************************************/ gboolean -nm_modem_complete_connection(NMModem * self, - const char * iface, - NMConnection * connection, +nm_modem_complete_connection(NMModem *self, + const char *iface, + NMConnection *connection, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMModemClass *klass; @@ -1126,27 +1147,26 @@ deactivate_cleanup(NMModem *self, NMDevice *device, gboolean stop_ppp_manager) { NMModemPrivate *priv; int ifindex; + int IS_IPv4; g_return_if_fail(NM_IS_MODEM(self)); priv = NM_MODEM_GET_PRIVATE(self); + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + priv->ip_data_x[IS_IPv4].stage3_started = FALSE; + nm_clear_g_source_inst(&priv->ip_data_x[IS_IPv4].stage3_on_idle_source); + } + priv->secrets_tries = 0; - if (priv->act_request) { + if (priv->act_req) { cancel_get_secrets(self); - g_object_unref(priv->act_request); - priv->act_request = NULL; + g_clear_object(&priv->act_req); } + g_clear_object(&priv->device); - priv->in_bytes = priv->out_bytes = 0; - - if (priv->ppp_manager) { - g_signal_handlers_disconnect_by_data(priv->ppp_manager, self); - if (stop_ppp_manager) - nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL); - g_clear_object(&priv->ppp_manager); - } + _ppp_mgr_cleanup(self); if (device) { g_return_if_fail(NM_IS_DEVICE(device)); @@ -1170,15 +1190,15 @@ deactivate_cleanup(NMModem *self, NMDevice *device, gboolean stop_ppp_manager) 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); + _set_ip_ifindex(self, -1); } /*****************************************************************************/ typedef struct { - NMModem * self; - NMDevice * device; - GCancellable * cancellable; + NMModem *self; + NMDevice *device; + GCancellable *cancellable; NMModemDeactivateCallback callback; gpointer callback_user_data; } DeactivateContext; @@ -1216,7 +1236,7 @@ _deactivate_call_disconnect(DeactivateContext *ctx) } static void -_deactivate_ppp_manager_stop_cb(NMPPPManager * ppp_manager, +_deactivate_ppp_manager_stop_cb(NMPPPManager *ppp_manager, NMPPPManagerStopHandle *handle, gboolean was_cancelled, gpointer user_data) @@ -1239,15 +1259,15 @@ _deactivate_ppp_manager_stop_cb(NMPPPManager * ppp_manager, } void -nm_modem_deactivate_async(NMModem * self, - NMDevice * device, - GCancellable * cancellable, +nm_modem_deactivate_async(NMModem *self, + NMDevice *device, + GCancellable *cancellable, NMModemDeactivateCallback callback, gpointer user_data) { - NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); DeactivateContext *ctx; - NMPPPManager * ppp_manager; + NMPPPManager *ppp_manager; g_return_if_fail(NM_IS_MODEM(self)); g_return_if_fail(NM_IS_DEVICE(device)); @@ -1307,11 +1327,11 @@ nm_modem_device_state_changed(NMModem *self, NMDeviceState new_state, NMDeviceSt case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_FAILED: case NM_DEVICE_STATE_DISCONNECTED: - if (priv->act_request) { + if (priv->act_req) { cancel_get_secrets(self); - g_object_unref(priv->act_request); - priv->act_request = NULL; + g_clear_object(&priv->act_req); } + g_clear_object(&priv->device); if (was_connected) { /* Don't bother warning on FAILED since the modem is already gone */ @@ -1377,32 +1397,27 @@ nm_modem_get_ip_ifindex(NMModem *self) } static void -_set_ip_ifindex(NMModem *self, int ifindex, const char *ifname) +_set_ip_ifindex(NMModem *self, int ifindex) { 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) { + _LOGD("signal: ifindex changed: %d", ifindex); priv->ip_ifindex = ifindex; _notify(self, PROP_IP_IFINDEX); } } gboolean -nm_modem_set_data_port(NMModem * self, - NMPlatform * platform, - const char * data_port, +nm_modem_set_data_port(NMModem *self, + NMPlatform *platform, + const char *data_port, NMModemIPMethod ip4_method, NMModemIPMethod ip6_method, guint timeout, - GError ** error) + GError **error) { NMModemPrivate *priv; gboolean is_ppp; @@ -1477,10 +1492,10 @@ nm_modem_set_data_port(NMModem * self, priv->ip6_method = ip6_method; if (is_ppp) { priv->data_port = g_strdup(data_port); - _set_ip_ifindex(self, -1, NULL); + _set_ip_ifindex(self, -1); } else { priv->data_port = NULL; - _set_ip_ifindex(self, ifindex, data_port); + _set_ip_ifindex(self, ifindex); } return TRUE; } @@ -1488,96 +1503,34 @@ nm_modem_set_data_port(NMModem * self, gboolean nm_modem_owns_port(NMModem *self, const char *iface) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + NMPlatform *platform; + const NMPlatformLink *plink; g_return_val_if_fail(iface != NULL, FALSE); 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); -} - -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; -} - -/*****************************************************************************/ - -void -nm_modem_get_route_parameters(NMModem *self, - guint32 *out_ip4_route_table, - guint32 *out_ip4_route_metric, - guint32 *out_ip6_route_table, - guint32 *out_ip6_route_metric) -{ - NMModemPrivate *priv; - - g_return_if_fail(NM_IS_MODEM(self)); - - priv = NM_MODEM_GET_PRIVATE(self); - NM_SET_OUT(out_ip4_route_table, priv->ip4_route_table); - NM_SET_OUT(out_ip4_route_metric, priv->ip4_route_metric); - NM_SET_OUT(out_ip6_route_table, priv->ip6_route_table); - NM_SET_OUT(out_ip6_route_metric, priv->ip6_route_metric); -} - -void -nm_modem_set_route_parameters(NMModem *self, - guint32 ip4_route_table, - guint32 ip4_route_metric, - guint32 ip6_route_table, - guint32 ip6_route_metric) -{ - NMModemPrivate *priv; - - g_return_if_fail(NM_IS_MODEM(self)); - - priv = NM_MODEM_GET_PRIVATE(self); - if (priv->ip4_route_table != ip4_route_table || priv->ip4_route_metric != ip4_route_metric - || priv->ip6_route_table != ip6_route_table || priv->ip6_route_metric != ip6_route_metric) { - priv->ip4_route_table = ip4_route_table; - priv->ip4_route_metric = ip4_route_metric; - priv->ip6_route_table = ip6_route_table; - priv->ip6_route_metric = ip6_route_metric; - - _LOGT("route-parameters: table-v4: %u, metric-v4: %u, table-v6: %u, metric-v6: %u", - priv->ip4_route_table, - priv->ip4_route_metric, - priv->ip6_route_table, - priv->ip6_route_metric); - } - - if (priv->ppp_manager) { - nm_ppp_manager_set_route_parameters(priv->ppp_manager, - priv->ip4_route_table, - priv->ip4_route_metric, - priv->ip6_route_table, - priv->ip6_route_metric); - } -} + if (NM_IN_STRSET(iface, priv->data_port, priv->control_port)) + return TRUE; -void -nm_modem_set_route_parameters_from_device(NMModem *self, NMDevice *device) -{ - g_return_if_fail(NM_IS_DEVICE(device)); + /* FIXME(parent-child-relationship): the whole notion of "owns-port" is wrong. + * When we have a name (iface) it must be always clear what this name is (which + * domain). Mixing data_port, control_port and devlink names is wrong. Looking + * up devlinks by name is also wrong (use ifindex). */ + if (priv->ip_ifindex > 0 && (platform = _get_platform(self)) + && (plink = nm_platform_link_get(platform, priv->ip_ifindex)) + && nm_streq(iface, plink->name)) + return TRUE; - nm_modem_set_route_parameters(self, - nm_device_get_route_table(device, AF_INET), - nm_device_get_route_metric(device, AF_INET), - nm_device_get_route_table(device, AF_INET6), - nm_device_get_route_metric(device, AF_INET6)); + return FALSE; } /*****************************************************************************/ void -nm_modem_get_capabilities(NMModem * self, +nm_modem_get_capabilities(NMModem *self, NMDeviceModemCapabilities *modem_caps, NMDeviceModemCapabilities *current_caps) { @@ -1593,9 +1546,10 @@ _nm_modem_set_operator_code(NMModem *self, const char *operator_code) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); - if (g_strcmp0(priv->operator_code, operator_code) != 0) { + if (!nm_streq0(priv->operator_code, operator_code)) { g_free(priv->operator_code); priv->operator_code = g_strdup(operator_code); + _LOGD("signal: operator-code changed: %s%s%s", NM_PRINT_FMT_QUOTE_STRING(operator_code)); _notify(self, PROP_OPERATOR_CODE); } } @@ -1605,9 +1559,10 @@ _nm_modem_set_apn(NMModem *self, const char *apn) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); - if (g_strcmp0(priv->apn, apn) != 0) { + if (!nm_streq0(priv->apn, apn)) { g_free(priv->apn); priv->apn = g_strdup(apn); + _LOGD("signal: apn changed: %s%s%s", NM_PRINT_FMT_QUOTE_STRING(apn)); _notify(self, PROP_APN); } } @@ -1615,7 +1570,7 @@ _nm_modem_set_apn(NMModem *self, const char *apn) static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMModem * self = NM_MODEM(object); + NMModem *self = NM_MODEM(object); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); switch (prop_id) { @@ -1665,7 +1620,7 @@ static void set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(object); - const char * s; + const char *s; switch (prop_id) { case PROP_PATH: @@ -1726,11 +1681,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; - priv->ip6_route_metric = 700; + priv->ip_ifindex = -1; } static void @@ -1752,7 +1703,8 @@ dispose(GObject *object) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(object); - g_clear_object(&priv->act_request); + g_clear_object(&priv->act_req); + g_clear_object(&priv->device); G_OBJECT_CLASS(nm_modem_parent_class)->dispose(object); } @@ -1767,7 +1719,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); @@ -1790,9 +1741,8 @@ nm_modem_class_init(NMModemClass *klass) object_class->dispose = dispose; object_class->finalize = finalize; - klass->modem_act_stage1_prepare = modem_act_stage1_prepare; - klass->stage3_ip6_config_request = stage3_ip6_config_request; - klass->deactivate_cleanup = deactivate_cleanup; + klass->modem_act_stage1_prepare = modem_act_stage1_prepare; + klass->deactivate_cleanup = deactivate_cleanup; obj_properties[PROP_UID] = g_param_spec_string(NM_MODEM_UID, @@ -1904,43 +1854,28 @@ nm_modem_class_init(NMModemClass *klass) 1, G_TYPE_UINT); - signals[IP4_CONFIG_RESULT] = g_signal_new(NM_MODEM_IP4_CONFIG_RESULT, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 2, - G_TYPE_OBJECT, - G_TYPE_POINTER); - - /** - * NMModem::ip6-config-result: - * @modem: the #NMModem on which the signal is emitted - * @config: the #NMIP6Config to apply to the modem's data port - * @do_slaac: %TRUE if IPv6 SLAAC should be started - * @error: a #GError if any error occurred during IP configuration - * - * This signal is emitted when IPv6 configuration has completed or failed. - * If @error is set the configuration failed. If @config is set, then + /* + * This signal is emitted when IP configuration has completed or failed. + * If @error is set the configuration failed. If @l3cd is set, then * the details should be applied to the data port before any further - * configuration (like SLAAC) is done. @do_slaac indicates whether SLAAC - * should be started after applying @config to the data port. + * configuration (like SLAAC) is done. @do_auto indicates whether DHCPv4/SLAAC + * should be started after applying @l3cd to the data port. */ - signals[IP6_CONFIG_RESULT] = g_signal_new(NM_MODEM_IP6_CONFIG_RESULT, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 3, - G_TYPE_OBJECT, - G_TYPE_BOOLEAN, - G_TYPE_POINTER); + signals[NEW_CONFIG] = g_signal_new(NM_MODEM_NEW_CONFIG, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 6, + G_TYPE_INT, /* int addr_family */ + G_TYPE_POINTER, /* const NML3ConfigData *l3cd */ + G_TYPE_BOOLEAN, /* gboolean do_auto */ + G_TYPE_POINTER, /* const NMUtilsIPv6IfaceId *iid */ + G_TYPE_INT, /* NMDeviceStateReason failure_reason */ + G_TYPE_POINTER); /* GError *error */ signals[PREPARE_RESULT] = g_signal_new(NM_MODEM_PREPARE_RESULT, G_OBJECT_CLASS_TYPE(object_class), diff --git a/src/core/devices/wwan/nm-modem.h b/src/core/devices/wwan/nm-modem.h index 4bc81ff8..ca541073 100644 --- a/src/core/devices/wwan/nm-modem.h +++ b/src/core/devices/wwan/nm-modem.h @@ -32,15 +32,14 @@ #define NM_MODEM_APN "apn" /* Signals */ -#define NM_MODEM_PPP_STATS "ppp-stats" -#define NM_MODEM_PPP_FAILED "ppp-failed" -#define NM_MODEM_PREPARE_RESULT "prepare-result" -#define NM_MODEM_IP4_CONFIG_RESULT "ip4-config-result" -#define NM_MODEM_IP6_CONFIG_RESULT "ip6-config-result" -#define NM_MODEM_AUTH_REQUESTED "auth-requested" -#define NM_MODEM_AUTH_RESULT "auth-result" -#define NM_MODEM_REMOVED "removed" -#define NM_MODEM_STATE_CHANGED "state-changed" +#define NM_MODEM_PPP_STATS "ppp-stats" +#define NM_MODEM_PPP_FAILED "ppp-failed" +#define NM_MODEM_PREPARE_RESULT "prepare-result" +#define NM_MODEM_NEW_CONFIG "new-config" +#define NM_MODEM_AUTH_REQUESTED "auth-requested" +#define NM_MODEM_AUTH_RESULT "auth-result" +#define NM_MODEM_REMOVED "removed" +#define NM_MODEM_STATE_CHANGED "state-changed" typedef enum { NM_MODEM_IP_METHOD_UNKNOWN = 0, @@ -101,44 +100,36 @@ typedef void (*_NMModemDisconnectCallback)(NMModem *modem, GError *error, gpoint typedef struct { GObjectClass parent; - void (*get_capabilities)(NMModem * self, + void (*get_capabilities)(NMModem *self, NMDeviceModemCapabilities *modem_caps, NMDeviceModemCapabilities *current_caps); - gboolean (*get_user_pass)(NMModem * modem, + gboolean (*get_user_pass)(NMModem *modem, NMConnection *connection, - const char ** user, - const char ** pass); + const char **user, + const char **pass); - gboolean (*check_connection_compatible_with_modem)(NMModem * modem, + gboolean (*check_connection_compatible_with_modem)(NMModem *modem, NMConnection *connection, - GError ** error); + GError **error); - gboolean (*complete_connection)(NMModem * modem, - const char * iface, - NMConnection * connection, + gboolean (*complete_connection)(NMModem *modem, + const char *iface, + NMConnection *connection, NMConnection *const *existing_connections, - GError ** error); + GError **error); - NMActStageReturn (*modem_act_stage1_prepare)(NMModem * modem, - NMConnection * connection, + NMActStageReturn (*modem_act_stage1_prepare)(NMModem *modem, + NMConnection *connection, NMDeviceStateReason *out_failure_reason); - NMActStageReturn (*static_stage3_ip4_config_start)(NMModem * self, - NMActRequest * req, - NMDeviceStateReason *out_failure_reason); - - /* Request the IP6 config; when the config returns the modem - * subclass should emit the ip6_config_result signal. - */ - NMActStageReturn (*stage3_ip6_config_request)(NMModem * self, - NMDeviceStateReason *out_failure_reason); + void (*stage3_ip_config_start)(NMModem *self, int addr_family, NMModemIPMethod method); void (*set_mm_enabled)(NMModem *self, gboolean enabled); - void (*disconnect)(NMModem * self, + void (*disconnect)(NMModem *self, gboolean warn, - GCancellable * cancellable, + GCancellable *cancellable, _NMModemDisconnectCallback callback, gpointer user_data); @@ -161,65 +152,43 @@ const char *nm_modem_get_driver(NMModem *modem); const char *nm_modem_get_device_id(NMModem *modem); const char *nm_modem_get_sim_id(NMModem *modem); const char *nm_modem_get_sim_operator_id(NMModem *modem); -gboolean nm_modem_get_iid(NMModem *modem, NMUtilsIPv6IfaceId *out_iid); const char *nm_modem_get_operator_code(NMModem *modem); const char *nm_modem_get_apn(NMModem *modem); -gboolean nm_modem_set_data_port(NMModem * self, - NMPlatform * platform, - const char * data_port, +gboolean nm_modem_set_data_port(NMModem *self, + NMPlatform *platform, + const char *data_port, NMModemIPMethod ip4_method, NMModemIPMethod ip6_method, guint timeout, - GError ** error); + GError **error); gboolean nm_modem_owns_port(NMModem *modem, const char *iface); -void nm_modem_get_capabilities(NMModem * self, +void nm_modem_get_capabilities(NMModem *self, NMDeviceModemCapabilities *modem_caps, NMDeviceModemCapabilities *current_caps); gboolean nm_modem_check_connection_compatible(NMModem *self, NMConnection *connection, GError **error); -gboolean nm_modem_complete_connection(NMModem * self, - const char * iface, - NMConnection * connection, +gboolean nm_modem_complete_connection(NMModem *self, + const char *iface, + NMConnection *connection, NMConnection *const *existing_connections, - GError ** error); - -void nm_modem_get_route_parameters(NMModem *self, - guint32 *out_ip4_route_table, - guint32 *out_ip4_route_metric, - guint32 *out_ip6_route_table, - guint32 *out_ip6_route_metric); - -void nm_modem_set_route_parameters(NMModem *self, - guint32 ip4_route_table, - guint32 ip4_route_metric, - guint32 ip6_route_table, - guint32 ip6_route_metric); - -void nm_modem_set_route_parameters_from_device(NMModem *modem, NMDevice *device); + GError **error); -NMActStageReturn nm_modem_act_stage1_prepare(NMModem * modem, - NMActRequest * req, +NMActStageReturn nm_modem_act_stage1_prepare(NMModem *modem, + NMActRequest *req, NMDeviceStateReason *out_failure_reason); -void nm_modem_act_stage2_config(NMModem *modem); +NMActStageReturn nm_modem_act_stage2_config(NMModem *self, + NMDevice *device, + NMDeviceStateReason *out_failure_reason); -NMActStageReturn nm_modem_stage3_ip4_config_start(NMModem * modem, - NMDevice * device, - gboolean * out_autoip4, - NMDeviceStateReason *out_failure_reason); +gboolean nm_modem_stage3_ip_config_start(NMModem *self, int addr_family, NMDevice *device); -NMActStageReturn nm_modem_stage3_ip6_config_start(NMModem * modem, - NMDevice * device, - NMDeviceStateReason *out_failure_reason); - -void nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config); - -void nm_modem_get_secrets(NMModem * modem, +void nm_modem_get_secrets(NMModem *modem, const char *setting_name, gboolean request_new, const char *hint); @@ -228,9 +197,9 @@ void nm_modem_deactivate(NMModem *modem, NMDevice *device); typedef void (*NMModemDeactivateCallback)(NMModem *self, GError *error, gpointer user_data); -void nm_modem_deactivate_async(NMModem * self, - NMDevice * device, - GCancellable * cancellable, +void nm_modem_deactivate_async(NMModem *self, + NMDevice *device, + GCancellable *cancellable, NMModemDeactivateCallback callback, gpointer user_data); @@ -242,13 +211,15 @@ void nm_modem_set_mm_enabled(NMModem *self, gboolean enabled); NMModemState nm_modem_get_state(NMModem *self); void nm_modem_set_state(NMModem *self, NMModemState new_state, const char *reason); void nm_modem_set_prev_state(NMModem *self, const char *reason); -const char * nm_modem_state_to_string(NMModemState state); +const char *nm_modem_state_to_string(NMModemState state); NMModemIPType nm_modem_get_supported_ip_types(NMModem *self); /* For the modem-manager only */ void nm_modem_emit_removed(NMModem *self); +void nm_modem_emit_auth_requested(NMModem *self); + void nm_modem_emit_prepare_result(NMModem *self, gboolean success, NMDeviceStateReason reason); void nm_modem_emit_ppp_failed(NMModem *self, NMDeviceStateReason reason); @@ -256,7 +227,23 @@ void nm_modem_emit_ppp_failed(NMModem *self, NMDeviceStateReason reason); GArray *nm_modem_get_connection_ip_type(NMModem *self, NMConnection *connection, GError **error); /* For subclasses */ -void nm_modem_emit_ip6_config_result(NMModem *self, NMIP6Config *config, GError *error); + +void nm_modem_emit_signal_new_config(NMModem *self, + int addr_family, + const NML3ConfigData *l3cd, + gboolean do_slaac, + const NMUtilsIPv6IfaceId *iid, + NMDeviceStateReason failure_reason, + GError *error); +void nm_modem_emit_signal_new_config_success(NMModem *self, + int addr_family, + const NML3ConfigData *l3cd, + gboolean do_auto, + const NMUtilsIPv6IfaceId *iid); +void nm_modem_emit_signal_new_config_failure(NMModem *self, + int addr_family, + NMDeviceStateReason failure_reason, + GError *error); const char *nm_modem_ip_type_to_string(NMModemIPType ip_type); diff --git a/src/core/devices/wwan/nm-service-providers.c b/src/core/devices/wwan/nm-service-providers.c index 89add6c5..83f21565 100644 --- a/src/core/devices/wwan/nm-service-providers.c +++ b/src/core/devices/wwan/nm-service-providers.c @@ -22,33 +22,33 @@ typedef enum { } ParseContextState; typedef struct { - char * mccmnc; + char *mccmnc; NMServiceProvidersGsmApnCallback callback; gpointer user_data; - GCancellable * cancellable; - GMarkupParseContext * ctx; + GCancellable *cancellable; + GMarkupParseContext *ctx; char buffer[4096]; - char * text_buffer; + char *text_buffer; ParseContextState state; gboolean mccmnc_matched; gboolean found_internet_apn; - char * apn; - char * username; - char * password; - char * gateway; - char * auth_method; - GSList * dns; + char *apn; + char *username; + char *password; + char *gateway; + char *auth_method; + GSList *dns; } ParseContext; /*****************************************************************************/ static void parser_toplevel_start(ParseContext *parse_context, - const char * name, - const char ** attribute_names, - const char ** attribute_values) + const char *name, + const char **attribute_names, + const char **attribute_values) { int i; @@ -72,9 +72,9 @@ parser_toplevel_start(ParseContext *parse_context, static void parser_country_start(ParseContext *parse_context, - const char * name, - const char ** attribute_names, - const char ** attribute_values) + const char *name, + const char **attribute_names, + const char **attribute_values) { if (strcmp(name, "provider") == 0) parse_context->state = PARSER_PROVIDER; @@ -82,9 +82,9 @@ parser_country_start(ParseContext *parse_context, static void parser_provider_start(ParseContext *parse_context, - const char * name, - const char ** attribute_names, - const char ** attribute_values) + const char *name, + const char **attribute_names, + const char **attribute_values) { parse_context->mccmnc_matched = FALSE; if (strcmp(name, "gsm") == 0) @@ -95,9 +95,9 @@ parser_provider_start(ParseContext *parse_context, static void parser_gsm_start(ParseContext *parse_context, - const char * name, - const char ** attribute_names, - const char ** attribute_values) + const char *name, + const char **attribute_names, + const char **attribute_values) { int i; @@ -140,9 +140,9 @@ parser_gsm_start(ParseContext *parse_context, static void parser_gsm_apn_start(ParseContext *parse_context, - const char * name, - const char ** attribute_names, - const char ** attribute_values) + const char *name, + const char **attribute_names, + const char **attribute_values) { int i; @@ -167,11 +167,11 @@ parser_gsm_apn_start(ParseContext *parse_context, static void parser_start_element(GMarkupParseContext *context, - const char * element_name, - const char ** attribute_names, - const char ** attribute_values, + const char *element_name, + const char **attribute_names, + const char **attribute_values, gpointer user_data, - GError ** error) + GError **error) { ParseContext *parse_context = user_data; @@ -265,9 +265,9 @@ parser_cdma_end(ParseContext *parse_context, const char *name) static void parser_end_element(GMarkupParseContext *context, - const char * element_name, + const char *element_name, gpointer user_data, - GError ** error) + GError **error) { ParseContext *parse_context = user_data; @@ -298,10 +298,10 @@ parser_end_element(GMarkupParseContext *context, static void parser_text(GMarkupParseContext *context, - const char * text, + const char *text, gsize text_len, gpointer user_data, - GError ** error) + GError **error) { ParseContext *parse_context = user_data; @@ -360,7 +360,7 @@ stream_read_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) GInputStream *stream = G_INPUT_STREAM(source_object); ParseContext *parse_context = user_data; gssize len; - GError * error = NULL; + GError *error = NULL; len = g_input_stream_read_finish(stream, res, &error); if (len == -1) { @@ -411,9 +411,9 @@ read_next_chunk(GInputStream *stream, ParseContext *parse_context) static void file_read_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - GFile * file = G_FILE(source_object); - ParseContext * parse_context = user_data; - GFileInputStream *stream; + GFile *file = G_FILE(source_object); + ParseContext *parse_context = user_data; + GFileInputStream *stream; gs_free_error GError *error = NULL; stream = g_file_read_finish(file, res, &error); @@ -431,13 +431,13 @@ file_read_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) /*****************************************************************************/ void -nm_service_providers_find_gsm_apn(const char * service_providers, - const char * mccmnc, - GCancellable * cancellable, +nm_service_providers_find_gsm_apn(const char *service_providers, + const char *mccmnc, + GCancellable *cancellable, NMServiceProvidersGsmApnCallback callback, gpointer user_data) { - GFile * file; + GFile *file; ParseContext *parse_context; parse_context = g_slice_new0(ParseContext); diff --git a/src/core/devices/wwan/nm-service-providers.h b/src/core/devices/wwan/nm-service-providers.h index 959f660a..cf90ef1e 100644 --- a/src/core/devices/wwan/nm-service-providers.h +++ b/src/core/devices/wwan/nm-service-providers.h @@ -6,18 +6,18 @@ #ifndef __NETWORKMANAGER_SERVICE_PROVIDERS_H__ #define __NETWORKMANAGER_SERVICE_PROVIDERS_H__ -typedef void (*NMServiceProvidersGsmApnCallback)(const char * apn, - const char * username, - const char * password, - const char * gateway, - const char * auth_method, +typedef void (*NMServiceProvidersGsmApnCallback)(const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, const GSList *dns, - GError * error, + GError *error, gpointer user_data); -void nm_service_providers_find_gsm_apn(const char * service_providers, - const char * mccmnc, - GCancellable * cancellable, +void nm_service_providers_find_gsm_apn(const char *service_providers, + const char *mccmnc, + GCancellable *cancellable, NMServiceProvidersGsmApnCallback callback, gpointer user_data); diff --git a/src/core/devices/wwan/nm-wwan-factory.c b/src/core/devices/wwan/nm-wwan-factory.c index 0d802ae1..169407c7 100644 --- a/src/core/devices/wwan/nm-wwan-factory.c +++ b/src/core/devices/wwan/nm-wwan-factory.c @@ -52,7 +52,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES(NM_DEVICE_FACTORY_DECLARE_LINK_TYPES( NM_SETTING_CDMA_SETTING_NAME)) G_MODULE_EXPORT NMDeviceFactory * - nm_device_factory_create(GError **error) +nm_device_factory_create(GError **error) { return g_object_new(NM_TYPE_WWAN_FACTORY, NULL); } @@ -62,9 +62,9 @@ G_MODULE_EXPORT NMDeviceFactory * static void modem_added_cb(NMModemManager *manager, NMModem *modem, gpointer user_data) { - NMWwanFactory * self = NM_WWAN_FACTORY(user_data); + NMWwanFactory *self = NM_WWAN_FACTORY(user_data); gs_unref_object NMDevice *device = NULL; - const char * driver; + const char *driver; if (nm_modem_is_claimed(modem)) return; @@ -89,11 +89,11 @@ modem_added_cb(NMModemManager *manager, NMModem *modem, gpointer user_data) } static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { g_return_val_if_fail(plink, NULL); g_return_val_if_fail(plink->type == NM_LINK_TYPE_WWAN_NET, NULL); @@ -104,7 +104,7 @@ create_device(NMDeviceFactory * factory, static void start(NMDeviceFactory *factory) { - NMWwanFactory * self = NM_WWAN_FACTORY(factory); + NMWwanFactory *self = NM_WWAN_FACTORY(factory); NMWwanFactoryPrivate *priv = NM_WWAN_FACTORY_GET_PRIVATE(self); priv->mm = g_object_ref(nm_modem_manager_get()); @@ -121,7 +121,7 @@ nm_wwan_factory_init(NMWwanFactory *self) static void dispose(GObject *object) { - NMWwanFactory * self = NM_WWAN_FACTORY(object); + NMWwanFactory *self = NM_WWAN_FACTORY(object); NMWwanFactoryPrivate *priv = NM_WWAN_FACTORY_GET_PRIVATE(self); if (priv->mm) @@ -135,7 +135,7 @@ dispose(GObject *object) static void nm_wwan_factory_class_init(NMWwanFactoryClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDeviceFactoryClass *factory_class = NM_DEVICE_FACTORY_CLASS(klass); object_class->dispose = dispose; diff --git a/src/core/devices/wwan/tests/test-service-providers.c b/src/core/devices/wwan/tests/test-service-providers.c index f95cccf8..e808b391 100644 --- a/src/core/devices/wwan/tests/test-service-providers.c +++ b/src/core/devices/wwan/tests/test-service-providers.c @@ -10,13 +10,13 @@ #include "nm-test-utils-core.h" static void -test_positive_cb(const char * apn, - const char * username, - const char * password, - const char * gateway, - const char * auth_method, +test_positive_cb(const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, const GSList *dns, - GError * error, + GError *error, gpointer user_data) { GMainLoop *loop = user_data; @@ -55,13 +55,13 @@ test_positive(void) /*****************************************************************************/ static void -test_negative_cb(const char * apn, - const char * username, - const char * password, - const char * gateway, - const char * auth_method, +test_negative_cb(const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, const GSList *dns, - GError * error, + GError *error, gpointer user_data) { GMainLoop *loop = user_data; @@ -88,13 +88,13 @@ test_negative(void) /*****************************************************************************/ static void -test_nonexistent_cb(const char * apn, - const char * username, - const char * password, - const char * gateway, - const char * auth_method, +test_nonexistent_cb(const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, const GSList *dns, - GError * error, + GError *error, gpointer user_data) { GMainLoop *loop = user_data; |