summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mm-bearer-qmi.c131
1 files changed, 105 insertions, 26 deletions
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c
index 4c693d24c..6543c9282 100644
--- a/src/mm-bearer-qmi.c
+++ b/src/mm-bearer-qmi.c
@@ -28,6 +28,7 @@
#include "mm-iface-modem.h"
#include "mm-bearer-qmi.h"
+#include "mm-modem-helpers.h"
#include "mm-modem-helpers-qmi.h"
#include "mm-port-enums-types.h"
#include "mm-log.h"
@@ -83,12 +84,14 @@ typedef struct {
QmiClientWds *client_ipv4;
guint32 packet_data_handle_ipv4;
GError *error_ipv4;
+ MMBearerIpConfig *ipv4_config;
gboolean ipv6;
gboolean running_ipv6;
QmiClientWds *client_ipv6;
guint32 packet_data_handle_ipv6;
GError *error_ipv6;
+ MMBearerIpConfig *ipv6_config;
} ConnectContext;
static void
@@ -99,6 +102,10 @@ connect_context_complete_and_free (ConnectContext *ctx)
g_free (ctx->apn);
g_free (ctx->user);
g_free (ctx->password);
+ if (ctx->ipv4_config)
+ g_object_unref (ctx->ipv4_config);
+ if (ctx->ipv6_config)
+ g_object_unref (ctx->ipv6_config);
if (ctx->error_ipv4)
g_error_free (ctx->error_ipv4);
if (ctx->error_ipv6)
@@ -247,14 +254,18 @@ build_start_network_input (ConnectContext *ctx)
}
static void
-print_address4 (gboolean success, const char *tag, guint32 address, GError *error)
+print_address4 (gboolean success,
+ gchar *buf,
+ gsize buf_len,
+ const gchar *tag,
+ guint32 address,
+ GError *error)
{
struct in_addr a = { .s_addr = GUINT32_TO_BE (address) };
- char buf[INET_ADDRSTRLEN + 1];
if (success) {
- memset (buf, 0, sizeof (buf));
- if (inet_ntop (AF_INET, &a, buf, sizeof (buf) - 1))
+ memset (buf, 0, buf_len);
+ if (inet_ntop (AF_INET, &a, buf, buf_len - 1))
mm_dbg (" %s: %s", tag, buf);
else
mm_dbg (" %s: failed (address conversion error)", tag);
@@ -265,24 +276,25 @@ print_address4 (gboolean success, const char *tag, guint32 address, GError *erro
static void
print_address6 (gboolean success,
+ gchar *buf,
+ gsize buf_len,
const char *tag,
GArray *array,
guint32 prefix,
GError *error)
{
struct in6_addr a;
- char buf[INET6_ADDRSTRLEN + 1];
guint32 i;
if (success) {
g_assert (array);
g_assert (array->len == 8);
- memset (buf, 0, sizeof (buf));
+ memset (buf, 0, buf_len);
for (i = 0; i < array->len; i++)
a.s6_addr16[i] = GUINT16_TO_BE (g_array_index (array, guint16, i));
- if (inet_ntop (AF_INET6, &a, buf, sizeof (buf) - 1))
+ if (inet_ntop (AF_INET6, &a, buf, buf_len - 1))
mm_dbg (" %s: %s/%d", tag, buf, prefix);
else
mm_dbg (" %s: failed (address conversion error)", tag);
@@ -316,34 +328,58 @@ get_current_settings_ready (QmiClientWds *client,
guint32 addr, mtu, i;
GArray *array;
guint8 prefix;
+ MMBearerIpConfig *ipv6_config = NULL;
+ MMBearerIpConfig *ipv4_config = NULL;
/* If the message has an IPv4 address, print IPv4 settings */
if (qmi_message_wds_get_current_settings_output_get_ipv4_address (output, &addr, &error)) {
+ gchar buf[INET_ADDRSTRLEN + 1];
+ gchar **dns;
+ guint ndns = 0;
+
+ ipv4_config = mm_bearer_ip_config_new ();
+ mm_bearer_ip_config_set_method (ipv4_config, MM_BEARER_IP_METHOD_STATIC);
+
mm_dbg ("QMI IPv4 Settings:");
/* IPv4 address */
- print_address4 (TRUE, "Address", addr, error);
+ print_address4 (TRUE, buf, INET_ADDRSTRLEN + 1, "Address", addr, error);
+ mm_bearer_ip_config_set_address (ipv4_config, buf);
g_clear_error (&error);
/* IPv4 gateway address */
success = qmi_message_wds_get_current_settings_output_get_ipv4_gateway_address (output, &addr, &error);
- print_address4 (success, "Gateway", addr, error);
+ print_address4 (success, buf, INET_ADDRSTRLEN + 1, "Gateway", addr, error);
+ if (success)
+ mm_bearer_ip_config_set_gateway (ipv4_config, buf);
g_clear_error (&error);
/* IPv4 subnet mask */
success = qmi_message_wds_get_current_settings_output_get_ipv4_gateway_subnet_mask (output, &addr, &error);
- print_address4 (success, "Netmask", addr, error);
+ print_address4 (success, buf, INET_ADDRSTRLEN + 1, "Netmask", addr, error);
+ if (success)
+ mm_bearer_ip_config_set_prefix (ipv4_config, mm_count_bits_set (addr));
g_clear_error (&error);
+ dns = g_new0 (gchar *, 3);
+
/* IPv4 DNS #1 */
success = qmi_message_wds_get_current_settings_output_get_primary_ipv4_dns_address (output, &addr, &error);
- print_address4 (success, " DNS #1", addr, error);
+ print_address4 (success, buf, INET_ADDRSTRLEN + 1, " DNS #1", addr, error);
+ if (success)
+ dns[ndns++] = g_strdup (buf);
g_clear_error (&error);
/* IPv4 DNS #2 */
success = qmi_message_wds_get_current_settings_output_get_secondary_ipv4_dns_address (output, &addr, &error);
- print_address4 (success, " DNS #2", addr, error);
+ print_address4 (success, buf, INET_ADDRSTRLEN + 1, " DNS #2", addr, error);
+ if (success)
+ dns[ndns++] = g_strdup (buf);
g_clear_error (&error);
+
+ if (ndns > 0)
+ mm_bearer_ip_config_set_dns (ipv4_config, (const gchar **)dns);
+ g_strfreev (dns);
} else {
/* no IPv4 configuration */
g_clear_error (&error);
@@ -351,26 +387,46 @@ get_current_settings_ready (QmiClientWds *client,
/* If the message has an IPv6 address, print IPv6 settings */
if (qmi_message_wds_get_current_settings_output_get_ipv6_address (output, &array, &prefix, &error)) {
+ gchar buf[INET6_ADDRSTRLEN + 1];
+ gchar **dns;
+ guint ndns = 0;
+
+ ipv6_config = mm_bearer_ip_config_new ();
+ mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_STATIC);
+
mm_dbg ("QMI IPv6 Settings:");
/* IPv6 address */
- print_address6 (TRUE, "Address", array, prefix, error);
+ print_address6 (TRUE, buf, INET6_ADDRSTRLEN + 1, "Address", array, prefix, error);
+ mm_bearer_ip_config_set_address (ipv6_config, buf);
g_clear_error (&error);
/* IPv6 gateway address */
success = qmi_message_wds_get_current_settings_output_get_ipv6_gateway_address (output, &array, &prefix, &error);
- print_address6 (success, "Gateway", array, prefix, error);
+ print_address6 (success, buf, INET6_ADDRSTRLEN + 1, "Gateway", array, prefix, error);
+ if (success)
+ mm_bearer_ip_config_set_gateway (ipv4_config, buf);
g_clear_error (&error);
+ dns = g_new0 (gchar *, 3);
+
/* IPv6 DNS #1 */
success = qmi_message_wds_get_current_settings_output_get_ipv6_primary_dns_address (output, &array, &error);
- print_address6 (success, " DNS #1", array, 0, error);
+ print_address6 (success, buf, INET6_ADDRSTRLEN + 1, " DNS #1", array, 0, error);
+ if (success)
+ dns[ndns++] = g_strdup (buf);
g_clear_error (&error);
/* IPv6 DNS #2 */
success = qmi_message_wds_get_current_settings_output_get_ipv6_secondary_dns_address (output, &array, &error);
- print_address6 (success, " DNS #2", array, 0, error);
+ print_address6 (success, buf, INET6_ADDRSTRLEN + 1, " DNS #2", array, 0, error);
+ if (success)
+ dns[ndns++] = g_strdup (buf);
g_clear_error (&error);
+
+ if (ndns > 0)
+ mm_bearer_ip_config_set_dns (ipv4_config, (const gchar **)dns);
+ g_strfreev (dns);
} else {
/* no IPv6 configuration */
g_clear_error (&error);
@@ -392,12 +448,32 @@ get_current_settings_ready (QmiClientWds *client,
g_clear_error (&error);
}
- if (qmi_message_wds_get_current_settings_output_get_mtu (output, &mtu, &error))
+ if (qmi_message_wds_get_current_settings_output_get_mtu (output, &mtu, &error)) {
mm_dbg (" MTU: %d", mtu);
- else {
+ if (ipv4_config)
+ mm_bearer_ip_config_set_mtu (ipv4_config, mtu);
+ if (ipv6_config)
+ mm_bearer_ip_config_set_mtu (ipv6_config, mtu);
+ } else {
mm_dbg (" MTU: failed (%s)", error ? error->message : "unknown");
g_clear_error (&error);
}
+
+ /* Set IPv4 config result */
+ if (ipv4_config) {
+ if (!ctx->ipv4_config)
+ ctx->ipv4_config = ipv4_config;
+ else
+ g_object_unref (ipv4_config);
+ }
+
+ /* Set IPv6 config result */
+ if (ipv6_config) {
+ if (!ctx->ipv6_config)
+ ctx->ipv6_config = ipv6_config;
+ else
+ g_object_unref (ipv6_config);
+ }
}
if (output)
@@ -728,8 +804,6 @@ connect_context_step (ConnectContext *ctx)
case CONNECT_STEP_LAST:
/* If one of IPv4 or IPv6 succeeds, we're connected */
if (ctx->packet_data_handle_ipv4 || ctx->packet_data_handle_ipv6) {
- MMBearerIpConfig *config;
-
/* Port is connected; update the state */
mm_port_set_connected (MM_PORT (ctx->data), TRUE);
@@ -751,19 +825,24 @@ connect_context_step (ConnectContext *ctx)
ctx->self->priv->client_ipv6 = g_object_ref (ctx->client_ipv6);
}
- /* Build IP config; always DHCP based */
- config = mm_bearer_ip_config_new ();
- mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP);
+ /* If no static data was retrieved, use dynamic */
+ if (!ctx->ipv4_config) {
+ ctx->ipv4_config = mm_bearer_ip_config_new ();
+ mm_bearer_ip_config_set_method (ctx->ipv4_config, MM_BEARER_IP_METHOD_DHCP);
+ }
+ if (!ctx->ipv6_config) {
+ ctx->ipv6_config = mm_bearer_ip_config_new ();
+ mm_bearer_ip_config_set_method (ctx->ipv6_config, MM_BEARER_IP_METHOD_DHCP);
+ }
/* Set operation result */
g_simple_async_result_set_op_res_gpointer (
ctx->result,
mm_bearer_connect_result_new (
ctx->data,
- ctx->packet_data_handle_ipv4 ? config : NULL,
- ctx->packet_data_handle_ipv6 ? config : NULL),
+ ctx->packet_data_handle_ipv4 ? ctx->ipv4_config : NULL,
+ ctx->packet_data_handle_ipv6 ? ctx->ipv6_config : NULL),
(GDestroyNotify)mm_bearer_connect_result_unref);
- g_object_unref (config);
} else {
GError *error;