Merge remote-tracking branch 'cros/upstream' into merge-upstream

Contains following commits:

ecd188f libmbim-glib,proxy: fix reporting of merged subscribe list
095cd71 libmbim-glib,proxy: avoid double GError free
21f7970 mbimcli: add missing EOL in error print when closing device
9277067 libmbim-glib,proxy: don't acquire device context during untrack
d3ac22b libmbim-glib,proxy: improve per-client operation logging
830885b libmbim-glib,proxy: improve per-device operation logging
feaf875 mbim-network: don't manage MBIM channel open when using the proxy
e266810 libmbim-glib,proxy: use same transaction id for all fragments
7e0957d ci: create release tarball and hash as build artifacts
34ce475 docs: add missing references to mbim_device_get_transaction_id()
f59b3f5 libmbim-glib,device: get_transaction_id() already in 1.24.4

BUG=None
TEST=Install on octopus. Check internet connection using UI.

Change-Id: I3464b685d960d03d27b8d3254222a9b9cd93d2da
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f38e5ae..d65df25 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -15,3 +15,11 @@
     - make check
     - make install
     - make distcheck
+    - sha256sum $CI_PROJECT_NAME-*.tar.xz | awk '{print $1;}' > pkg_hash.txt
+  artifacts:
+    name: "$CI_PROJECT_NAME-$CI_COMMIT_SHORT_SHA"
+    paths:
+      - /builds/$CI_PROJECT_ROOT_NAMESPACE/$CI_PROJECT_NAME/$CI_PROJECT_NAME-*.tar.xz
+      - /builds/$CI_PROJECT_ROOT_NAMESPACE/$CI_PROJECT_NAME/pkg_hash.txt
+    expire_in: 2 days
+
diff --git a/docs/reference/libmbim-glib/libmbim-glib-common.sections b/docs/reference/libmbim-glib/libmbim-glib-common.sections
index 7634a7b..c461202 100644
--- a/docs/reference/libmbim-glib/libmbim-glib-common.sections
+++ b/docs/reference/libmbim-glib/libmbim-glib-common.sections
@@ -223,6 +223,7 @@
 mbim_device_close
 mbim_device_close_finish
 mbim_device_close_force
+mbim_device_get_transaction_id
 mbim_device_get_next_transaction_id
 mbim_device_command
 mbim_device_command_finish
diff --git a/docs/reference/libmbim-glib/libmbim-glib-docs.xml b/docs/reference/libmbim-glib/libmbim-glib-docs.xml
index 88bfec8..97ec4ee 100644
--- a/docs/reference/libmbim-glib/libmbim-glib-docs.xml
+++ b/docs/reference/libmbim-glib/libmbim-glib-docs.xml
@@ -147,6 +147,10 @@
     <title>Index of new symbols in 1.24</title>
     <xi:include href="xml/api-index-1.24.xml"></xi:include>
   </chapter>
+  <chapter id="api-index-1-24-4" role="1.24.4">
+    <title>Index of new symbols in 1.24.4</title>
+    <xi:include href="xml/api-index-1.24.4.xml"></xi:include>
+  </chapter>
 
   <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
 </book>
diff --git a/src/libmbim-glib/mbim-device.c b/src/libmbim-glib/mbim-device.c
index 42f83f2..221956a 100644
--- a/src/libmbim-glib/mbim-device.c
+++ b/src/libmbim-glib/mbim-device.c
@@ -1768,6 +1768,16 @@
 
 /*****************************************************************************/
 
+guint32
+mbim_device_get_transaction_id (MbimDevice *self)
+{
+    g_return_val_if_fail (MBIM_IS_DEVICE (self), 0);
+
+    return self->priv->transaction_id;
+}
+
+/*****************************************************************************/
+
 static gboolean
 device_write (MbimDevice    *self,
               const guint8  *data,
diff --git a/src/libmbim-glib/mbim-device.h b/src/libmbim-glib/mbim-device.h
index 2cbdbf6..9c943f8 100644
--- a/src/libmbim-glib/mbim-device.h
+++ b/src/libmbim-glib/mbim-device.h
@@ -383,6 +383,19 @@
 guint32 mbim_device_get_next_transaction_id (MbimDevice *self);
 
 /**
+ * mbim_device_get_transaction_id:
+ * @self: A #MbimDevice.
+ *
+ * Acquire the transaction ID of this #MbimDevice without
+ * incrementing the internal transaction ID.
+ *
+ * Returns: the current transaction ID.
+ *
+ * Since: 1.24.4
+ */
+guint32 mbim_device_get_transaction_id (MbimDevice *self);
+
+/**
  * mbim_device_command:
  * @self: a #MbimDevice.
  * @message: the message to send.
diff --git a/src/libmbim-glib/mbim-proxy.c b/src/libmbim-glib/mbim-proxy.c
index 93b36ad..58b7374 100644
--- a/src/libmbim-glib/mbim-proxy.c
+++ b/src/libmbim-glib/mbim-proxy.c
@@ -95,6 +95,7 @@
 
 typedef struct {
     volatile gint ref_count;
+    gulong        id;
 
     MbimProxy *self; /* not full ref */
     GSocketConnection *connection;
@@ -127,7 +128,7 @@
     }
 
     if (client->connection) {
-        g_debug ("Client (%d) connection closed...", g_socket_get_fd (g_socket_connection_get_socket (client->connection)));
+        g_debug ("[client %lu] connection closed", client->id);
         g_output_stream_close (g_io_stream_get_output_stream (G_IO_STREAM (client->connection)), NULL, NULL);
         g_object_unref (client->connection);
         client->connection = NULL;
@@ -187,9 +188,9 @@
 }
 
 static gboolean
-client_send_message (Client *client,
-                     MbimMessage *message,
-                     GError **error)
+client_send_message (Client       *client,
+                     MbimMessage  *message,
+                     GError      **error)
 {
     if (!client->connection) {
         g_set_error (error,
@@ -199,7 +200,6 @@
         return FALSE;
     }
 
-    g_debug ("Client (%d) TX: %u bytes", g_socket_get_fd (g_socket_connection_get_socket (client->connection)), message->len);
     if (!g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (client->connection)),
                                     message->data,
                                     message->len,
@@ -245,12 +245,10 @@
 forward_indication (Client      *client,
                     MbimMessage *message)
 {
-    GError *error = NULL;
+    g_autoptr(GError) error = NULL;
 
-    if (!client_send_message (client, message, &error)) {
-        g_warning ("couldn't forward indication to client");
-        g_error_free (error);
-    }
+    if (!client_send_message (client, message, &error))
+        g_warning ("[client %lu] couldn't forward indication: %s", client->id, error->message);
 }
 
 static void
@@ -312,13 +310,13 @@
 request_complete_and_free (Request *request)
 {
     if (request->response) {
-        GError *error = NULL;
+        g_autoptr(GError) error = NULL;
 
         /* Try to send response to client; if it fails, always assume we have
          * to close the connection */
         if (!client_send_message (request->client, request->response, &error)) {
-            g_debug ("couldn't send response back to client: %s", error->message);
-            g_error_free (error);
+            g_warning ("[client %lu,0x%08x] couldn't send response back to client: %s",
+                       request->client->id, request->original_transaction_id, error->message);
             /* Disconnect and untrack client */
             untrack_client (request->self, request->client);
         }
@@ -516,9 +514,9 @@
                                        GAsyncResult *res,
                                        GTask        *task)
 {
-    MbimProxy   *self;
-    GError      *error = NULL;
-    MbimMessage *response;
+    MbimProxy              *self;
+    g_autoptr(MbimMessage)  response = NULL;
+    g_autoptr(GError)       error = NULL;
 
     self = g_task_get_source_object (task);
 
@@ -529,26 +527,23 @@
     if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
         /* If we get a not-opened error, well, force closing right away and reopen */
         if (g_error_matches (error, MBIM_PROTOCOL_ERROR, MBIM_PROTOCOL_ERROR_NOT_OPENED)) {
-            g_debug ("device not-opened error reported, reopening");
+            g_debug ("[%s] device not-opened error reported, reopening", mbim_device_get_path (device));
             reset_client_service_subscribe_lists (self, device);
             mbim_device_close_force (device, NULL);
             internal_open (task);
-            if (response)
-                mbim_message_unref (response);
-            g_error_free (error);
             return;
         }
 
         /* Warn other (unlikely!) errors, but keep on anyway */
-        g_warning ("device caps query during internal open failed: %s", error->message);
-        g_error_free (error);
+        g_warning ("[%s] device caps query during internal open failed: %s",
+                   mbim_device_get_path (device), error->message);
     }
 
+    g_debug ("[%s] device caps query during internal open succeeded",
+             mbim_device_get_path (device));
+
     g_task_return_boolean (task, TRUE);
     g_object_unref (task);
-
-    if (response)
-        mbim_message_unref (response);
 }
 
 static void
@@ -579,7 +574,8 @@
          * ready callback, and we'll reopen silently if we find this. */
         g_signal_handlers_block_by_func (device, proxy_device_error_cb, self);
 
-        g_debug ("checking device caps during client device open...");
+        g_debug ("[%s] checking device caps during client device open...",
+                 mbim_device_get_path (device));
         message = mbim_message_device_caps_query_new (NULL);
         mbim_device_command (device,
                              message,
@@ -609,11 +605,11 @@
     request = request_new (self, client, message);
 
     if (!client->device)
-        g_warning ("cannot process Open: device not set");
+        g_warning ("[client %lu] cannot process MBIM open: device not set", client->id);
     else if (!mbim_device_is_open (client->device))
-        g_warning ("cannot process Open: device not opened by proxy");
+        g_warning ("[client %lu] cannot process MBIM open: device not opened by proxy", client->id);
     else {
-        g_debug ("connection to MBIM device '%s' established", mbim_device_get_path (client->device));
+        g_debug ("[client %lu] connection to MBIM device '%s' established", client->id, mbim_device_get_path (client->device));
         status = MBIM_STATUS_ERROR_NONE;
     }
 
@@ -631,9 +627,14 @@
                               MbimMessage *message)
 {
     Request *request;
+    guint32  original_transaction_id;
+
+    original_transaction_id = mbim_message_get_transaction_id (message);
+    g_debug ("[client %lu,0x%08x] requested explicit MBIM channel close",
+             client->id, original_transaction_id);
 
     request = request_new (self, client, message);
-    request->response = mbim_message_close_done_new (mbim_message_get_transaction_id (message), MBIM_STATUS_ERROR_NONE);
+    request->response = mbim_message_close_done_new (original_transaction_id, MBIM_STATUS_ERROR_NONE);
     request_complete_and_free (request);
     return TRUE;
 }
@@ -667,17 +668,20 @@
                                          GAsyncResult *res,
                                          Request      *request)
 {
-    GError *error = NULL;
+    g_autoptr(GError) error = NULL;
 
     if (!internal_device_open_finish (self, res, &error)) {
-        g_warning ("error opening device: %s", error->message);
-        g_error_free (error);
+        g_warning ("[client %lu,0x%08x] cannot configure proxy: couldn't open MBIM device: %s",
+                   request->client->id, request->original_transaction_id, error->message);
         /* Untrack client and complete without response */
         untrack_client (request->self, request->client);
         request_complete_and_free (request);
         return;
     }
 
+    g_debug ("[client %lu,0x%08x] proxy configured",
+             request->client->id, request->original_transaction_id);
+
     if (request->client->config_ongoing == TRUE)
         request->client->config_ongoing = FALSE;
     request->response = build_proxy_control_command_done (request->message, MBIM_STATUS_ERROR_NONE);
@@ -689,14 +693,14 @@
                   GAsyncResult *res,
                   Request      *request)
 {
-    GError *error = NULL;
-    MbimDevice *existing;
-    MbimDevice *device;
+    g_autoptr(GError)  error = NULL;
+    MbimDevice        *existing;
+    MbimDevice        *device;
 
     device = mbim_device_new_finish (res, &error);
     if (!device) {
-        g_warning ("couldn't create MBIM device: %s", error->message);
-        g_error_free (error);
+        g_warning ("[client %lu,0x%08x] cannot configure proxy: couldn't create MBIM device: %s",
+                   request->client->id, request->original_transaction_id, error->message);
         /* Untrack client and complete without response */
         untrack_client (request->self, request->client);
         request_complete_and_free (request);
@@ -738,8 +742,13 @@
     /* create request holder */
     request = request_new (self, client, message);
 
+    g_debug ("[client %lu,0x%08x] request to configure proxy",
+             request->client->id, request->original_transaction_id);
+
     /* Error out if there is already a proxy config ongoing */
     if (client->config_ongoing) {
+        g_warning ("[client %lu,0x%08x] cannot configure proxy: another request already ongoing",
+                   request->client->id, request->original_transaction_id);
         request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_BUSY);
         request_complete_and_free (request);
         return TRUE;
@@ -747,6 +756,8 @@
 
     /* Only allow SET command */
     if (mbim_message_command_get_command_type (message) != MBIM_MESSAGE_COMMAND_TYPE_SET) {
+        g_warning ("[client %lu,0x%08x] cannot configure proxy: invalid request type",
+                   request->client->id, request->original_transaction_id);
         request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_INVALID_PARAMETERS);
         request_complete_and_free (request);
         return TRUE;
@@ -754,7 +765,8 @@
 
     /* Retrieve path from request */
     if (!_mbim_message_read_string (message, 0, 0, &incoming_path, &error)) {
-        g_warning ("Error reading device path from message: %s", error->message);
+        g_warning ("[client %lu,0x%08x] cannot configure proxy: couldn't read device path from request: %s",
+                   request->client->id, request->original_transaction_id, error->message);
         request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_INVALID_PARAMETERS);
         request_complete_and_free (request);
         return TRUE;
@@ -765,7 +777,8 @@
      * each other. */
     path = __mbim_utils_get_devpath (incoming_path, &error);
     if (!path) {
-        g_warning ("Error looking up real device path: %s", error->message);
+        g_warning ("[client %lu,0x%08x] cannot configure proxy: couldn't lookup real device path: %s",
+                   request->client->id, request->original_transaction_id, error->message);
         request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_INVALID_PARAMETERS);
         request_complete_and_free (request);
         return TRUE;
@@ -773,17 +786,23 @@
 
     /* Only allow subsequent requests with the same path */
     if (client->device) {
-        if (g_str_equal (path, mbim_device_get_path (client->device)))
+        if (g_str_equal (path, mbim_device_get_path (client->device))) {
+            g_debug ("[client %lu,0x%08x] proxy re-configured",
+                       request->client->id, request->original_transaction_id);
             request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_NONE);
-        else
+        } else {
+            g_warning ("[client %lu,0x%08x] cannot configure proxy: different device path given",
+                       request->client->id, request->original_transaction_id);
             request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_FAILURE);
+        }
         request_complete_and_free (request);
         return TRUE;
     }
 
     /* Read requested timeout value */
     if (!_mbim_message_read_guint32 (message, 8, &request->timeout_secs, &error)) {
-        g_warning ("Error reading requested timeout from message: %s", error->message);
+        g_warning ("[client %lu,0x%08x] cannot configure proxy: couldn't read timeout from request: %s",
+                   request->client->id, request->original_transaction_id, error->message);
         request->response = build_proxy_control_command_done (message, MBIM_STATUS_ERROR_INVALID_PARAMETERS);
         request_complete_and_free (request);
         return TRUE;
@@ -827,7 +846,7 @@
 
     mbim_event_entry_array = _mbim_proxy_helper_service_subscribe_request_parse (message, &mbim_event_entry_array_size, &error);
     if (error) {
-        g_warning ("Invalid subscribe request message: %s", error->message);
+        g_warning ("[client %lu] invalid subscribe request message: %s", client->id, error->message);
         return;
     }
 
@@ -839,7 +858,7 @@
     client->mbim_event_entry_array_size = mbim_event_entry_array_size;
 
     if (mbim_utils_get_traces_enabled ()) {
-        g_debug ("Client (%d) service subscribe list built", g_socket_get_fd (g_socket_connection_get_socket (client->connection)));
+        g_debug ("[client %lu] service subscribe list built", client->id);
         _mbim_proxy_helper_service_subscribe_list_debug ((const MbimEventEntry * const *)client->mbim_event_entry_array,
                                                          client->mbim_event_entry_array_size);
     }
@@ -885,17 +904,22 @@
     if (!tmp_response) {
         /* Translate a MbimDevice wrong state error into a Not-Opened function error. */
         if (g_error_matches (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE)) {
+            g_debug ("[client %lu,0x%08x] sending request to device failed: wrong state",
+                     request->client->id, request->original_transaction_id);
             request->response = mbim_message_function_error_new (mbim_message_get_transaction_id (request->message), MBIM_PROTOCOL_ERROR_NOT_OPENED);
             request_complete_and_free (request);
             return;
         }
 
         /* Don't disconnect client, just let the request timeout in its side */
-        g_debug ("sending request to device failed: %s", error->message);
+        g_debug ("[client %lu,0x%08x] sending request to device failed: %s",
+                 request->client->id, request->original_transaction_id, error->message);
         request_complete_and_free (request);
         return;
     }
 
+    g_debug ("[client %lu,0x%08x] response from device received",
+             request->client->id, request->original_transaction_id);
     error_status_code = GUINT32_FROM_LE (((struct full_message *)(tmp_response->data))->message.command_done.status_code);
     device_service_subscribe_list_set_complete (request, error_status_code);
 }
@@ -913,12 +937,17 @@
     /* create request holder */
     request = request_new (self, client, message);
 
+    g_debug ("[client %lu,0x%08x] request to update service subscribe list received",
+             request->client->id, request->original_transaction_id);
+
     /* trace the service subscribe list for the client */
     track_service_subscribe_list (client, message);
 
     /* merge all service subscribe list for all clients to set on device */
     updated = merge_client_service_subscribe_lists (self, client->device, &updated_size);
     if (!updated) {
+        g_debug ("[client %lu,0x%08x] service subscribe list update in device not needed",
+                 request->client->id, request->original_transaction_id);
         device_service_subscribe_list_set_complete (request, MBIM_STATUS_ERROR_NONE);
         return TRUE;
     }
@@ -927,6 +956,8 @@
     request_message = mbim_message_device_service_subscribe_list_set_new (updated_size, (const MbimEventEntry *const *)updated, NULL);
     mbim_message_set_transaction_id (request_message, mbim_device_get_next_transaction_id (client->device));
 
+    g_debug ("[client %lu,0x%08x] updating service subscribe list in device...",
+             request->client->id, request->original_transaction_id);
     mbim_device_command (client->device,
                          request_message,
                          300,
@@ -950,18 +981,23 @@
     if (!request->response) {
         /* Translate a MbimDevice wrong state error into a Not-Opened function error. */
         if (g_error_matches (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_WRONG_STATE)) {
+            g_debug ("[client %lu,0x%08x] sending request to device failed: wrong state",
+                     request->client->id, request->original_transaction_id);
             request->response = mbim_message_function_error_new (request->original_transaction_id, MBIM_PROTOCOL_ERROR_NOT_OPENED);
             request_complete_and_free (request);
             return;
         }
 
         /* Don't disconnect client, just let the request timeout in its side */
-        g_debug ("sending request to device failed: %s", error->message);
+        g_debug ("[client %lu,0x%08x] sending request to device failed: %s",
+                 request->client->id, request->original_transaction_id, error->message);
         request_complete_and_free (request);
         return;
     }
 
     /* replace reponse transaction id with the requested transaction id */
+    g_debug ("[client %lu,0x%08x] response from device received",
+             request->client->id, request->original_transaction_id);
     mbim_message_set_transaction_id (request->response, request->original_transaction_id);
     request_complete_and_free (request);
 }
@@ -971,13 +1007,31 @@
                  Client      *client,
                  MbimMessage *message)
 {
-    Request *request;
+    Request     *request;
+    const gchar *command;
+    const gchar *command_type;
+    const gchar *service;
+
+    command = mbim_cid_get_printable (mbim_message_command_get_service (message),
+                                      mbim_message_command_get_cid (message));
+    command_type = mbim_message_command_type_get_string (mbim_message_command_get_command_type (message));
+    service = mbim_service_get_string (mbim_message_command_get_service (message));
 
     /* create request holder */
     request = request_new (self, client, message);
 
-    /* replace command transaction id with internal proxy transaction id to avoid collision */
-    mbim_message_set_transaction_id (message, mbim_device_get_next_transaction_id (client->device));
+    g_debug ("[client %lu,0x%08x] forwarding request to device: %s, %s, %s",
+             client->id, request->original_transaction_id,
+             service      ? service      : "unknown service",
+             command_type ? command_type : "unknown command type",
+             command      ? command      : "unknown command");
+
+    if (_mbim_message_fragment_get_current (message) == _mbim_message_fragment_get_total (message) - 1)
+        /* replace command transaction id with internal proxy transaction id to avoid collision */
+        mbim_message_set_transaction_id (message, mbim_device_get_next_transaction_id (client->device));
+    else
+        /* avoid incrementing transaction until the last fragment is processed */
+        mbim_message_set_transaction_id (message, mbim_device_get_transaction_id (client->device));
 
     /* The timeout needs to be big enough for any kind of transaction to
      * complete, otherwise the remote clients will lose the reply if they
@@ -1025,7 +1079,7 @@
     case MBIM_MESSAGE_TYPE_CLOSE_DONE:
     case MBIM_MESSAGE_TYPE_FUNCTION_ERROR:
     default:
-        g_debug ("invalid message from client: not a command message");
+        g_debug ("[client %lu] invalid message: not a command", client->id);
         return FALSE;
     }
 
@@ -1085,7 +1139,7 @@
                              NULL,
                              &error);
     if (r < 0) {
-        g_warning ("Error reading from istream: %s", error ? error->message : "unknown");
+        g_warning ("[client %lu] error reading from istream: %s", client->id, error ? error->message : "unknown");
         /* Close the device */
         untrack_client (self, client);
         return FALSE;
@@ -1111,28 +1165,32 @@
              GObject           *unused,
              MbimProxy         *self)
 {
+    static gulong            client_id = 0;
     Client                  *client;
     g_autoptr(GCredentials)  credentials = NULL;
     g_autoptr(GError)        error = NULL;
     uid_t                    uid;
 
-    g_debug ("Client (%d) connection open...", g_socket_get_fd (g_socket_connection_get_socket (connection)));
+    /* Each new incoming request updates the client id, even if the request is
+     * not accepted */
+    client_id++;
+
+    g_debug ("[client %lu] connection open...", client_id);
 
     credentials = g_socket_get_credentials (g_socket_connection_get_socket (connection), &error);
     if (!credentials) {
-        g_warning ("Client not allowed: Error getting socket credentials: %s", error->message);
-        g_error_free (error);
+        g_warning ("[client %lu] not allowed: error getting socket credentials: %s", client_id, error->message);
         return;
     }
 
     uid = g_credentials_get_unix_user (credentials, &error);
     if (error) {
-        g_warning ("Client not allowed: Error getting unix user id: %s", error->message);
+        g_warning ("[client %lu] not allowed: error getting unix user id: %s", client_id, error->message);
         return;
     }
 
     if (!__mbim_user_allowed (uid, &error)) {
-        g_warning ("Client not allowed: %s", error->message);
+        g_warning ("[client %lu] not allowed: %s", client_id, error->message);
         return;
     }
 
@@ -1140,6 +1198,7 @@
     client = g_slice_new0 (Client);
     client->self = self;
     client->ref_count = 1;
+    client->id = client_id;
     client->connection = g_object_ref (connection);
 
     /* By default, a new client has all the standard services enabled for indications */
@@ -1236,7 +1295,7 @@
         ctx = g_slice_new0 (DeviceContext);
         ctx->mbim_event_entry_array = _mbim_proxy_helper_service_subscribe_list_new_standard (&ctx->mbim_event_entry_array_size);
 
-        g_debug ("Initial device subscribe list...");
+        g_debug ("[%s] initial device subscribe list...", mbim_device_get_path (device));
         _mbim_proxy_helper_service_subscribe_list_debug ((const MbimEventEntry * const *)ctx->mbim_event_entry_array, ctx->mbim_event_entry_array_size);
 
         g_object_set_qdata_full (G_OBJECT (device), device_context_quark, ctx, (GDestroyNotify)device_context_free);
@@ -1255,6 +1314,7 @@
     gsize                           updated_size = 0;
     DeviceContext                  *ctx;
 
+    g_debug ("[%s] merging client service subscribe lists...", mbim_device_get_path (device));
     ctx = device_context_get (device);
     g_assert (ctx);
 
@@ -1282,7 +1342,7 @@
     if (_mbim_proxy_helper_service_subscribe_list_cmp (
             (const MbimEventEntry *const *)updated, updated_size,
             (const MbimEventEntry *const *)ctx->mbim_event_entry_array, ctx->mbim_event_entry_array_size)) {
-        g_debug ("Merged service subscribe list not updated for device '%s'", mbim_device_get_path (device));
+        g_debug ("[%s] merged service subscribe list not updated", mbim_device_get_path (device));
         return NULL;
     }
 
@@ -1292,13 +1352,13 @@
     ctx->mbim_event_entry_array_size = updated_size;
 
     if (mbim_utils_get_traces_enabled ()) {
-        g_debug ("Merged service subscribe list built for device '%s'", mbim_device_get_path (device));
+        g_debug ("[%s] merged service subscribe list built", mbim_device_get_path (device));
         _mbim_proxy_helper_service_subscribe_list_debug ((const MbimEventEntry * const *)ctx->mbim_event_entry_array,
                                                          ctx->mbim_event_entry_array_size);
     }
 
-    *out_size = updated_size;
-    return updated;
+    *out_size = ctx->mbim_event_entry_array_size;
+    return ctx->mbim_event_entry_array;
 }
 
 static void
@@ -1308,6 +1368,7 @@
     DeviceContext *ctx;
     GList         *l;
 
+    g_debug ("[%s] reseting client service subscribe lists...", mbim_device_get_path (device));
     ctx = device_context_get (device);
     g_assert (ctx);
 
@@ -1336,7 +1397,7 @@
                        MbimProxy  *self)
 {
     if (g_error_matches (error, MBIM_PROTOCOL_ERROR, MBIM_PROTOCOL_ERROR_NOT_OPENED)) {
-        g_debug ("device '%s' reports as being closed...", mbim_device_get_path (device));
+        g_debug ("[%s] reports as being closed...", mbim_device_get_path (device));
         reset_client_service_subscribe_lists (self, device);
         mbim_device_close_force (device, NULL);
     }
@@ -1368,12 +1429,10 @@
 untrack_device (MbimProxy  *self,
                 MbimDevice *device)
 {
-    GList         *l;
-    GList         *to_remove = NULL;
-    DeviceContext *ctx;
+    GList *l;
+    GList *to_remove = NULL;
 
-    ctx = device_context_get (device);
-    g_assert (ctx);
+    g_debug ("[%s] untracking device...", mbim_device_get_path (device));
 
     if (!g_list_find (self->priv->devices, device))
         return;
diff --git a/src/mbimcli/mbimcli.c b/src/mbimcli/mbimcli.c
index 9e92843..b6114db 100644
--- a/src/mbimcli/mbimcli.c
+++ b/src/mbimcli/mbimcli.c
@@ -196,7 +196,7 @@
     GError *error = NULL;
 
     if (!mbim_device_close_finish (dev, res, &error)) {
-        g_printerr ("error: couldn't close device: %s", error->message);
+        g_printerr ("error: couldn't close device: %s\n", error->message);
         g_error_free (error);
     } else
         g_debug ("Device closed");
diff --git a/utils/mbim-network.in b/utils/mbim-network.in
index cb8db19..17d92e4 100755
--- a/utils/mbim-network.in
+++ b/utils/mbim-network.in
@@ -200,6 +200,10 @@
     KEY=$1
     VAL=$2
 
+    if [ -n "${PROXY_OPT}" ]; then
+        return
+    fi
+
     echo "Saving state at ${STATE_FILE}... ($KEY: $VAL)"
 
     if [ -f "$STATE_FILE" ]; then
@@ -219,10 +223,13 @@
 
 load_state ()
 {
+    if [ -n "${PROXY_OPT}" ]; then
+        return
+    fi
+
     if [ -f "$STATE_FILE" ]; then
         echo "Loading previous state from ${STATE_FILE}..."
         . $STATE_FILE
-
         if [ -n "$TRID" ]; then
             echo "    Previous Transaction ID: $TRID"
         fi
@@ -231,6 +238,10 @@
 
 clear_state ()
 {
+    if [ -n "${PROXY_OPT}" ]; then
+        return
+    fi
+
     echo "Clearing state at ${STATE_FILE}..."
     rm -f $STATE_FILE
 }
@@ -249,44 +260,57 @@
 connect ()
 {
     # Always try to connect using a fresh session
-    if [ -n "$TRID" ]; then
-        mbimcli -d $DEVICE --no-open=$TRID $PROXY_OPT
-        clear_state
+    if [ -z "${PROXY_OPT}" ]; then
+        if [ -n "$TRID" ]; then
+            # This will implicitly close the previous session
+            mbimcli -d $DEVICE --no-open=$TRID
+            clear_state
+        fi
     fi
 
-    SUBSCRIBER_READY_CMD="mbimcli -d $DEVICE --query-subscriber-ready-status --no-close $PROXY_OPT"
+    if [ -z "${PROXY_OPT}" ]; then
+        EXTRA_OPT="--no-close"
+    else
+        EXTRA_OPT="${PROXY_OPT}"
+    fi
+
+    SUBSCRIBER_READY_CMD="mbimcli -d $DEVICE --query-subscriber-ready-status ${EXTRA_OPT}"
     echo "Querying subscriber ready status '$SUBSCRIBER_READY_CMD'..."
 
     SUBSCRIBER_READY_OUT=`$SUBSCRIBER_READY_CMD`
     echo $SUBSCRIBER_READY_OUT
 
-    # Save the new TRID
-    TRID=`echo "$SUBSCRIBER_READY_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"`
-    if [ -n "$TRID" ]; then
-        save_state "TRID" $TRID
+    if [ -z "${PROXY_OPT}" ]; then
+        TRID=`echo "$SUBSCRIBER_READY_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"`
+        EXTRA_OPT="--no-open=$TRID --no-close"
+    else
+        EXTRA_OPT="${PROXY_OPT}"
     fi
 
-    REGISTRATION_STATE_CMD="mbimcli -d $DEVICE --query-registration-state --no-open=$TRID --no-close $PROXY_OPT"
+    REGISTRATION_STATE_CMD="mbimcli -d $DEVICE --query-registration-state ${EXTRA_OPT}"
     echo "Querying registration state '$REGISTRATION_STATE_CMD'..."
 
     REGISTRATION_STATE_OUT=`$REGISTRATION_STATE_CMD`
     echo $REGISTRATION_STATE_OUT
 
-    # Save the new TRID
-    TRID=`echo "$REGISTRATION_STATE_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"`
-    if [ -n "$TRID" ]; then
-        save_state "TRID" $TRID
+    if [ -z "${PROXY_OPT}" ]; then
+        TRID=`echo "$REGISTRATION_STATE_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"`
+        EXTRA_OPT="--no-open=$TRID --no-close"
+    else
+        EXTRA_OPT="${PROXY_OPT}"
     fi
 
-    ATTACH_CMD="mbimcli -d $DEVICE --attach-packet-service --no-open=$TRID --no-close $PROXY_OPT"
+    ATTACH_CMD="mbimcli -d $DEVICE --attach-packet-service ${EXTRA_OPT}"
     echo "Attaching to packet service with '$ATTACH_CMD'..."
 
     ATTACH_OUT=`$ATTACH_CMD`
+    echo $ATTACH_OUT
 
-    # Save the new TRID
-    TRID=`echo "$ATTACH_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"`
-    if [ -n "$TRID" ]; then
-        save_state "TRID" $TRID
+    if [ -z "${PROXY_OPT}" ]; then
+        TRID=`echo "$ATTACH_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"`
+        EXTRA_OPT="--no-open=$TRID --no-close"
+    else
+        EXTRA_OPT="${PROXY_OPT}"
     fi
 
     CONNECT_ARGS="apn='$APN'"
@@ -300,7 +324,7 @@
         fi
     fi
 
-    CONNECT_CMD="mbimcli -d $DEVICE --connect=$CONNECT_ARGS --no-open=$TRID --no-close $PROXY_OPT"
+    CONNECT_CMD="mbimcli -d $DEVICE --connect=$CONNECT_ARGS ${EXTRA_OPT}"
     echo "Starting network with '$CONNECT_CMD'..."
 
     CONNECT_OUT=`$CONNECT_CMD`
@@ -312,9 +336,11 @@
     fi
 
     # Save the new TRID
-    TRID=`echo "$CONNECT_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"`
-    if [ -n "$TRID" ]; then
-        save_state "TRID" $TRID
+    if [ -z "${PROXY_OPT}" ]; then
+        TRID=`echo "$CONNECT_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"`
+        if [ -n "$TRID" ]; then
+            save_state "TRID" $TRID
+        fi
     fi
 }
 
@@ -332,11 +358,15 @@
 disconnect ()
 {
     # Always close the session when disconnecting
-    if [ -n "$TRID" ]; then
-        DISCONNECT_CMD="mbimcli -d $DEVICE --disconnect --no-open=$TRID $PROXY_OPT"
+    if [ -n "${PROXY_OPT}" ]; then
+        EXTRA_OPT="${PROXY_OPT}"
+    elif [ -n "$TRID" ]; then
+        EXTRA_OPT="--no-open=$TRID"
     else
-        DISCONNECT_CMD="mbimcli -d $DEVICE --disconnect $PROXY_OPT"
+        EXTRA_OPT=""
     fi
+    DISCONNECT_CMD="mbimcli -d $DEVICE --disconnect ${EXTRA_OPT}"
+
     echo "Stopping network with '$DISCONNECT_CMD'..."
 
     DISCONNECT_OUT=`$DISCONNECT_CMD`
@@ -362,19 +392,25 @@
 #
 status ()
 {
-    if [ -n "$TRID" ]; then
-        STATUS_CMD="mbimcli -d $DEVICE --query-connection-state --no-close --no-open=$TRID $PROXY_OPT"
+    if [ -n "${PROXY_OPT}" ]; then
+        EXTRA_OPT="${PROXY_OPT}"
+    elif [ -n "$TRID" ]; then
+        EXTRA_OPT="--no-open=$TRID --no-close"
     else
-        STATUS_CMD="mbimcli -d $DEVICE --query-connection-state $PROXY_OPT"
+        EXTRA_OPT=""
     fi
+
+    STATUS_CMD="mbimcli -d $DEVICE --query-connection-state ${EXTRA_OPT}"
     echo "Getting status with '$STATUS_CMD'..."
 
     STATUS_OUT=`$STATUS_CMD`
 
     # Save the new TRID
-    TRID=`echo "$STATUS_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"`
-    if [ -n "$TRID" ]; then
-        save_state "TRID" $TRID
+    if [ -z "${PROXY_OPT}" ]; then
+        TRID=`echo "$STATUS_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"`
+        if [ -n "$TRID" ]; then
+            save_state "TRID" $TRID
+        fi
     fi
 
     CONN=`echo "$STATUS_OUT" | sed -n "s/.*Activation state:.*'\(.*\)'.*/\1/p"`