aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2012-10-19 19:32:03 -0500
committerAleksander Morgado <aleksander@lanedo.com>2012-10-23 18:20:24 +0200
commit90e67404d6ab075d8d4bae1f006b69ca26696296 (patch)
tree246b820988146b6d8d031bf951cbe23f663e6433
parent6788f809ea442b7ed3dca7a4f4351d51c67db5d1 (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.c216
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;