diff options
-rw-r--r-- | src/mm-bearer-qmi.c | 131 |
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; |