mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-31 21:50:11 +01:00
merge: branch 'lr/gsm-default-apn'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/98
This commit is contained in:
commit
beab85520a
22 changed files with 1000 additions and 78 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -209,6 +209,7 @@ test-*.trs
|
|||
/src/devices/tests/test-acd
|
||||
/src/devices/tests/test-lldp
|
||||
/src/devices/wifi/tests/test-devices-wifi
|
||||
/src/devices/wwan/tests/test-service-providers
|
||||
/src/dhcp/nm-dhcp-helper
|
||||
/src/dhcp/tests/test-dhcp-dhclient
|
||||
/src/dhcp/tests/test-dhcp-options
|
||||
|
|
|
|||
31
Makefile.am
31
Makefile.am
|
|
@ -3315,7 +3315,10 @@ src_devices_wwan_libnm_wwan_la_SOURCES = \
|
|||
src/devices/wwan/nm-modem-manager.c \
|
||||
src/devices/wwan/nm-modem-manager.h \
|
||||
src/devices/wwan/nm-modem.c \
|
||||
src/devices/wwan/nm-modem.h
|
||||
src/devices/wwan/nm-modem.h \
|
||||
src/devices/wwan/nm-service-providers.c \
|
||||
src/devices/wwan/nm-service-providers.h \
|
||||
$(NULL)
|
||||
|
||||
if WITH_OFONO
|
||||
src_devices_wwan_libnm_wwan_la_SOURCES += \
|
||||
|
|
@ -3364,11 +3367,35 @@ check-local-devices-wwan: src/devices/wwan/libnm-device-plugin-wwan.la src/devic
|
|||
|
||||
check_local += check-local-devices-wwan
|
||||
|
||||
src_devices_wwan_tests_test_service_providers_SOURCES = \
|
||||
src/devices/wwan/tests/test-service-providers.c \
|
||||
src/devices/wwan/nm-service-providers.c \
|
||||
src/devices/wwan/nm-service-providers.h \
|
||||
$(NULL)
|
||||
|
||||
src_devices_wwan_tests_test_service_providers_CPPFLAGS = \
|
||||
$(src_cppflags_base_test) \
|
||||
-I$(srcdir)/src/devices/wwan \
|
||||
$(NULL)
|
||||
|
||||
src_devices_wwan_tests_test_service_providers_LDFLAGS = \
|
||||
$(SANITIZER_EXEC_LDFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
src_devices_wwan_tests_test_service_providers_LDADD = \
|
||||
src/libNetworkManagerTest.la \
|
||||
$(GLIB_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
check_programs += src/devices/wwan/tests/test-service-providers
|
||||
|
||||
endif
|
||||
|
||||
EXTRA_DIST += \
|
||||
src/devices/wwan/libnm-wwan.ver \
|
||||
src/devices/wwan/meson.build
|
||||
src/devices/wwan/meson.build \
|
||||
src/devices/wwan/tests/test-service-providers.xml \
|
||||
$(NULL)
|
||||
|
||||
###############################################################################
|
||||
# src/devices/bluetooth
|
||||
|
|
|
|||
|
|
@ -5365,6 +5365,9 @@ static const NMMetaPropertyInfo *const property_infos_ETHTOOL[] = {
|
|||
#undef _CURRENT_NM_META_SETTING_TYPE
|
||||
#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_GSM
|
||||
static const NMMetaPropertyInfo *const property_infos_GSM[] = {
|
||||
PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_AUTO_CONFIG,
|
||||
.property_type = &_pt_gobject_bool,
|
||||
),
|
||||
PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_NUMBER,
|
||||
.property_type = &_pt_gobject_string,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@
|
|||
#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH N_("An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the priority may use all of the bandwidth allocated to its assigned group.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS N_("An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which the priority is mapped.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_GSM_APN N_("The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network. The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_GSM_AUTO_CONFIG N_("When TRUE, the settings such as APN, username, or password will default to values that match the network the modem will register to in the Mobile Broadband Provider database.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_GSM_DEVICE_ID N_("The device unique identifier (as given by the WWAN management service) which this connection applies to. If given, the connection will only apply to the specified device.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_GSM_HOME_ONLY N_("When TRUE, only connections to the home network will be allowed. Connections to roaming networks will not be made.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_GSM_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.")
|
||||
|
|
|
|||
|
|
@ -150,12 +150,12 @@ id
|
|||
path
|
||||
uuid
|
||||
<<<
|
||||
size: 4116
|
||||
size: 4159
|
||||
location: clients/tests/test-client.py:911:test_003()/12
|
||||
cmd: $NMCLI con s con-gsm1
|
||||
lang: C
|
||||
returncode: 0
|
||||
stdout: 3982 bytes
|
||||
stdout: 4025 bytes
|
||||
>>>
|
||||
connection.id: con-gsm1
|
||||
connection.uuid: UUID-con-gsm1-REPLACED-REPLACED-REPL
|
||||
|
|
@ -228,6 +228,7 @@ serial.bits: 8
|
|||
serial.parity: even
|
||||
serial.stopbits: 1
|
||||
serial.send-delay: 100
|
||||
gsm.auto-config: no
|
||||
gsm.number: --
|
||||
gsm.username: --
|
||||
gsm.password: <hidden>
|
||||
|
|
@ -247,12 +248,12 @@ proxy.pac-url: --
|
|||
proxy.pac-script: --
|
||||
|
||||
<<<
|
||||
size: 4145
|
||||
size: 4189
|
||||
location: clients/tests/test-client.py:911:test_003()/13
|
||||
cmd: $NMCLI con s con-gsm1
|
||||
lang: pl_PL.UTF-8
|
||||
returncode: 0
|
||||
stdout: 4001 bytes
|
||||
stdout: 4045 bytes
|
||||
>>>
|
||||
connection.id: con-gsm1
|
||||
connection.uuid: UUID-con-gsm1-REPLACED-REPLACED-REPL
|
||||
|
|
@ -325,6 +326,7 @@ serial.bits: 8
|
|||
serial.parity: even
|
||||
serial.stopbits: 1
|
||||
serial.send-delay: 100
|
||||
gsm.auto-config: nie
|
||||
gsm.number: --
|
||||
gsm.username: --
|
||||
gsm.password: <hidden>
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@
|
|||
/* Define to path of the kernel firmware directory */
|
||||
#mesondefine KERNEL_FIRMWARE_DIR
|
||||
|
||||
/* Mobile Broadband Service Provider Information Database location */
|
||||
#mesondefine MOBILE_BROADBAND_PROVIDER_INFO_DATABASE
|
||||
|
||||
/* Path to netconfig */
|
||||
#mesondefine NETCONFIG_PATH
|
||||
|
||||
|
|
|
|||
10
configure.ac
10
configure.ac
|
|
@ -747,10 +747,20 @@ if (test "${with_modem_manager_1}" != "no"); then
|
|||
fi
|
||||
else
|
||||
with_modem_manager_1="yes"
|
||||
|
||||
PKG_CHECK_MODULES(MOBILE_BROADBAND_PROVIDER_INFO, [mobile-broadband-provider-info],
|
||||
[MOBILE_BROADBAND_PROVIDER_INFO_DATABASE=`$PKG_CONFIG --variable=database mobile-broadband-provider-info`],
|
||||
[MOBILE_BROADBAND_PROVIDER_INFO_DATABASE="$prefix/share/mobile-broadband-provider-info/serviceproviders.xml"])
|
||||
AC_DEFINE_UNQUOTED([MOBILE_BROADBAND_PROVIDER_INFO_DATABASE],
|
||||
["$MOBILE_BROADBAND_PROVIDER_INFO_DATABASE"],
|
||||
[Mobile Broadband Service Provider Information Database location])
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL(WITH_MODEM_MANAGER_1, test "${with_modem_manager_1}" = "yes")
|
||||
|
||||
|
||||
|
||||
|
||||
# Bluez5 DUN support
|
||||
PKG_CHECK_MODULES(BLUEZ5, [bluez >= 5], [have_bluez5=yes],[have_bluez5=no])
|
||||
AC_ARG_ENABLE(bluez5-dun,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ install \
|
|||
\
|
||||
ModemManager-devel \
|
||||
ModemManager-glib-devel \
|
||||
mobile-broadband-provider-info-devel \
|
||||
audit-libs-devel \
|
||||
bash-completion \
|
||||
bluez-libs-devel \
|
||||
|
|
|
|||
|
|
@ -219,6 +219,9 @@ BuildRequires: libndp-devel >= 1.0
|
|||
%if 0%{?with_modem_manager_1}
|
||||
BuildRequires: ModemManager-glib-devel >= 1.0
|
||||
%endif
|
||||
%if %{with wwan}
|
||||
BuildRequires: mobile-broadband-provider-info-devel
|
||||
%endif
|
||||
%if %{with nmtui}
|
||||
BuildRequires: newt-devel
|
||||
%endif
|
||||
|
|
|
|||
|
|
@ -1041,7 +1041,7 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_infiniband_mtu (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_infiniband_mtu (NMConnection *self)
|
||||
{
|
||||
NMSettingInfiniband *s_infini = nm_connection_get_setting_infiniband (self);
|
||||
|
||||
|
|
@ -1056,7 +1056,7 @@ _normalize_infiniband_mtu (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_bond_mode (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_bond_mode (NMConnection *self)
|
||||
{
|
||||
NMSettingBond *s_bond = nm_connection_get_setting_bond (self);
|
||||
|
||||
|
|
@ -1077,7 +1077,7 @@ _normalize_bond_mode (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_bond_options (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_bond_options (NMConnection *self)
|
||||
{
|
||||
NMSettingBond *s_bond = nm_connection_get_setting_bond (self);
|
||||
gboolean changed = FALSE;
|
||||
|
|
@ -1107,7 +1107,7 @@ again:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_wireless_mac_address_randomization (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_wireless_mac_address_randomization (NMConnection *self)
|
||||
{
|
||||
NMSettingWireless *s_wifi = nm_connection_get_setting_wireless (self);
|
||||
const char *cloned_mac_address;
|
||||
|
|
@ -1153,7 +1153,7 @@ _normalize_wireless_mac_address_randomization (NMConnection *self, GHashTable *p
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_macsec (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_macsec (NMConnection *self)
|
||||
{
|
||||
NMSettingMacsec *s_macsec = nm_connection_get_setting_macsec (self);
|
||||
gboolean changed = FALSE;
|
||||
|
|
@ -1176,7 +1176,7 @@ _normalize_macsec (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_team_config (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_team_config (NMConnection *self)
|
||||
{
|
||||
NMSettingTeam *s_team = nm_connection_get_setting_team (self);
|
||||
|
||||
|
|
@ -1192,7 +1192,7 @@ _normalize_team_config (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_team_port_config (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_team_port_config (NMConnection *self)
|
||||
{
|
||||
NMSettingTeamPort *s_team_port = nm_connection_get_setting_team_port (self);
|
||||
|
||||
|
|
@ -1208,7 +1208,7 @@ _normalize_team_port_config (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_bluetooth_type (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_bluetooth_type (NMConnection *self)
|
||||
{
|
||||
const char *type = _nm_connection_detect_bluetooth_type (self);
|
||||
|
||||
|
|
@ -1222,7 +1222,7 @@ _normalize_bluetooth_type (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_ovs_interface_type (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_ovs_interface_type (NMConnection *self)
|
||||
{
|
||||
NMSettingOvsInterface *s_ovs_interface = nm_connection_get_setting_ovs_interface (self);
|
||||
gboolean modified;
|
||||
|
|
@ -1243,7 +1243,7 @@ _normalize_ovs_interface_type (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_ip_tunnel_wired_setting (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_ip_tunnel_wired_setting (NMConnection *self)
|
||||
{
|
||||
NMSettingIPTunnel *s_ip_tunnel;
|
||||
|
||||
|
|
@ -1263,7 +1263,7 @@ _normalize_ip_tunnel_wired_setting (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_sriov_vf_order (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_sriov_vf_order (NMConnection *self)
|
||||
{
|
||||
NMSettingSriov *s_sriov;
|
||||
|
||||
|
|
@ -1275,7 +1275,7 @@ _normalize_sriov_vf_order (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_bridge_vlan_order (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_bridge_vlan_order (NMConnection *self)
|
||||
{
|
||||
NMSettingBridge *s_bridge;
|
||||
|
||||
|
|
@ -1287,7 +1287,7 @@ _normalize_bridge_vlan_order (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_bridge_port_vlan_order (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_bridge_port_vlan_order (NMConnection *self)
|
||||
{
|
||||
NMSettingBridgePort *s_port;
|
||||
|
||||
|
|
@ -1299,7 +1299,30 @@ _normalize_bridge_port_vlan_order (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_required_settings (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_gsm_auto_config (NMConnection *self)
|
||||
{
|
||||
NMSettingGsm *s_gsm;
|
||||
|
||||
s_gsm = nm_connection_get_setting_gsm (self);
|
||||
if (!s_gsm)
|
||||
return FALSE;
|
||||
|
||||
if (!nm_setting_gsm_get_auto_config (s_gsm))
|
||||
return FALSE;
|
||||
|
||||
if ( !nm_setting_gsm_get_apn (s_gsm)
|
||||
&& !nm_setting_gsm_get_username (s_gsm)
|
||||
&& !nm_setting_gsm_get_password (s_gsm))
|
||||
return FALSE;
|
||||
|
||||
g_object_set (s_gsm,
|
||||
NM_SETTING_GSM_AUTO_CONFIG, FALSE,
|
||||
NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_required_settings (NMConnection *self)
|
||||
{
|
||||
NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (self);
|
||||
NMSetting *s_bridge;
|
||||
|
|
@ -1323,7 +1346,7 @@ _normalize_required_settings (NMConnection *self, GHashTable *parameters)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_normalize_invalid_slave_port_settings (NMConnection *self, GHashTable *parameters)
|
||||
_normalize_invalid_slave_port_settings (NMConnection *self)
|
||||
{
|
||||
NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
|
||||
const char *slave_type;
|
||||
|
|
@ -1597,23 +1620,24 @@ _connection_normalize (NMConnection *connection,
|
|||
was_modified |= _normalize_connection_uuid (connection);
|
||||
was_modified |= _normalize_connection_type (connection);
|
||||
was_modified |= _normalize_connection_slave_type (connection);
|
||||
was_modified |= _normalize_required_settings (connection, parameters);
|
||||
was_modified |= _normalize_invalid_slave_port_settings (connection, parameters);
|
||||
was_modified |= _normalize_required_settings (connection);
|
||||
was_modified |= _normalize_invalid_slave_port_settings (connection);
|
||||
was_modified |= _normalize_ip_config (connection, parameters);
|
||||
was_modified |= _normalize_ethernet_link_neg (connection);
|
||||
was_modified |= _normalize_infiniband_mtu (connection, parameters);
|
||||
was_modified |= _normalize_bond_mode (connection, parameters);
|
||||
was_modified |= _normalize_bond_options (connection, parameters);
|
||||
was_modified |= _normalize_wireless_mac_address_randomization (connection, parameters);
|
||||
was_modified |= _normalize_macsec (connection, parameters);
|
||||
was_modified |= _normalize_team_config (connection, parameters);
|
||||
was_modified |= _normalize_team_port_config (connection, parameters);
|
||||
was_modified |= _normalize_bluetooth_type (connection, parameters);
|
||||
was_modified |= _normalize_ovs_interface_type (connection, parameters);
|
||||
was_modified |= _normalize_ip_tunnel_wired_setting (connection, parameters);
|
||||
was_modified |= _normalize_sriov_vf_order (connection, parameters);
|
||||
was_modified |= _normalize_bridge_vlan_order (connection, parameters);
|
||||
was_modified |= _normalize_bridge_port_vlan_order (connection, parameters);
|
||||
was_modified |= _normalize_infiniband_mtu (connection);
|
||||
was_modified |= _normalize_bond_mode (connection);
|
||||
was_modified |= _normalize_bond_options (connection);
|
||||
was_modified |= _normalize_wireless_mac_address_randomization (connection);
|
||||
was_modified |= _normalize_macsec (connection);
|
||||
was_modified |= _normalize_team_config (connection);
|
||||
was_modified |= _normalize_team_port_config (connection);
|
||||
was_modified |= _normalize_bluetooth_type (connection);
|
||||
was_modified |= _normalize_ovs_interface_type (connection);
|
||||
was_modified |= _normalize_ip_tunnel_wired_setting (connection);
|
||||
was_modified |= _normalize_sriov_vf_order (connection);
|
||||
was_modified |= _normalize_bridge_vlan_order (connection);
|
||||
was_modified |= _normalize_bridge_port_vlan_order (connection);
|
||||
was_modified |= _normalize_gsm_auto_config (connection);
|
||||
|
||||
was_modified = !!was_modified;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
|
||||
PROP_AUTO_CONFIG,
|
||||
PROP_NUMBER,
|
||||
PROP_USERNAME,
|
||||
PROP_PASSWORD,
|
||||
|
|
@ -40,6 +41,8 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE (
|
|||
);
|
||||
|
||||
typedef struct {
|
||||
gboolean auto_config;
|
||||
|
||||
char *number; /* For dialing, duh */
|
||||
char *username;
|
||||
char *password;
|
||||
|
|
@ -66,6 +69,22 @@ G_DEFINE_TYPE (NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* nm_setting_gsm_get_auto_config:
|
||||
* @setting: the #NMSettingGsm
|
||||
*
|
||||
* Returns: the #NMSettingGsm:auto-config property of the setting
|
||||
*
|
||||
* Since: 1.22
|
||||
**/
|
||||
gboolean
|
||||
nm_setting_gsm_get_auto_config (NMSettingGsm *setting)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_GSM (setting), FALSE);
|
||||
|
||||
return NM_SETTING_GSM_GET_PRIVATE (setting)->auto_config;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_gsm_get_number:
|
||||
* @setting: the #NMSettingGsm
|
||||
|
|
@ -273,10 +292,10 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||
}
|
||||
|
||||
if (priv->apn) {
|
||||
guint32 apn_len = strlen (priv->apn);
|
||||
guint32 i;
|
||||
gsize apn_len = strlen (priv->apn);
|
||||
gsize i;
|
||||
|
||||
if (apn_len < 1 || apn_len > 64) {
|
||||
if (apn_len > 64) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
|
|
@ -320,7 +339,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||
}
|
||||
}
|
||||
|
||||
if (priv->username && !strlen (priv->username)) {
|
||||
if ( priv->username
|
||||
&& priv->username[0] == '\0') {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
|
|
@ -330,8 +350,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||
}
|
||||
|
||||
if (priv->network_id) {
|
||||
guint32 nid_len = strlen (priv->network_id);
|
||||
guint32 i;
|
||||
gsize nid_len = strlen (priv->network_id);
|
||||
gsize i;
|
||||
|
||||
/* Accept both 5 and 6 digit MCC/MNC codes */
|
||||
if ((nid_len < 5) || (nid_len > 6)) {
|
||||
|
|
@ -400,6 +420,16 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||
}
|
||||
}
|
||||
|
||||
if ( priv->auto_config
|
||||
&& (priv->apn || priv->username || priv->password)) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("can't be enabled when manual configuration is present"));
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_AUTO_CONFIG);
|
||||
return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -440,6 +470,9 @@ get_property (GObject *object, guint prop_id,
|
|||
NMSettingGsm *setting = NM_SETTING_GSM (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_AUTO_CONFIG:
|
||||
g_value_set_boolean (value, nm_setting_gsm_get_auto_config (setting));
|
||||
break;
|
||||
case PROP_NUMBER:
|
||||
g_value_set_string (value, nm_setting_gsm_get_number (setting));
|
||||
break;
|
||||
|
|
@ -493,6 +526,9 @@ set_property (GObject *object, guint prop_id,
|
|||
char *tmp;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_AUTO_CONFIG:
|
||||
priv->auto_config = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_NUMBER:
|
||||
g_free (priv->number);
|
||||
priv->number = g_value_dup_string (value);
|
||||
|
|
@ -608,6 +644,21 @@ nm_setting_gsm_class_init (NMSettingGsmClass *klass)
|
|||
setting_class->verify_secrets = verify_secrets;
|
||||
setting_class->need_secrets = need_secrets;
|
||||
|
||||
/**
|
||||
* NMSettingGsm:auto-config:
|
||||
*
|
||||
* When %TRUE, the settings such as APN, username, or password will
|
||||
* default to values that match the network the modem will register
|
||||
* to in the Mobile Broadband Provider database.
|
||||
*
|
||||
* Since: 1.22
|
||||
**/
|
||||
obj_properties[PROP_AUTO_CONFIG] =
|
||||
g_param_spec_boolean (NM_SETTING_GSM_AUTO_CONFIG, "", "",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* NMSettingGsm:number:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ G_BEGIN_DECLS
|
|||
|
||||
#define NM_SETTING_GSM_SETTING_NAME "gsm"
|
||||
|
||||
#define NM_SETTING_GSM_AUTO_CONFIG "auto-config"
|
||||
#define NM_SETTING_GSM_USERNAME "username"
|
||||
#define NM_SETTING_GSM_PASSWORD "password"
|
||||
#define NM_SETTING_GSM_PASSWORD_FLAGS "password-flags"
|
||||
|
|
@ -59,6 +60,10 @@ typedef struct {
|
|||
GType nm_setting_gsm_get_type (void);
|
||||
|
||||
NMSetting *nm_setting_gsm_new (void);
|
||||
|
||||
NM_AVAILABLE_IN_1_22
|
||||
gboolean nm_setting_gsm_get_auto_config (NMSettingGsm *setting);
|
||||
|
||||
const char *nm_setting_gsm_get_username (NMSettingGsm *setting);
|
||||
const char *nm_setting_gsm_get_password (NMSettingGsm *setting);
|
||||
const char *nm_setting_gsm_get_apn (NMSettingGsm *setting);
|
||||
|
|
|
|||
|
|
@ -1747,7 +1747,7 @@ test_setting_gsm_apn_bad_chars (void)
|
|||
|
||||
/* 0 characters long */
|
||||
g_object_set (s_gsm, NM_SETTING_GSM_APN, "", NULL);
|
||||
g_assert (!nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
|
||||
g_assert (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
|
||||
|
||||
/* 65-character long */
|
||||
g_object_set (s_gsm, NM_SETTING_GSM_APN, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl1", NULL);
|
||||
|
|
|
|||
|
|
@ -1628,3 +1628,8 @@ global:
|
|||
nm_setting_wireguard_get_ip6_auto_default_route;
|
||||
nm_settings_add_connection2_flags_get_type;
|
||||
} libnm_1_18_0;
|
||||
|
||||
libnm_1_22_0 {
|
||||
global:
|
||||
nm_setting_gsm_get_auto_config;
|
||||
} libnm_1_20_0;
|
||||
|
|
|
|||
|
|
@ -502,6 +502,9 @@ config_h.set10('WITH_PPP', enable_ppp)
|
|||
enable_modem_manager = get_option('modem_manager')
|
||||
if enable_modem_manager
|
||||
mm_glib_dep = dependency('mm-glib', version: '>= 0.7.991')
|
||||
|
||||
service_provider_db = dependency('mobile-broadband-provider-info').get_pkgconfig_variable('database')
|
||||
config_h.set_quoted('MOBILE_BROADBAND_PROVIDER_INFO_DATABASE', service_provider_db)
|
||||
endif
|
||||
|
||||
# Bluez5 DUN support
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ sources = files(
|
|||
'nm-modem-broadband.c',
|
||||
'nm-modem.c',
|
||||
'nm-modem-manager.c',
|
||||
'nm-service-providers.c',
|
||||
)
|
||||
|
||||
deps = [
|
||||
|
|
@ -28,8 +29,10 @@ libnm_wwan = shared_module(
|
|||
install_dir: nm_plugindir,
|
||||
)
|
||||
|
||||
wwan_inc = include_directories('.')
|
||||
|
||||
libnm_wwan_dep = declare_dependency(
|
||||
include_directories: include_directories('.'),
|
||||
include_directories: wwan_inc,
|
||||
link_with: libnm_wwan,
|
||||
)
|
||||
|
||||
|
|
@ -74,3 +77,7 @@ check-local-devices-wwan: src/devices/wwan/libnm-device-plugin-wwan.la src/devic
|
|||
$(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wwan/.libs/libnm-wwan.so "$(srcdir)/src/devices/wwan/libnm-wwan.ver"
|
||||
$(call check_so_symbols,$(builddir)/src/devices/wwan/.libs/libnm-wwan.so)
|
||||
'''
|
||||
|
||||
if enable_tests
|
||||
subdir('tests')
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "nm-default.h"
|
||||
|
||||
#include "nm-modem-broadband.h"
|
||||
#include "nm-service-providers.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <libmm-glib.h>
|
||||
|
|
@ -261,7 +262,10 @@ create_cdma_connect_properties (NMConnection *connection)
|
|||
}
|
||||
|
||||
static MMSimpleConnectProperties *
|
||||
create_gsm_connect_properties (NMConnection *connection)
|
||||
create_gsm_connect_properties (NMConnection *connection,
|
||||
const char *apn,
|
||||
const char *username,
|
||||
const char *password)
|
||||
{
|
||||
NMSettingGsm *setting;
|
||||
NMSettingPpp *s_ppp;
|
||||
|
|
@ -269,11 +273,14 @@ create_gsm_connect_properties (NMConnection *connection)
|
|||
const char *str;
|
||||
|
||||
setting = nm_connection_get_setting_gsm (connection);
|
||||
|
||||
properties = mm_simple_connect_properties_new ();
|
||||
|
||||
/* Blank APN ("") means the default subscription APN */
|
||||
str = nm_setting_gsm_get_apn (setting);
|
||||
mm_simple_connect_properties_set_apn (properties, str ?: "");
|
||||
mm_simple_connect_properties_set_apn (properties, apn ?: "");
|
||||
if (username)
|
||||
mm_simple_connect_properties_set_user (properties, username);
|
||||
if (password)
|
||||
mm_simple_connect_properties_set_password (properties, password);
|
||||
|
||||
str = nm_setting_gsm_get_network_id (setting);
|
||||
if (str)
|
||||
|
|
@ -283,14 +290,6 @@ create_gsm_connect_properties (NMConnection *connection)
|
|||
if (str)
|
||||
mm_simple_connect_properties_set_pin (properties, str);
|
||||
|
||||
str = nm_setting_gsm_get_username (setting);
|
||||
if (str)
|
||||
mm_simple_connect_properties_set_user (properties, str);
|
||||
|
||||
str = nm_setting_gsm_get_password (setting);
|
||||
if (str)
|
||||
mm_simple_connect_properties_set_password (properties, str);
|
||||
|
||||
/* Roaming */
|
||||
if (nm_setting_gsm_get_home_only (setting))
|
||||
mm_simple_connect_properties_set_allow_roaming (properties, FALSE);
|
||||
|
|
@ -443,6 +442,95 @@ send_pin_ready (MMSim *sim, GAsyncResult *result, NMModemBroadband *self)
|
|||
connect_context_step (self);
|
||||
}
|
||||
|
||||
static void
|
||||
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,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMModemBroadband *self = user_data;
|
||||
NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE (self);
|
||||
ConnectContext *ctx = priv->ctx;
|
||||
|
||||
if (error) {
|
||||
_LOGW ("failed to connect '%s': APN not found: %s",
|
||||
nm_connection_get_id (ctx->connection), error->message);
|
||||
|
||||
nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_GSM_APN_FAILED);
|
||||
connect_context_clear (self);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Blank APN ("") means the default subscription APN */
|
||||
ctx->connect_properties = create_gsm_connect_properties (ctx->connection,
|
||||
apn,
|
||||
username,
|
||||
password);
|
||||
g_return_if_fail (ctx->connect_properties);
|
||||
connect_context_step (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
try_create_connect_properties (NMModemBroadband *self)
|
||||
{
|
||||
NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE (self);
|
||||
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;
|
||||
|
||||
s_gsm = nm_connection_get_setting_gsm (ctx->connection);
|
||||
if (s_gsm)
|
||||
network_id = nm_setting_gsm_get_network_id (s_gsm);
|
||||
if (!network_id) {
|
||||
if (mm_modem_get_state (self->_priv.modem_iface) < MM_MODEM_STATE_REGISTERED)
|
||||
return FALSE;
|
||||
modem_3gpp = mm_object_get_modem_3gpp (priv->modem_object);
|
||||
network_id = mm_modem_3gpp_get_operator_code (modem_3gpp);
|
||||
}
|
||||
if (!network_id) {
|
||||
_LOGW ("failed to connect '%s': unable to determine the network id",
|
||||
nm_connection_get_id (ctx->connection));
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_service_providers_find_gsm_apn (MOBILE_BROADBAND_PROVIDER_INFO_DATABASE,
|
||||
network_id,
|
||||
ctx->cancellable,
|
||||
find_gsm_apn_cb,
|
||||
self);
|
||||
} else {
|
||||
ctx->connect_properties = create_gsm_connect_properties (ctx->connection,
|
||||
nm_setting_gsm_get_apn (s_gsm),
|
||||
nm_setting_gsm_get_username (s_gsm),
|
||||
nm_setting_gsm_get_password (s_gsm));
|
||||
g_return_val_if_fail (ctx->connect_properties, TRUE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
} else if (MODEM_CAPS_3GPP2 (ctx->caps)) {
|
||||
ctx->connect_properties = create_cdma_connect_properties (ctx->connection);
|
||||
g_return_val_if_fail (ctx->connect_properties, FALSE);
|
||||
return TRUE;
|
||||
} else {
|
||||
_LOGW ("failed to connect '%s': not a mobile broadband modem",
|
||||
nm_connection_get_id (ctx->connection));
|
||||
}
|
||||
|
||||
out:
|
||||
nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED);
|
||||
connect_context_clear (self);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
connect_context_step (NMModemBroadband *self)
|
||||
{
|
||||
|
|
@ -487,22 +575,8 @@ connect_context_step (NMModemBroadband *self)
|
|||
if (mm_modem_get_state (self->_priv.modem_iface) <= MM_MODEM_STATE_LOCKED)
|
||||
break;
|
||||
|
||||
/* Create core connect properties based on the modem capabilities */
|
||||
g_assert (!ctx->connect_properties);
|
||||
|
||||
if (MODEM_CAPS_3GPP (ctx->caps))
|
||||
ctx->connect_properties = create_gsm_connect_properties (ctx->connection);
|
||||
else if (MODEM_CAPS_3GPP2 (ctx->caps))
|
||||
ctx->connect_properties = create_cdma_connect_properties (ctx->connection);
|
||||
else {
|
||||
_LOGW ("failed to connect '%s': not a mobile broadband modem",
|
||||
nm_connection_get_id (ctx->connection));
|
||||
|
||||
nm_modem_emit_prepare_result (NM_MODEM (self), FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED);
|
||||
connect_context_clear (self);
|
||||
if (!try_create_connect_properties (self))
|
||||
break;
|
||||
}
|
||||
g_assert (ctx->connect_properties);
|
||||
|
||||
/* Build up list of IP types that we need to use in the retries */
|
||||
ctx->ip_types = nm_modem_get_connection_ip_type (NM_MODEM (self), ctx->connection, &error);
|
||||
|
|
@ -521,6 +595,9 @@ connect_context_step (NMModemBroadband *self)
|
|||
}
|
||||
/* fall through */
|
||||
case CONNECT_STEP_CONNECT:
|
||||
if (!ctx->connect_properties)
|
||||
break;
|
||||
|
||||
if (ctx->ip_types_i < ctx->ip_types->len) {
|
||||
NMModemIPType current;
|
||||
|
||||
|
|
@ -533,7 +610,7 @@ connect_context_step (NMModemBroadband *self)
|
|||
else if (current == NM_MODEM_IP_TYPE_IPV4V6)
|
||||
mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV4V6);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
g_return_if_reached ();
|
||||
|
||||
_nm_modem_set_apn (NM_MODEM (self), mm_simple_connect_properties_get_apn (ctx->connect_properties));
|
||||
|
||||
|
|
@ -676,6 +753,9 @@ complete_connection (NMModem *modem,
|
|||
if (!s_gsm) {
|
||||
s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_gsm));
|
||||
g_object_set (G_OBJECT (s_gsm),
|
||||
NM_SETTING_GSM_AUTO_CONFIG, TRUE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (!nm_setting_gsm_get_device_id (s_gsm)) {
|
||||
|
|
@ -863,8 +943,8 @@ static_stage3_ip4_done (NMModemBroadband *self)
|
|||
guint32 ip4_route_table, ip4_route_metric;
|
||||
NMPlatformIP4Route *r;
|
||||
|
||||
g_assert (self->_priv.ipv4_config);
|
||||
g_assert (self->_priv.bearer);
|
||||
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;
|
||||
|
||||
|
|
@ -895,7 +975,7 @@ static_stage3_ip4_done (NMModemBroadband *self)
|
|||
}
|
||||
|
||||
data_port = mm_bearer_get_interface (self->_priv.bearer);
|
||||
g_assert (data_port);
|
||||
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));
|
||||
|
||||
|
|
@ -970,7 +1050,7 @@ stage3_ip6_done (NMModemBroadband *self)
|
|||
const char **dns;
|
||||
guint i;
|
||||
|
||||
g_assert (self->_priv.ipv6_config);
|
||||
g_return_val_if_fail (self->_priv.ipv6_config, FALSE);
|
||||
|
||||
self->_priv.idle_id_ip6 = 0;
|
||||
memset (&address, 0, sizeof (address));
|
||||
|
|
@ -1002,7 +1082,8 @@ stage3_ip6_done (NMModemBroadband *self)
|
|||
_LOGI ("IPv6 base configuration:");
|
||||
|
||||
data_port = mm_bearer_get_interface (self->_priv.bearer);
|
||||
g_assert (data_port);
|
||||
g_return_val_if_fail (data_port, FALSE);
|
||||
|
||||
config = nm_ip6_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET),
|
||||
nm_platform_link_get_ifindex (NM_PLATFORM_GET, data_port));
|
||||
|
||||
|
|
@ -1370,8 +1451,9 @@ set_property (GObject *object,
|
|||
/* construct-only */
|
||||
self->_priv.modem_object = g_value_dup_object (value);
|
||||
self->_priv.modem_iface = mm_object_get_modem (self->_priv.modem_object);
|
||||
g_return_if_fail (self->_priv.modem_iface);
|
||||
self->_priv.modem_3gpp_iface = mm_object_get_modem_3gpp (self->_priv.modem_object);
|
||||
g_assert (self->_priv.modem_iface != NULL);
|
||||
|
||||
g_signal_connect (self->_priv.modem_iface,
|
||||
"state-changed",
|
||||
G_CALLBACK (modem_state_changed),
|
||||
|
|
|
|||
460
src/devices/wwan/nm-service-providers.c
Normal file
460
src/devices/wwan/nm-service-providers.c
Normal file
|
|
@ -0,0 +1,460 @@
|
|||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
/*
|
||||
* Copyright (C) 2009 Novell, Inc.
|
||||
* Author: Tambet Ingo (tambet@gmail.com).
|
||||
*
|
||||
* Copyright (C) 2009 - 2019 Red Hat, Inc.
|
||||
* Copyright (C) 2012 Lanedo GmbH
|
||||
*/
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-service-providers.h"
|
||||
|
||||
typedef enum {
|
||||
PARSER_TOPLEVEL = 0,
|
||||
PARSER_COUNTRY,
|
||||
PARSER_PROVIDER,
|
||||
PARSER_METHOD_GSM,
|
||||
PARSER_METHOD_GSM_APN,
|
||||
PARSER_METHOD_CDMA,
|
||||
PARSER_DONE,
|
||||
PARSER_ERROR
|
||||
} ParseContextState;
|
||||
|
||||
typedef struct {
|
||||
char *mccmnc;
|
||||
NMServiceProvidersGsmApnCallback callback;
|
||||
gpointer user_data;
|
||||
GCancellable *cancellable;
|
||||
GMarkupParseContext *ctx;
|
||||
char buffer[4096];
|
||||
|
||||
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;
|
||||
} ParseContext;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
parser_toplevel_start (ParseContext *parse_context,
|
||||
const char *name,
|
||||
const char **attribute_names,
|
||||
const char **attribute_values)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (strcmp (name, "serviceproviders") == 0) {
|
||||
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
||||
if (strcmp (attribute_names[i], "format") == 0) {
|
||||
if (strcmp (attribute_values[i], "2.0")) {
|
||||
g_warning ("%s: mobile broadband provider database format '%s'"
|
||||
" not supported.", __func__, attribute_values[i]);
|
||||
parse_context->state = PARSER_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (strcmp (name, "country") == 0) {
|
||||
parse_context->state = PARSER_COUNTRY;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parser_country_start (ParseContext *parse_context,
|
||||
const char *name,
|
||||
const char **attribute_names,
|
||||
const char **attribute_values)
|
||||
{
|
||||
if (strcmp (name, "provider") == 0)
|
||||
parse_context->state = PARSER_PROVIDER;
|
||||
}
|
||||
|
||||
static void
|
||||
parser_provider_start (ParseContext *parse_context,
|
||||
const char *name,
|
||||
const char **attribute_names,
|
||||
const char **attribute_values)
|
||||
{
|
||||
parse_context->mccmnc_matched = FALSE;
|
||||
if (strcmp (name, "gsm") == 0)
|
||||
parse_context->state = PARSER_METHOD_GSM;
|
||||
else if (strcmp (name, "cdma") == 0)
|
||||
parse_context->state = PARSER_METHOD_CDMA;
|
||||
}
|
||||
|
||||
static void
|
||||
parser_gsm_start (ParseContext *parse_context,
|
||||
const char *name,
|
||||
const char **attribute_names,
|
||||
const char **attribute_values)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (strcmp (name, "network-id") == 0) {
|
||||
const char *mcc = NULL, *mnc = NULL;
|
||||
|
||||
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
||||
if (strcmp (attribute_names[i], "mcc") == 0)
|
||||
mcc = attribute_values[i];
|
||||
else if (strcmp (attribute_names[i], "mnc") == 0)
|
||||
mnc = attribute_values[i];
|
||||
if (mcc && strlen (mcc) && mnc && strlen (mnc)) {
|
||||
char *mccmnc = g_strdup_printf ("%s%s", mcc, mnc);
|
||||
|
||||
if (strcmp (mccmnc, parse_context->mccmnc) == 0)
|
||||
parse_context->mccmnc_matched = TRUE;
|
||||
g_free (mccmnc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (strcmp (name, "apn") == 0) {
|
||||
parse_context->found_internet_apn = FALSE;
|
||||
g_clear_pointer (&parse_context->apn, g_free);
|
||||
g_clear_pointer (&parse_context->username, g_free);
|
||||
g_clear_pointer (&parse_context->password, g_free);
|
||||
g_clear_pointer (&parse_context->gateway, g_free);
|
||||
g_clear_pointer (&parse_context->auth_method, g_free);
|
||||
g_slist_free_full (parse_context->dns, g_free);
|
||||
parse_context->dns = NULL;
|
||||
|
||||
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
||||
if (strcmp (attribute_names[i], "value") == 0) {
|
||||
parse_context->state = PARSER_METHOD_GSM_APN;
|
||||
parse_context->apn = g_strstrip (g_strdup (attribute_values[i]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parser_gsm_apn_start (ParseContext *parse_context,
|
||||
const char *name,
|
||||
const char **attribute_names,
|
||||
const char **attribute_values)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (strcmp (name, "usage") == 0) {
|
||||
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
||||
if ( (strcmp (attribute_names[i], "type") == 0)
|
||||
&& (strcmp (attribute_values[i], "internet") == 0)) {
|
||||
parse_context->found_internet_apn = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (strcmp (name, "authentication") == 0) {
|
||||
for (i = 0; attribute_names && attribute_names[i]; i++) {
|
||||
if (strcmp (attribute_names[i], "method") == 0) {
|
||||
g_clear_pointer (&parse_context->auth_method, g_free);
|
||||
parse_context->auth_method = g_strstrip (g_strdup (attribute_values[i]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parser_start_element (GMarkupParseContext *context,
|
||||
const char *element_name,
|
||||
const char **attribute_names,
|
||||
const char **attribute_values,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
ParseContext *parse_context = user_data;
|
||||
|
||||
g_clear_pointer (&parse_context->text_buffer, g_free);
|
||||
|
||||
switch (parse_context->state) {
|
||||
case PARSER_TOPLEVEL:
|
||||
parser_toplevel_start (parse_context, element_name, attribute_names, attribute_values);
|
||||
break;
|
||||
case PARSER_COUNTRY:
|
||||
parser_country_start (parse_context, element_name, attribute_names, attribute_values);
|
||||
break;
|
||||
case PARSER_PROVIDER:
|
||||
parser_provider_start (parse_context, element_name, attribute_names, attribute_values);
|
||||
break;
|
||||
case PARSER_METHOD_GSM:
|
||||
parser_gsm_start (parse_context, element_name, attribute_names, attribute_values);
|
||||
break;
|
||||
case PARSER_METHOD_GSM_APN:
|
||||
parser_gsm_apn_start (parse_context, element_name, attribute_names, attribute_values);
|
||||
break;
|
||||
case PARSER_METHOD_CDMA:
|
||||
break;
|
||||
case PARSER_ERROR:
|
||||
break;
|
||||
case PARSER_DONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parser_country_end (ParseContext *parse_context,
|
||||
const char *name)
|
||||
{
|
||||
if (strcmp (name, "country") == 0) {
|
||||
g_clear_pointer (&parse_context->text_buffer, g_free);
|
||||
parse_context->state = PARSER_TOPLEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parser_provider_end (ParseContext *parse_context,
|
||||
const char *name)
|
||||
{
|
||||
if (strcmp (name, "provider") == 0) {
|
||||
g_clear_pointer (&parse_context->text_buffer, g_free);
|
||||
parse_context->state = PARSER_COUNTRY;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parser_gsm_end (ParseContext *parse_context,
|
||||
const char *name)
|
||||
{
|
||||
if (strcmp (name, "gsm") == 0) {
|
||||
g_clear_pointer (&parse_context->text_buffer, g_free);
|
||||
parse_context->state = PARSER_PROVIDER;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parser_gsm_apn_end (ParseContext *parse_context,
|
||||
const char *name)
|
||||
{
|
||||
if (strcmp (name, "username") == 0) {
|
||||
g_clear_pointer (&parse_context->username, g_free);
|
||||
parse_context->username = g_steal_pointer (&parse_context->text_buffer);
|
||||
} else if (strcmp (name, "password") == 0) {
|
||||
g_clear_pointer (&parse_context->password, g_free);
|
||||
parse_context->password = g_steal_pointer (&parse_context->text_buffer);
|
||||
} else if (strcmp (name, "dns") == 0) {
|
||||
parse_context->dns = g_slist_prepend (parse_context->dns,
|
||||
g_steal_pointer (&parse_context->text_buffer));
|
||||
} else if (strcmp (name, "gateway") == 0) {
|
||||
g_clear_pointer (&parse_context->gateway, g_free);
|
||||
parse_context->gateway = g_steal_pointer (&parse_context->text_buffer);
|
||||
} else if (strcmp (name, "apn") == 0) {
|
||||
g_clear_pointer (&parse_context->text_buffer, g_free);
|
||||
|
||||
if (parse_context->mccmnc_matched && parse_context->found_internet_apn)
|
||||
parse_context->state = PARSER_DONE;
|
||||
else
|
||||
parse_context->state = PARSER_METHOD_GSM;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parser_cdma_end (ParseContext *parse_context,
|
||||
const char *name)
|
||||
{
|
||||
if (strcmp (name, "cdma") == 0) {
|
||||
g_clear_pointer (&parse_context->text_buffer, g_free);
|
||||
parse_context->state = PARSER_PROVIDER;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parser_end_element (GMarkupParseContext *context,
|
||||
const char *element_name,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
ParseContext *parse_context = user_data;
|
||||
|
||||
switch (parse_context->state) {
|
||||
case PARSER_TOPLEVEL:
|
||||
break;
|
||||
case PARSER_COUNTRY:
|
||||
parser_country_end (parse_context, element_name);
|
||||
break;
|
||||
case PARSER_PROVIDER:
|
||||
parser_provider_end (parse_context, element_name);
|
||||
break;
|
||||
case PARSER_METHOD_GSM:
|
||||
parser_gsm_end (parse_context, element_name);
|
||||
break;
|
||||
case PARSER_METHOD_GSM_APN:
|
||||
parser_gsm_apn_end (parse_context, element_name);
|
||||
break;
|
||||
case PARSER_METHOD_CDMA:
|
||||
parser_cdma_end (parse_context, element_name);
|
||||
break;
|
||||
case PARSER_ERROR:
|
||||
break;
|
||||
case PARSER_DONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parser_text (GMarkupParseContext *context,
|
||||
const char *text,
|
||||
gsize text_len,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
ParseContext *parse_context = user_data;
|
||||
|
||||
g_free (parse_context->text_buffer);
|
||||
parse_context->text_buffer = g_strdup (text);
|
||||
}
|
||||
|
||||
static const GMarkupParser parser = {
|
||||
.start_element = parser_start_element,
|
||||
.end_element = parser_end_element,
|
||||
.text = parser_text,
|
||||
.passthrough = NULL,
|
||||
.error = NULL,
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
finish_parse_context (ParseContext *parse_context, GError *error)
|
||||
{
|
||||
if (parse_context->callback) {
|
||||
if (error) {
|
||||
parse_context->callback (NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, error,
|
||||
parse_context->user_data);
|
||||
} else {
|
||||
parse_context->callback (parse_context->apn,
|
||||
parse_context->username,
|
||||
parse_context->password,
|
||||
parse_context->gateway,
|
||||
parse_context->auth_method,
|
||||
parse_context->dns,
|
||||
error,
|
||||
parse_context->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (parse_context->mccmnc);
|
||||
g_markup_parse_context_free (parse_context->ctx);
|
||||
|
||||
g_free (parse_context->text_buffer);
|
||||
g_free (parse_context->apn);
|
||||
g_free (parse_context->username);
|
||||
g_free (parse_context->password);
|
||||
g_free (parse_context->gateway);
|
||||
g_free (parse_context->auth_method);
|
||||
g_slist_free_full (parse_context->dns, g_free);
|
||||
|
||||
g_slice_free (ParseContext, parse_context);
|
||||
}
|
||||
|
||||
static void
|
||||
read_next_chunk (GInputStream *stream, ParseContext *parse_context);
|
||||
|
||||
static void
|
||||
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;
|
||||
|
||||
len = g_input_stream_read_finish (stream, res, &error);
|
||||
if (len == -1) {
|
||||
g_prefix_error (&error, "Error reading service provider database: ");
|
||||
finish_parse_context (parse_context, error);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
g_set_error (&error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Operator ID '%s' not found in service provider database",
|
||||
parse_context->mccmnc);
|
||||
finish_parse_context (parse_context, error);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_markup_parse_context_parse (parse_context->ctx, parse_context->buffer, len, &error)) {
|
||||
g_prefix_error (&error, "Error parsing service provider database: ");
|
||||
finish_parse_context (parse_context, error);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (parse_context->state == PARSER_DONE) {
|
||||
finish_parse_context (parse_context, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
read_next_chunk (stream, parse_context);
|
||||
}
|
||||
|
||||
static void
|
||||
read_next_chunk (GInputStream *stream, ParseContext *parse_context)
|
||||
{
|
||||
g_input_stream_read_async (stream,
|
||||
parse_context->buffer,
|
||||
sizeof (parse_context->buffer),
|
||||
G_PRIORITY_DEFAULT,
|
||||
parse_context->cancellable,
|
||||
stream_read_cb,
|
||||
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;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
stream = g_file_read_finish (file, res, &error);
|
||||
if (!stream) {
|
||||
g_prefix_error (&error, "Error opening service provider database: ");
|
||||
finish_parse_context (parse_context, error);
|
||||
return;
|
||||
}
|
||||
|
||||
read_next_chunk (G_INPUT_STREAM (stream), parse_context);
|
||||
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
nm_service_providers_find_gsm_apn (const char *service_providers,
|
||||
const char *mccmnc,
|
||||
GCancellable *cancellable,
|
||||
NMServiceProvidersGsmApnCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GFile *file;
|
||||
ParseContext *parse_context;
|
||||
|
||||
parse_context = g_slice_new0 (ParseContext);
|
||||
parse_context->mccmnc = g_strdup (mccmnc);
|
||||
parse_context->cancellable = cancellable;
|
||||
parse_context->callback = callback;
|
||||
parse_context->user_data = user_data;
|
||||
parse_context->ctx = g_markup_parse_context_new (&parser, 0, parse_context, NULL);
|
||||
|
||||
file = g_file_new_for_path (service_providers);
|
||||
|
||||
g_file_read_async (file, G_PRIORITY_DEFAULT, cancellable, file_read_cb, parse_context);
|
||||
|
||||
g_object_unref (file);
|
||||
}
|
||||
24
src/devices/wwan/nm-service-providers.h
Normal file
24
src/devices/wwan/nm-service-providers.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
/*
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#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,
|
||||
const GSList *dns,
|
||||
GError *error,
|
||||
gpointer user_data);
|
||||
|
||||
void nm_service_providers_find_gsm_apn (const char *service_providers,
|
||||
const char *mccmnc,
|
||||
GCancellable *cancellable,
|
||||
NMServiceProvidersGsmApnCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
#endif /* __NETWORKMANAGER_SERVICE_PROVIDERS_H__ */
|
||||
13
src/devices/wwan/tests/meson.build
Normal file
13
src/devices/wwan/tests/meson.build
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
exe = executable(
|
||||
'test-service-providers',
|
||||
sources: files('test-service-providers.c',
|
||||
'../nm-service-providers.c'),
|
||||
dependencies: test_nm_dep,
|
||||
include_directories: wwan_inc,
|
||||
)
|
||||
test(
|
||||
'wwan/test-service-providers',
|
||||
test_script,
|
||||
timeout: default_test_timeout,
|
||||
args: test_args + [exe.full_path()],
|
||||
)
|
||||
124
src/devices/wwan/tests/test-service-providers.c
Normal file
124
src/devices/wwan/tests/test-service-providers.c
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
/*
|
||||
* Copyright (C) 2019 Red Hat
|
||||
*/
|
||||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-service-providers.h"
|
||||
|
||||
#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,
|
||||
const GSList *dns,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
GMainLoop *loop = user_data;
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
g_assert_no_error (error);
|
||||
g_assert_cmpstr (apn, ==, "gprs.example.com");
|
||||
g_assert_cmpstr (username, ==, "praise");
|
||||
g_assert_cmpstr (password, ==, "santa");
|
||||
g_assert_cmpstr (gateway, ==, "192.0.2.3");
|
||||
g_assert_cmpstr (auth_method, ==, "pap");
|
||||
|
||||
g_assert_nonnull (dns);
|
||||
g_assert_cmpstr (dns->data, ==, "192.0.2.2");
|
||||
dns = dns->next;
|
||||
g_assert_nonnull (dns);
|
||||
g_assert_cmpstr (dns->data, ==, "192.0.2.1");
|
||||
g_assert_null (dns->next);
|
||||
}
|
||||
|
||||
static void
|
||||
test_positive (void)
|
||||
{
|
||||
GMainLoop *loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
nm_service_providers_find_gsm_apn (NM_BUILD_SRCDIR"/src/devices/wwan/tests/test-service-providers.xml",
|
||||
"13337", NULL, test_positive_cb, loop);
|
||||
g_main_loop_run (loop);
|
||||
g_main_loop_unref (loop);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_negative_cb (const char *apn,
|
||||
const char *username,
|
||||
const char *password,
|
||||
const char *gateway,
|
||||
const char *auth_method,
|
||||
const GSList *dns,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
GMainLoop *loop = user_data;
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
g_assert_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN);
|
||||
}
|
||||
|
||||
static void
|
||||
test_negative (void)
|
||||
{
|
||||
GMainLoop *loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
nm_service_providers_find_gsm_apn (NM_BUILD_SRCDIR"/src/devices/wwan/tests/test-service-providers.xml",
|
||||
"78130", NULL, test_negative_cb, loop);
|
||||
g_main_loop_run (loop);
|
||||
g_main_loop_unref (loop);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_nonexistent_cb (const char *apn,
|
||||
const char *username,
|
||||
const char *password,
|
||||
const char *gateway,
|
||||
const char *auth_method,
|
||||
const GSList *dns,
|
||||
GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
GMainLoop *loop = user_data;
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_AGAIN);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nonexistent (void)
|
||||
{
|
||||
GMainLoop *loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
nm_service_providers_find_gsm_apn ("nonexistent.xml", "13337", NULL,
|
||||
test_nonexistent_cb, loop);
|
||||
g_main_loop_run (loop);
|
||||
g_main_loop_unref (loop);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
|
||||
|
||||
g_test_add_func ("/service-providers/positive", test_positive);
|
||||
g_test_add_func ("/service-providers/negative", test_negative);
|
||||
g_test_add_func ("/service-providers/nonexistent", test_nonexistent);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
73
src/devices/wwan/tests/test-service-providers.xml
Normal file
73
src/devices/wwan/tests/test-service-providers.xml
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding='utf-8'?>
|
||||
<!DOCTYPE serviceproviders SYSTEM "serviceproviders.2.dtd">
|
||||
|
||||
<serviceproviders format="2.0">
|
||||
|
||||
<country code="feh">
|
||||
<provider>
|
||||
<name>Sophia</name>
|
||||
<gsm>
|
||||
<network-id mcc="666" mnc="999"/>
|
||||
<apn value="access.example.com">
|
||||
<plan type="postpaid"/>
|
||||
<usage type="internet"/>
|
||||
<name>APN</name>
|
||||
<dns>192.0.2.1</dns>
|
||||
<dns>192.0.2.2</dns>
|
||||
</apn>
|
||||
</gsm>
|
||||
</provider>
|
||||
</country>
|
||||
|
||||
<country code="meh">
|
||||
<provider>
|
||||
<name>Demiurge</name>
|
||||
<gsm>
|
||||
<network-id mcc="133" mnc="37"/>
|
||||
<network-id mcc="133" mnc="666"/>
|
||||
<apn value="mms">
|
||||
<usage type="mms"/>
|
||||
<name>Unsolicited Nudes MMS</name>
|
||||
<username>mms</username>
|
||||
<password>mms</password>
|
||||
<mmsc>http://mms.example.com/</mmsc>
|
||||
<mmsproxy>192.0.2.1:8080</mmsproxy>
|
||||
</apn>
|
||||
<apn value="gprs.example.com">
|
||||
<plan type="postpaid"/>
|
||||
<usage type="internet"/>
|
||||
<name>GPRS</name>
|
||||
<username>praise</username>
|
||||
<password>santa</password>
|
||||
<dns>192.0.2.1</dns>
|
||||
<dns>192.0.2.2</dns>
|
||||
<gateway>192.0.2.3</gateway>
|
||||
<authentication method="pap"/>
|
||||
</apn>
|
||||
<apn value="second.example.com">
|
||||
<plan type="postpaid"/>
|
||||
<usage type="internet"/>
|
||||
<name>Second</name>
|
||||
<username>worship</username>
|
||||
<password>doom</password>
|
||||
</apn>
|
||||
</gsm>
|
||||
</provider>
|
||||
|
||||
<provider>
|
||||
<name>Personal</name>
|
||||
<gsm>
|
||||
<network-id mcc="666" mnc="999"/>
|
||||
<apn value="access.example.com">
|
||||
<plan type="postpaid"/>
|
||||
<usage type="internet"/>
|
||||
<name>APN</name>
|
||||
<dns>192.0.2.1</dns>
|
||||
<dns>192.0.2.2</dns>
|
||||
</apn>
|
||||
</gsm>
|
||||
</provider>
|
||||
</country>
|
||||
|
||||
</serviceproviders>
|
||||
|
||||
Loading…
Add table
Reference in a new issue