diff options
author | Dan Williams <dcbw@redhat.com> | 2012-10-19 19:32:03 -0500 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-10-23 18:20:24 +0200 |
commit | 90e67404d6ab075d8d4bae1f006b69ca26696296 (patch) | |
tree | 246b820988146b6d8d031bf951cbe23f663e6433 | |
parent | 6788f809ea442b7ed3dca7a4f4351d51c67db5d1 (diff) |
bearer-qmi: get and log current IP settings when connecting the bearer
All addresses are given as machine byte order, and thus must be converted
to network byte order (BE) before passing to inet_ntop().
-rw-r--r-- | src/mm-bearer-qmi.c | 216 |
1 files changed, 210 insertions, 6 deletions
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c index b928fca5..9523a1c9 100644 --- a/src/mm-bearer-qmi.c +++ b/src/mm-bearer-qmi.c @@ -19,6 +19,8 @@ #include <unistd.h> #include <string.h> #include <ctype.h> +#include <netinet/in.h> +#include <arpa/inet.h> #include <ModemManager.h> #define _LIBMM_INSIDE_MM @@ -73,6 +75,7 @@ typedef enum { CONNECT_STEP_WDS_CLIENT_IPV6, CONNECT_STEP_IP_FAMILY_IPV6, CONNECT_STEP_START_NETWORK_IPV6, + CONNECT_STEP_GET_CURRENT_SETTINGS, CONNECT_STEP_LAST } ConnectStep; @@ -269,6 +272,184 @@ build_start_network_input (ConnectContext *ctx) } static void +print_address4 (gboolean success, const char *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)) + mm_dbg (" %s: %s", tag, buf); + else + mm_dbg (" %s: failed (address conversion error)", tag); + return; + } + mm_dbg (" %s: failed (%s)", tag, error ? error->message : "unknown"); +} + +static void +print_address6 (gboolean success, + 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)); + 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)) + mm_dbg (" %s: %s/%d", tag, buf, prefix); + else + mm_dbg (" %s: failed (address conversion error)", tag); + + g_array_free (array, TRUE); + return; + } + + mm_dbg (" %s: failed (%s)", tag, error ? error->message : "unknown"); +} + +static void +get_current_settings_ready (QmiClientWds *client, + GAsyncResult *res, + ConnectContext *ctx) +{ + GError *error = NULL; + QmiMessageWdsGetCurrentSettingsOutput *output; + + g_assert (ctx->running_ipv4 || ctx->running_ipv6); + g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); + + output = qmi_client_wds_get_current_settings_finish (client, res, &error); + if (!output || + !qmi_message_wds_get_current_settings_output_get_result (output, &error)) { + /* Never treat this as a hard connection error; not all devices support + * "WDS Get Current Settings" */ + mm_info ("error: couldn't get current settings: %s", error->message); + g_error_free (error); + } else { + gboolean success; + guint32 addr, mtu, i; + GArray *array; + guint8 prefix; + + if (ctx->running_ipv4) { + mm_dbg ("QMI IPv4 Settings:"); + + /* IPv4 address */ + success = qmi_message_wds_get_current_settings_output_get_ipv4_address (output, &addr, &error); + print_address4 (success, "Address", addr, error); + 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); + 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); + g_clear_error (&error); + + /* 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); + 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); + g_clear_error (&error); + } else { + mm_dbg ("QMI IPv6 Settings:"); + + /* IPv6 address */ + success = qmi_message_wds_get_current_settings_output_get_ipv6_address (output, &array, &prefix, &error); + print_address6 (success, "Address", array, prefix, error); + 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); + g_clear_error (&error); + + /* 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); + 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); + g_clear_error (&error); + } + + /* Domain names */ + if (qmi_message_wds_get_current_settings_output_get_domain_name_list (output, &array, &error)) { + GString *s = g_string_sized_new (array ? (array->len * 20) : 1); + + for (i = 0; array && (i < array->len); i++) { + if (s->len) + g_string_append (s, ", "); + g_string_append (s, g_array_index (array, const char *, i)); + } + mm_dbg (" Domains: %s", s->str); + g_string_free (s, TRUE); + } else { + mm_dbg (" Domains: failed (%s)", error ? error->message : "unknown"); + g_clear_error (&error); + } + + if (qmi_message_wds_get_current_settings_output_get_mtu (output, &mtu, &error)) + mm_dbg (" MTU: %d", mtu); + else { + mm_dbg (" MTU: failed (%s)", error ? error->message : "unknown"); + g_clear_error (&error); + } + } + + if (output) + qmi_message_wds_get_current_settings_output_unref (output); + + /* Keep on */ + ctx->step++; + connect_context_step (ctx); +} + +static QmiMessageWdsGetCurrentSettingsInput * +build_get_current_settings_input (ConnectContext *ctx) +{ + QmiMessageWdsGetCurrentSettingsInput *input; + QmiWdsGetCurrentSettingsRequestedSettings requested = QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_NONE; + + g_assert (ctx->running_ipv4 || ctx->running_ipv6); + g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); + + input = qmi_message_wds_get_current_settings_input_new (); + + requested = QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DNS_ADDRESS | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GRANTED_QOS | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_ADDRESS | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GATEWAY_INFO | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_MTU | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DOMAIN_NAME_LIST | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_FAMILY; + + qmi_message_wds_get_current_settings_input_set_requested_settings (input, requested, NULL); + return input; +} + +static void set_ip_family_ready (QmiClientWds *client, GAsyncResult *res, ConnectContext *ctx) @@ -461,7 +642,7 @@ connect_context_step (ConnectContext *ctx) case CONNECT_STEP_IPV6: /* If no IPv6 setup needed, jump to last */ if (!ctx->ipv6) { - ctx->step = CONNECT_STEP_LAST; + ctx->step = CONNECT_STEP_GET_CURRENT_SETTINGS; connect_context_step (ctx); return; } @@ -536,6 +717,29 @@ connect_context_step (ConnectContext *ctx) return; } + case CONNECT_STEP_GET_CURRENT_SETTINGS: { + QmiMessageWdsGetCurrentSettingsInput *input; + QmiClientWds *client; + + if (ctx->running_ipv4) + client = ctx->client_ipv4; + else if (ctx->running_ipv6) + client = ctx->client_ipv6; + else + g_assert_not_reached (); + + mm_dbg ("Getting IP configuration..."); + input = build_get_current_settings_input (ctx); + qmi_client_wds_get_current_settings (client, + input, + 45, + ctx->cancellable, + (GAsyncReadyCallback)get_current_settings_ready, + ctx); + qmi_message_wds_get_current_settings_input_unref (input); + return; + } + 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) { @@ -602,10 +806,10 @@ connect_context_step (ConnectContext *ctx) } static void -connect (MMBearer *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +_connect (MMBearer *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { MMBearerProperties *properties = NULL; ConnectContext *ctx; @@ -1025,7 +1229,7 @@ mm_bearer_qmi_class_init (MMBearerQmiClass *klass) /* Virtual methods */ object_class->dispose = dispose; - bearer_class->connect = connect; + bearer_class->connect = _connect; bearer_class->connect_finish = connect_finish; bearer_class->disconnect = disconnect; bearer_class->disconnect_finish = disconnect_finish; |