api,bearer: new 'apn-type' setting

This new setting allows the user setting up the connection to specify
the purpose of the connection being brought up.

Until now, we would always assume that connections are exclusively
brought up for connecting to the Internet, also limited by the
inability to connect to multiple different APNs at the same time.

But that may really not be true as there may be additional services
that may be accessed through other APNs, like MMS services or even
private networks for companies that have their own APNs on a given
operator (e.g. not that uncommon with banks and connected cars).

The new APN type setting will not change the way the bearer is
connected, but will allow the connection manager to decide what kind
of networking setup the specific connection needs.

This new setting can be provided by the user itself, or implicitly
read from the device if the device stores this information.
This commit is contained in:
Aleksander Morgado
2021-03-23 10:16:42 +01:00
parent 21ae558fe3
commit ff8e21b535
14 changed files with 222 additions and 1 deletions

View File

@@ -155,6 +155,7 @@ print_bearer_info (MMBearer *bearer)
/* Properties */
{
const gchar *apn = NULL;
gchar *apn_type_str = NULL;
const gchar *roaming = NULL;
gchar *ip_family_str = NULL;
const gchar *user = NULL;
@@ -164,6 +165,7 @@ print_bearer_info (MMBearer *bearer)
if (properties) {
apn = mm_bearer_properties_get_apn (properties);
apn_type_str = (properties ? mm_bearer_apn_type_build_string_from_mask (mm_bearer_properties_get_apn_type (properties)) : NULL);
ip_family_str = (properties ? mm_bearer_ip_family_build_string_from_mask (mm_bearer_properties_get_ip_type (properties)) : NULL);
allowed_auth_str = (properties ? mm_bearer_allowed_auth_build_string_from_mask (mm_bearer_properties_get_allowed_auth (properties)) : NULL);
user = mm_bearer_properties_get_user (properties);
@@ -175,6 +177,7 @@ print_bearer_info (MMBearer *bearer)
}
mmcli_output_string (MMC_F_BEARER_PROPERTIES_APN, apn);
mmcli_output_string_take (MMC_F_BEARER_PROPERTIES_APN_TYPE, apn_type_str);
mmcli_output_string (MMC_F_BEARER_PROPERTIES_ROAMING, roaming);
mmcli_output_string_take (MMC_F_BEARER_PROPERTIES_IP_TYPE, ip_family_str);
mmcli_output_string (MMC_F_BEARER_PROPERTIES_USER, user);

View File

@@ -212,6 +212,7 @@ static FieldInfo field_infos[] = {
[MMC_F_BEARER_STATUS_INTERFACE] = { "bearer.status.interface", "interface", MMC_S_BEARER_STATUS, },
[MMC_F_BEARER_STATUS_IP_TIMEOUT] = { "bearer.status.ip-timeout", "ip timeout", MMC_S_BEARER_STATUS, },
[MMC_F_BEARER_PROPERTIES_APN] = { "bearer.properties.apn", "apn", MMC_S_BEARER_PROPERTIES, },
[MMC_F_BEARER_PROPERTIES_APN_TYPE] = { "bearer.properties.apn-type", "apn type", MMC_S_BEARER_PROPERTIES, },
[MMC_F_BEARER_PROPERTIES_ROAMING] = { "bearer.properties.roaming", "roaming", MMC_S_BEARER_PROPERTIES, },
[MMC_F_BEARER_PROPERTIES_IP_TYPE] = { "bearer.properties.ip-type", "ip type", MMC_S_BEARER_PROPERTIES, },
[MMC_F_BEARER_PROPERTIES_ALLOWED_AUTH] = { "bearer.properties.allowed-auth", "allowed-auth", MMC_S_BEARER_PROPERTIES, },

View File

@@ -229,6 +229,7 @@ typedef enum {
MMC_F_BEARER_STATUS_IP_TIMEOUT,
/* Bearer properties section */
MMC_F_BEARER_PROPERTIES_APN,
MMC_F_BEARER_PROPERTIES_APN_TYPE,
MMC_F_BEARER_PROPERTIES_ROAMING,
MMC_F_BEARER_PROPERTIES_IP_TYPE,
MMC_F_BEARER_PROPERTIES_ALLOWED_AUTH,

View File

@@ -15,6 +15,7 @@ MMBearerIpFamily
MMBearerIpMethod
MMBearerAllowedAuth
MMBearerMultiplexSupport
MMBearerApnType
MMCallDirection
MMCallState
MMCallStateReason

View File

@@ -861,6 +861,8 @@ mm_simple_connect_properties_get_operator_id
mm_simple_connect_properties_set_operator_id
mm_simple_connect_properties_get_apn
mm_simple_connect_properties_set_apn
mm_simple_connect_properties_get_apn_type
mm_simple_connect_properties_set_apn_type
mm_simple_connect_properties_get_allowed_auth
mm_simple_connect_properties_set_allowed_auth
mm_simple_connect_properties_get_user
@@ -1183,6 +1185,8 @@ mm_bearer_properties_new
<SUBSECTION GettersSetters>
mm_bearer_properties_get_apn
mm_bearer_properties_set_apn
mm_bearer_properties_get_apn_type
mm_bearer_properties_set_apn_type
mm_bearer_properties_get_allowed_auth
mm_bearer_properties_set_allowed_auth
mm_bearer_properties_get_user
@@ -1536,6 +1540,7 @@ mm_bearer_ip_method_get_string
mm_bearer_ip_family_get_string
mm_bearer_allowed_auth_build_string_from_mask
mm_bearer_multiplex_support_get_string
mm_bearer_apn_type_build_string_from_mask
mm_modem_capability_build_string_from_mask
mm_modem_state_get_string
mm_modem_state_failed_reason_get_string
@@ -1599,6 +1604,7 @@ mm_bearer_ip_family_build_string_from_mask
mm_bearer_ip_method_build_string_from_mask
mm_bearer_allowed_auth_get_string
mm_bearer_multiplex_support_build_string_from_mask
mm_bearer_apn_type_get_string
mm_modem_cdma_registration_state_build_string_from_mask
mm_modem_cdma_activation_state_build_string_from_mask
mm_modem_cdma_rm_protocol_build_string_from_mask
@@ -1624,6 +1630,7 @@ MM_TYPE_BEARER_IP_FAMILY
MM_TYPE_BEARER_IP_METHOD
MM_TYPE_BEARER_ALLOWED_AUTH
MM_TYPE_BEARER_MULTIPLEX_SUPPORT
MM_TYPE_BEARER_APN_TYPE
MM_TYPE_FIRMWARE_IMAGE_TYPE
MM_TYPE_MODEM_3GPP_FACILITY
MM_TYPE_MODEM_3GPP_NETWORK_AVAILABILITY
@@ -1667,6 +1674,7 @@ mm_bearer_ip_family_get_type
mm_bearer_ip_method_get_type
mm_bearer_allowed_auth_get_type
mm_bearer_multiplex_support_get_type
mm_bearer_apn_type_get_type
mm_firmware_image_type_get_type
mm_modem_3gpp_facility_get_type
mm_modem_3gpp_network_availability_get_type

View File

@@ -1544,4 +1544,55 @@ typedef enum { /*< underscore_name=mm_bearer_multiplex_support >*/
MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED = 3,
} MMBearerMultiplexSupport;
/**
* MMBearerApnType:
* @MM_BEARER_APN_TYPE_NONE: Unknown or unsupported.
* @MM_BEARER_APN_TYPE_INITIAL: APN used for the initial attach procedure.
* @MM_BEARER_APN_TYPE_DEFAULT: Default connection APN providing access to the Internet.
* @MM_BEARER_APN_TYPE_IMS: APN providing access to IMS services.
* @MM_BEARER_APN_TYPE_MMS: APN providing access to MMS services.
* @MM_BEARER_APN_TYPE_MANAGEMENT: APN providing access to over-the-air device management procedures.
* @MM_BEARER_APN_TYPE_VOICE: APN providing access to voice-over-IP services.
* @MM_BEARER_APN_TYPE_EMERGENCY: APN providing access to emergency services.
* @MM_BEARER_APN_TYPE_PRIVATE: APN providing access to private networks.
*
* Purpose of the APN used in a given Bearer.
*
* This information may be stored in the device configuration (e.g. if carrier
* specific configurations have been enabled for the SIM in use), or provided
* explicitly by the user.
*
* If the mask of types includes %MM_BEARER_APN_TYPE_DEFAULT, it is expected
* that the connection manager will include a default route through the specific
* bearer connection to the public Internet.
*
* For any other mask type, it is expected that the connection manager will
* not setup a default route and will therefore require additional custom
* routing rules to provide access to the different services. E.g. a bearer
* connected with %MM_BEARER_APN_TYPE_MMS will probably require an explicit
* additional route in the host to access the MMSC server at the address
* specified by the operator. If this address relies on a domain name instead
* of a fixed IP address, the name resolution should be performed using the
* DNS servers specified in the corresponding bearer connection settings.
*
* If not explicitly specified during a connection attempt, the connection
* manager should be free to treat it with its own logic. E.g. a good default
* could be to treat the first connection as %MM_BEARER_APN_TYPE_DEFAULT (with
* a default route) and any other additional connection as
* %MM_BEARER_APN_TYPE_PRIVATE (without a default route).
*
* Since: 1.18
*/
typedef enum { /*< underscore_name=mm_bearer_apn_type >*/
MM_BEARER_APN_TYPE_NONE = 0,
MM_BEARER_APN_TYPE_INITIAL = 1 << 0,
MM_BEARER_APN_TYPE_DEFAULT = 1 << 1,
MM_BEARER_APN_TYPE_IMS = 1 << 2,
MM_BEARER_APN_TYPE_MMS = 1 << 3,
MM_BEARER_APN_TYPE_MANAGEMENT = 1 << 4,
MM_BEARER_APN_TYPE_VOICE = 1 << 5,
MM_BEARER_APN_TYPE_EMERGENCY = 1 << 6,
MM_BEARER_APN_TYPE_PRIVATE = 1 << 7,
} MMBearerApnType;
#endif /* _MODEMMANAGER_ENUMS_H_ */

View File

@@ -388,6 +388,13 @@
value (signature <literal>"u"</literal>).
</listitem>
</varlistentry>
<varlistentry><term><literal>"apn-type"</literal></term>
<listitem>
The purposes of the specified APN, given as a
<link linkend="MMBearerApnType">MMBearerApnType</link>
value (signature <literal>"u"</literal>).
</listitem>
</varlistentry>
<varlistentry><term><literal>"allowed-auth"</literal></term>
<listitem>
The authentication method to use, given as a

View File

@@ -38,6 +38,7 @@ G_DEFINE_TYPE (MMBearerProperties, mm_bearer_properties, G_TYPE_OBJECT);
#define PROPERTY_USER "user"
#define PROPERTY_PASSWORD "password"
#define PROPERTY_IP_TYPE "ip-type"
#define PROPERTY_APN_TYPE "apn-type"
#define PROPERTY_ALLOW_ROAMING "allow-roaming"
#define PROPERTY_RM_PROTOCOL "rm-protocol"
#define PROPERTY_MULTIPLEX "multiplex"
@@ -50,6 +51,8 @@ struct _MMBearerPropertiesPrivate {
gchar *apn;
/* IP type */
MMBearerIpFamily ip_type;
/* APN type */
MMBearerApnType apn_type;
/* Allowed auth */
MMBearerAllowedAuth allowed_auth;
/* User */
@@ -266,6 +269,44 @@ mm_bearer_properties_get_ip_type (MMBearerProperties *self)
/*****************************************************************************/
/**
* mm_bearer_properties_set_apn_type:
* @self: a #MMBearerProperties.
* @apn_type: a mask of #MMBearerApnType values.
*
* Sets the APN types to use.
*
* Since: 1.18
*/
void
mm_bearer_properties_set_apn_type (MMBearerProperties *self,
MMBearerApnType apn_type)
{
g_return_if_fail (MM_IS_BEARER_PROPERTIES (self));
self->priv->apn_type = apn_type;
}
/**
* mm_bearer_properties_get_apn_type:
* @self: a #MMBearerProperties.
*
* Gets the APN types to use.
*
* Returns: a mask of #MMBearerApnType values.
*
* Since: 1.18
*/
MMBearerApnType
mm_bearer_properties_get_apn_type (MMBearerProperties *self)
{
g_return_val_if_fail (MM_IS_BEARER_PROPERTIES (self), MM_BEARER_APN_TYPE_NONE);
return self->priv->apn_type;
}
/*****************************************************************************/
/**
* mm_bearer_properties_set_allow_roaming:
* @self: a #MMBearerProperties.
@@ -476,6 +517,12 @@ mm_bearer_properties_get_dictionary (MMBearerProperties *self)
PROPERTY_IP_TYPE,
g_variant_new_uint32 (self->priv->ip_type));
if (self->priv->apn_type != MM_BEARER_APN_TYPE_NONE)
g_variant_builder_add (&builder,
"{sv}",
PROPERTY_APN_TYPE,
g_variant_new_uint32 (self->priv->apn_type));
if (self->priv->allow_roaming_set)
g_variant_builder_add (&builder,
"{sv}",
@@ -536,6 +583,16 @@ mm_bearer_properties_consume_string (MMBearerProperties *self,
return FALSE;
}
mm_bearer_properties_set_ip_type (self, ip_type);
} else if (g_str_equal (key, PROPERTY_APN_TYPE)) {
GError *inner_error = NULL;
MMBearerApnType apn_type;
apn_type = mm_common_get_apn_type_from_string (value, &inner_error);
if (inner_error) {
g_propagate_error (error, inner_error);
return FALSE;
}
mm_bearer_properties_set_apn_type (self, apn_type);
} else if (g_str_equal (key, PROPERTY_ALLOW_ROAMING)) {
GError *inner_error = NULL;
gboolean allow_roaming;
@@ -655,6 +712,10 @@ mm_bearer_properties_consume_variant (MMBearerProperties *properties,
mm_bearer_properties_set_ip_type (
properties,
g_variant_get_uint32 (value));
else if (g_str_equal (key, PROPERTY_APN_TYPE))
mm_bearer_properties_set_apn_type (
properties,
g_variant_get_uint32 (value));
else if (g_str_equal (key, PROPERTY_ALLOW_ROAMING))
mm_bearer_properties_set_allow_roaming (
properties,
@@ -762,6 +823,23 @@ cmp_ip_type (MMBearerIpFamily a,
return FALSE;
}
static gboolean
cmp_apn_type (MMBearerApnType a,
MMBearerApnType b,
MMBearerPropertiesCmpFlags flags)
{
/* Strict match */
if (a == b)
return TRUE;
/* Additional loose match NONE == DEFAULT */
if (flags & MM_BEARER_PROPERTIES_CMP_FLAGS_LOOSE) {
if ((a == MM_BEARER_APN_TYPE_NONE && b == MM_BEARER_APN_TYPE_DEFAULT) ||
(b == MM_BEARER_APN_TYPE_NONE && a == MM_BEARER_APN_TYPE_DEFAULT))
return TRUE;
}
return FALSE;
}
static gboolean
cmp_allowed_auth (MMBearerAllowedAuth a,
MMBearerAllowedAuth b,
@@ -813,8 +891,11 @@ mm_bearer_properties_cmp (MMBearerProperties *a,
if (!cmp_allowed_auth (a->priv->allowed_auth, b->priv->allowed_auth, flags))
return FALSE;
if (!cmp_str (a->priv->user, b->priv->user, flags))
if (!(flags & MM_BEARER_PROPERTIES_CMP_FLAGS_NO_APN_TYPE) &&
!cmp_apn_type (a->priv->apn_type, b->priv->apn_type, flags))
return FALSE;
if (!(flags & MM_BEARER_PROPERTIES_CMP_FLAGS_NO_PASSWORD) && !cmp_str (a->priv->password, b->priv->password, flags))
if (!(flags & MM_BEARER_PROPERTIES_CMP_FLAGS_NO_PASSWORD) &&
!cmp_str (a->priv->password, b->priv->password, flags))
return FALSE;
if (!(flags & MM_BEARER_PROPERTIES_CMP_FLAGS_NO_ALLOW_ROAMING)) {
if (a->priv->allow_roaming != b->priv->allow_roaming)
@@ -861,6 +942,7 @@ mm_bearer_properties_init (MMBearerProperties *self)
self->priv->rm_protocol = MM_MODEM_CDMA_RM_PROTOCOL_UNKNOWN;
self->priv->allowed_auth = MM_BEARER_ALLOWED_AUTH_UNKNOWN;
self->priv->ip_type = MM_BEARER_IP_FAMILY_NONE;
self->priv->apn_type = MM_BEARER_APN_TYPE_NONE;
self->priv->multiplex = MM_BEARER_MULTIPLEX_SUPPORT_UNKNOWN;
}

View File

@@ -68,6 +68,8 @@ void mm_bearer_properties_set_password (MMBearerProperties *self,
const gchar *password);
void mm_bearer_properties_set_ip_type (MMBearerProperties *self,
MMBearerIpFamily ip_type);
void mm_bearer_properties_set_apn_type (MMBearerProperties *self,
MMBearerApnType apn_type);
void mm_bearer_properties_set_allow_roaming (MMBearerProperties *self,
gboolean allow_roaming);
void mm_bearer_properties_set_rm_protocol (MMBearerProperties *self,
@@ -80,6 +82,7 @@ MMBearerAllowedAuth mm_bearer_properties_get_allowed_auth (MMBearerProper
const gchar *mm_bearer_properties_get_user (MMBearerProperties *self);
const gchar *mm_bearer_properties_get_password (MMBearerProperties *self);
MMBearerIpFamily mm_bearer_properties_get_ip_type (MMBearerProperties *self);
MMBearerApnType mm_bearer_properties_get_apn_type (MMBearerProperties *self);
gboolean mm_bearer_properties_get_allow_roaming (MMBearerProperties *self);
MMModemCdmaRmProtocol mm_bearer_properties_get_rm_protocol (MMBearerProperties *self);
MMBearerMultiplexSupport mm_bearer_properties_get_multiplex (MMBearerProperties *self);
@@ -122,6 +125,7 @@ typedef enum {
MM_BEARER_PROPERTIES_CMP_FLAGS_NO_PASSWORD = 1 << 1,
MM_BEARER_PROPERTIES_CMP_FLAGS_NO_ALLOW_ROAMING = 1 << 2,
MM_BEARER_PROPERTIES_CMP_FLAGS_NO_RM_PROTOCOL = 1 << 3,
MM_BEARER_PROPERTIES_CMP_FLAGS_NO_APN_TYPE = 1 << 4,
} MMBearerPropertiesCmpFlags;
gboolean mm_bearer_properties_cmp (MMBearerProperties *a,

View File

@@ -867,6 +867,16 @@ mm_common_get_multiplex_support_from_string (const gchar *str,
error);
}
MMBearerApnType
mm_common_get_apn_type_from_string (const gchar *str,
GError **error)
{
return _flags_from_string (MM_TYPE_BEARER_APN_TYPE,
str,
MM_BEARER_APN_TYPE_NONE,
error);
}
GArray *
mm_common_oma_pending_network_initiated_sessions_variant_to_garray (GVariant *variant)
{

View File

@@ -85,6 +85,9 @@ MMModemAccessTechnology mm_common_get_access_technology_from_string (const gchar
MMBearerMultiplexSupport mm_common_get_multiplex_support_from_string (const gchar *str,
GError **error);
MMBearerApnType mm_common_get_apn_type_from_string (const gchar *str,
GError **error);
GArray *mm_common_ports_variant_to_garray (GVariant *variant);
MMModemPortInfo *mm_common_ports_variant_to_array (GVariant *variant,
guint *n_ports);

View File

@@ -326,6 +326,44 @@ mm_simple_connect_properties_get_ip_type (MMSimpleConnectProperties *self)
/*****************************************************************************/
/**
* mm_simple_connect_properties_set_apn_type:
* @self: a #MMSimpleConnectProperties.
* @apn_type: a mask of #MMBearerApnType values.
*
* Sets the APN types to use.
*
* Since: 1.18
*/
void
mm_simple_connect_properties_set_apn_type (MMSimpleConnectProperties *self,
MMBearerApnType apn_type)
{
g_return_if_fail (MM_IS_SIMPLE_CONNECT_PROPERTIES (self));
mm_bearer_properties_set_apn_type (self->priv->bearer_properties, apn_type);
}
/**
* mm_simple_connect_properties_get_apn_type:
* @self: a #MMSimpleConnectProperties.
*
* Gets the APN types to use.
*
* Returns: a mask of #MMBearerApnType values.
*
* Since: 1.18
*/
MMBearerApnType
mm_simple_connect_properties_get_apn_type (MMSimpleConnectProperties *self)
{
g_return_val_if_fail (MM_IS_SIMPLE_CONNECT_PROPERTIES (self), MM_BEARER_APN_TYPE_NONE);
return mm_bearer_properties_get_apn_type (self->priv->bearer_properties);
}
/*****************************************************************************/
/**
* mm_simple_connect_properties_set_allow_roaming:
* @self: a #MMSimpleConnectProperties.

View File

@@ -74,6 +74,8 @@ void mm_simple_connect_properties_set_password (MMSimpleConnectProperties *
const gchar *password);
void mm_simple_connect_properties_set_ip_type (MMSimpleConnectProperties *self,
MMBearerIpFamily ip_type);
void mm_simple_connect_properties_set_apn_type (MMSimpleConnectProperties *self,
MMBearerApnType apn_type);
void mm_simple_connect_properties_set_allow_roaming (MMSimpleConnectProperties *self,
gboolean allow_roaming);
void mm_simple_connect_properties_set_rm_protocol (MMSimpleConnectProperties *self,
@@ -88,6 +90,7 @@ MMBearerAllowedAuth mm_simple_connect_properties_get_allowed_auth (MMSimp
const gchar *mm_simple_connect_properties_get_user (MMSimpleConnectProperties *self);
const gchar *mm_simple_connect_properties_get_password (MMSimpleConnectProperties *self);
MMBearerIpFamily mm_simple_connect_properties_get_ip_type (MMSimpleConnectProperties *self);
MMBearerApnType mm_simple_connect_properties_get_apn_type (MMSimpleConnectProperties *self);
gboolean mm_simple_connect_properties_get_allow_roaming (MMSimpleConnectProperties *self);
MMModemCdmaRmProtocol mm_simple_connect_properties_get_rm_protocol (MMSimpleConnectProperties *self);
MMBearerMultiplexSupport mm_simple_connect_properties_get_multiplex (MMSimpleConnectProperties *self);

View File

@@ -691,6 +691,7 @@ connect_auth_ready (MMBaseModem *self,
{
MMBearerMultiplexSupport multiplex;
MMBearerAllowedAuth allowed_auth;
MMBearerApnType apn_type;
gchar *str;
MMBearerIpFamily ip_family;
@@ -701,6 +702,14 @@ connect_auth_ready (MMBaseModem *self,
mm_obj_dbg (self, " allowed roaming: %s", mm_simple_connect_properties_get_allow_roaming (ctx->properties) ? "yes" : "no");
mm_obj_dbg (self, " APN: %s", VALIDATE_UNSPECIFIED (mm_simple_connect_properties_get_apn (ctx->properties)));
apn_type = mm_simple_connect_properties_get_apn_type (ctx->properties);
if (apn_type != MM_BEARER_APN_TYPE_NONE) {
str = mm_bearer_apn_type_build_string_from_mask (apn_type);
mm_obj_dbg (self, " APN type: %s", str);
g_free (str);
} else
mm_obj_dbg (self, " APN type: %s", VALIDATE_UNSPECIFIED (NULL));
ip_family = mm_simple_connect_properties_get_ip_type (ctx->properties);
if (ip_family != MM_BEARER_IP_FAMILY_NONE) {
str = mm_bearer_ip_family_build_string_from_mask (ip_family);