summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/reference/libmbim-glib/meson.build2
-rw-r--r--src/libmbim-glib/mbim-device.c4
-rw-r--r--src/libmbim-glib/mbim-helpers.c10
-rw-r--r--src/libmbim-glib/mbim-helpers.h10
-rw-r--r--src/libmbim-glib/mbim-net-port-manager-wdm.c262
-rw-r--r--src/libmbim-glib/mbim-net-port-manager-wdm.h44
-rw-r--r--src/libmbim-glib/mbim-net-port-manager.c423
-rw-r--r--src/libmbim-glib/mbim-net-port-manager.h68
-rw-r--r--src/libmbim-glib/meson.build1
9 files changed, 545 insertions, 279 deletions
diff --git a/docs/reference/libmbim-glib/meson.build b/docs/reference/libmbim-glib/meson.build
index 29c6adc..803b939 100644
--- a/docs/reference/libmbim-glib/meson.build
+++ b/docs/reference/libmbim-glib/meson.build
@@ -15,6 +15,8 @@ private_headers = [
'mbim-helpers-netlink.h',
'mbim-message-private.h',
'mbim-net-port-manager.h',
+ 'mbim-net-port-manager-wdm.h',
+ 'wwan.h',
]
scan_args = [
diff --git a/src/libmbim-glib/mbim-device.c b/src/libmbim-glib/mbim-device.c
index cc623e7..bfc4084 100644
--- a/src/libmbim-glib/mbim-device.c
+++ b/src/libmbim-glib/mbim-device.c
@@ -39,6 +39,7 @@
#include "mbim-proxy.h"
#include "mbim-proxy-control.h"
#include "mbim-net-port-manager.h"
+#include "mbim-net-port-manager-wdm.h"
#include "mbim-basic-connect.h"
#include "mbim-ms-basic-connect-extensions.h"
@@ -593,7 +594,8 @@ setup_net_port_manager (MbimDevice *self,
return FALSE;
}
- self->priv->net_port_manager = mbim_net_port_manager_new (self->priv->wwan_iface, error);
+ self->priv->net_port_manager = MBIM_NET_PORT_MANAGER (mbim_net_port_manager_wdm_new (self->priv->wwan_iface, error));
+
return !!self->priv->net_port_manager;
}
diff --git a/src/libmbim-glib/mbim-helpers.c b/src/libmbim-glib/mbim-helpers.c
index 9667981..3a37556 100644
--- a/src/libmbim-glib/mbim-helpers.c
+++ b/src/libmbim-glib/mbim-helpers.c
@@ -102,11 +102,11 @@ mbim_helpers_get_devname (const gchar *cdc_wdm_path,
/*****************************************************************************/
gboolean
-mbim_helpers_list_links (GFile *sysfs_file,
- GCancellable *cancellable,
- GPtrArray *previous_links,
- GPtrArray **out_links,
- GError **error)
+mbim_helpers_list_links_wdm (GFile *sysfs_file,
+ GCancellable *cancellable,
+ GPtrArray *previous_links,
+ GPtrArray **out_links,
+ GError **error)
{
g_autofree gchar *sysfs_path = NULL;
g_autoptr(GFileEnumerator) direnum = NULL;
diff --git a/src/libmbim-glib/mbim-helpers.h b/src/libmbim-glib/mbim-helpers.h
index 1f26fc3..b314e0e 100644
--- a/src/libmbim-glib/mbim-helpers.h
+++ b/src/libmbim-glib/mbim-helpers.h
@@ -31,11 +31,11 @@ gchar *mbim_helpers_get_devname (const gchar *cdc_wdm_path,
GError **error);
G_GNUC_INTERNAL
-gboolean mbim_helpers_list_links (GFile *sysfs_file,
- GCancellable *cancellable,
- GPtrArray *previous_links,
- GPtrArray **out_links,
- GError **error);
+gboolean mbim_helpers_list_links_wdm (GFile *sysfs_file,
+ GCancellable *cancellable,
+ GPtrArray *previous_links,
+ GPtrArray **out_links,
+ GError **error);
#if !GLIB_CHECK_VERSION(2,54,0)
diff --git a/src/libmbim-glib/mbim-net-port-manager-wdm.c b/src/libmbim-glib/mbim-net-port-manager-wdm.c
new file mode 100644
index 0000000..2d0aa9a
--- /dev/null
+++ b/src/libmbim-glib/mbim-net-port-manager-wdm.c
@@ -0,0 +1,262 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * libmbim-glib -- GLib/GIO based library to control MBIM devices
+ *
+ * Copyright (C) 2022 Daniele Palmas <dnlplm@gmail.com>
+ *
+ * Based on previous work:
+ * Copyright (C) 2020-2021 Eric Caruso <ejcaruso@chromium.org>
+ * Copyright (C) 2020-2021 Andrew Lassalle <andrewlassalle@chromium.org>
+ * Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#include <linux/if_link.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include "mbim-device.h"
+#include "mbim-helpers.h"
+#include "mbim-error-types.h"
+#include "mbim-net-port-manager.h"
+#include "mbim-net-port-manager-wdm.h"
+#include "mbim-helpers-netlink.h"
+
+G_DEFINE_TYPE (MbimNetPortManagerWdm, mbim_net_port_manager_wdm, MBIM_TYPE_NET_PORT_MANAGER)
+
+/* alternative VLAN for IP session 0 if not untagged */
+#define MBIM_IPS0_VID 4094
+
+#define VLAN_DATA_TYPE "vlan"
+
+/*****************************************************************************/
+
+static guint
+session_id_to_vlan_id (guint session_id)
+{
+ /* VLAN ID 4094 is an alternative mapping of MBIM session 0. If you create
+ * a subinterface with this ID then it will take over the session 0 traffic
+ * and no packets go untagged anymore. */
+ return (session_id == 0 ? MBIM_IPS0_VID : session_id);
+}
+
+/*****************************************************************************/
+
+static NetlinkMessage *
+netlink_message_new_link (guint vlan_id,
+ gchar *ifname,
+ guint base_if_index)
+{
+ NetlinkMessage *msg;
+ guint linkinfo_pos, datainfo_pos;
+ struct rtattr info;
+
+ msg = mbim_helpers_netlink_message_new (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
+ mbim_helpers_netlink_append_attribute_uint32 (msg, IFLA_LINK, base_if_index);
+ mbim_helpers_netlink_append_attribute_string (msg, IFLA_IFNAME, ifname);
+
+ /* Store the position of the next attribute to adjust its length later. */
+ linkinfo_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg);
+ mbim_helpers_netlink_append_attribute_nested (msg, IFLA_LINKINFO);
+ mbim_helpers_netlink_append_attribute_string (msg, IFLA_INFO_KIND, VLAN_DATA_TYPE);
+
+ /* Store the position of the next attribute to adjust its length later. */
+ datainfo_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg);
+ mbim_helpers_netlink_append_attribute_nested (msg, IFLA_INFO_DATA);
+ mbim_helpers_netlink_append_attribute_uint16 (msg, IFLA_VLAN_ID, vlan_id);
+
+ /* Use memcpy to preserve byte alignment */
+ memcpy (&info, (char *) msg->data + datainfo_pos, sizeof (struct rtattr));
+ info.rta_len = msg->len - datainfo_pos;
+ memcpy ((char *) msg->data + datainfo_pos, &info, sizeof (struct rtattr));
+
+ memcpy (&info, (char *) msg->data + linkinfo_pos, sizeof (struct rtattr));
+ info.rta_len = msg->len - linkinfo_pos;
+ memcpy ((char *) msg->data + linkinfo_pos, &info, sizeof (struct rtattr));
+
+ return msg;
+}
+
+/*****************************************************************************/
+
+static gboolean
+mbim_net_port_manager_wdm_list_links (MbimNetPortManager *self,
+ const gchar *base_ifname,
+ GPtrArray **out_links,
+ GError **error)
+{
+ g_autoptr(GFile) sysfs_file = NULL;
+ g_autofree gchar *sysfs_path = NULL;
+
+ sysfs_path = g_strdup_printf ("/sys/class/net/%s", base_ifname);
+ sysfs_file = g_file_new_for_path (sysfs_path);
+
+ return mbim_helpers_list_links_wdm (sysfs_file, NULL, NULL, out_links, error);
+}
+
+/*****************************************************************************/
+
+typedef struct {
+ guint session_id;
+ guint vlan_id;
+ gchar *ifname;
+} AddLinkContext;
+
+static void
+add_link_context_free (AddLinkContext *ctx)
+{
+ g_free (ctx->ifname);
+ g_free (ctx);
+}
+
+static gchar *
+mbim_net_port_manager_wdm_add_link_finish (MbimNetPortManager *self,
+ guint *session_id,
+ GAsyncResult *res,
+ GError **error)
+{
+ AddLinkContext *ctx;
+
+ ctx = g_task_get_task_data (G_TASK (res));
+
+ if (!g_task_propagate_boolean (G_TASK (res), error)) {
+ g_prefix_error (error, "Failed to add link with session id %d: ",
+ ctx->session_id);
+ return NULL;
+ }
+
+ *session_id = ctx->session_id;
+ return g_steal_pointer (&ctx->ifname);
+}
+
+static void
+mbim_net_port_manager_wdm_add_link (MbimNetPortManager *self,
+ guint session_id,
+ const gchar *base_ifname,
+ const gchar *ifname_prefix,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ NetlinkMessage *msg;
+ NetlinkTransaction *tr;
+ GTask *task;
+ GError *error = NULL;
+ gssize bytes_sent;
+ guint base_if_index;
+ AddLinkContext *ctx;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ ctx = g_new0 (AddLinkContext, 1);
+ ctx->session_id = session_id;
+ g_task_set_task_data (task, ctx, (GDestroyNotify) add_link_context_free);
+
+ if (ctx->session_id == MBIM_DEVICE_SESSION_ID_AUTOMATIC) {
+ if (!mbim_net_port_manager_util_get_first_free_session_id (ifname_prefix, &ctx->session_id)) {
+ g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
+ "Failed to find an available session ID");
+ g_object_unref (task);
+ return;
+ }
+ g_debug ("Using dynamic session ID %u", ctx->session_id);
+ } else
+ g_debug ("Using static session ID %u", ctx->session_id);
+
+ /* validate interface to use */
+ if (g_strcmp0 (mbim_net_port_manager_peek_iface (self),
+ base_ifname) != 0) {
+ g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
+ "Invalid network interface %s: expected %s",
+ base_ifname, mbim_net_port_manager_peek_iface (self));
+ g_object_unref (task);
+ return;
+ }
+
+ base_if_index = if_nametoindex (base_ifname);
+ if (!base_if_index) {
+ g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
+ "%s interface is not available",
+ base_ifname);
+ g_object_unref (task);
+ return;
+ }
+
+ ctx->ifname = mbim_net_port_manager_util_session_id_to_ifname (ifname_prefix, ctx->session_id);
+ ctx->vlan_id = session_id_to_vlan_id (ctx->session_id);
+ g_debug ("Using ifname '%s' and vlan id %u", ctx->ifname, ctx->vlan_id);
+
+ msg = netlink_message_new_link (ctx->vlan_id, ctx->ifname, base_if_index);
+
+ /* The task ownership is transferred to the transaction. */
+ tr = mbim_helpers_netlink_transaction_new (mbim_net_port_manager_peek_current_sequence_id (MBIM_NET_PORT_MANAGER (self)),
+ mbim_net_port_manager_peek_transactions (MBIM_NET_PORT_MANAGER (self)),
+ msg, timeout, task);
+
+ bytes_sent = g_socket_send (mbim_net_port_manager_peek_socket (MBIM_NET_PORT_MANAGER (self)),
+ (const gchar *) msg->data,
+ msg->len,
+ cancellable,
+ &error);
+ mbim_helpers_netlink_message_free (msg);
+
+ if (bytes_sent < 0)
+ mbim_helpers_netlink_transaction_complete_with_error (tr,
+ mbim_net_port_manager_peek_transactions (MBIM_NET_PORT_MANAGER (self)),
+ error);
+
+ g_object_unref (task);
+}
+
+/*****************************************************************************/
+
+MbimNetPortManagerWdm *
+mbim_net_port_manager_wdm_new (const gchar *iface,
+ GError **error)
+{
+ MbimNetPortManagerWdm *self;
+ gint socket_fd;
+ GSocket *gsocket;
+ GError *inner_error = NULL;
+
+ socket_fd = socket (AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+ if (socket_fd < 0) {
+ g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
+ "Failed to create netlink socket");
+ return NULL;
+ }
+
+ gsocket = g_socket_new_from_fd (socket_fd, &inner_error);
+ if (inner_error) {
+ g_debug ("Could not create socket: %s", inner_error->message);
+ close (socket_fd);
+ g_propagate_error (error, inner_error);
+ return NULL;
+ }
+
+ self = g_object_new (MBIM_TYPE_NET_PORT_MANAGER_WDM, NULL);
+ mbim_net_port_manager_common_setup (MBIM_NET_PORT_MANAGER (self), iface, gsocket);
+
+ return self;
+}
+
+static void
+mbim_net_port_manager_wdm_init (MbimNetPortManagerWdm *self)
+{
+}
+
+static void
+mbim_net_port_manager_wdm_class_init (MbimNetPortManagerWdmClass *klass)
+{
+ MbimNetPortManagerClass *net_port_manager_class = MBIM_NET_PORT_MANAGER_CLASS (klass);
+
+ net_port_manager_class->list_links = mbim_net_port_manager_wdm_list_links;
+ net_port_manager_class->add_link = mbim_net_port_manager_wdm_add_link;
+ net_port_manager_class->add_link_finish = mbim_net_port_manager_wdm_add_link_finish;
+}
diff --git a/src/libmbim-glib/mbim-net-port-manager-wdm.h b/src/libmbim-glib/mbim-net-port-manager-wdm.h
new file mode 100644
index 0000000..42aeaae
--- /dev/null
+++ b/src/libmbim-glib/mbim-net-port-manager-wdm.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * libmbim-glib -- GLib/GIO based library to control MBIM devices
+ *
+ * Copyright (C) 2022 Daniele Palmas <dnlplm@gmail.com>
+ *
+ * Based on previous work:
+ * Copyright (C) 2020-2021 Eric Caruso <ejcaruso@chromium.org>
+ * Copyright (C) 2020-2021 Andrew Lassalle <andrewlassalle@chromium.org>
+ * Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#ifndef _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_WDM_H_
+#define _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_WDM_H_
+
+#include <gio/gio.h>
+#include <glib-object.h>
+
+#define MBIM_TYPE_NET_PORT_MANAGER_WDM (mbim_net_port_manager_wdm_get_type ())
+#define MBIM_NET_PORT_MANAGER_WDM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MBIM_TYPE_NET_PORT_MANAGER_WDM, MbimNetPortManagerWdm))
+#define MBIM_NET_PORT_MANAGER_WDM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MBIM_TYPE_NET_PORT_MANAGER_WDM, MbimNetPortManagerWdmClass))
+#define MBIM_IS_NET_PORT_MANAGER_WDM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MBIM_TYPE_NET_PORT_MANAGER_WDM))
+#define MBIM_IS_NET_PORT_MANAGER_WDM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MBIM_TYPE_NET_PORT_MANAGER_WDM))
+#define MBIM_NET_PORT_MANAGER_WDM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MBIM_TYPE_NET_PORT_MANAGER_WDM, MbimNetPortManagerWdmClass))
+
+typedef struct _MbimNetPortManagerWdm MbimNetPortManagerWdm;
+typedef struct _MbimNetPortManagerWdmClass MbimNetPortManagerWdmClass;
+
+struct _MbimNetPortManagerWdm {
+ MbimNetPortManager parent;
+};
+
+struct _MbimNetPortManagerWdmClass {
+ MbimNetPortManagerClass parent;
+};
+
+GType mbim_net_port_manager_wdm_get_type (void);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimNetPortManagerWdm, g_object_unref)
+
+MbimNetPortManagerWdm *mbim_net_port_manager_wdm_new (const gchar *iface,
+ GError **error);
+
+#endif /* _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_WDM_H_ */
diff --git a/src/libmbim-glib/mbim-net-port-manager.c b/src/libmbim-glib/mbim-net-port-manager.c
index 5958660..ef4a38a 100644
--- a/src/libmbim-glib/mbim-net-port-manager.c
+++ b/src/libmbim-glib/mbim-net-port-manager.c
@@ -14,10 +14,6 @@
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
-#include <net/if_arp.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <string.h>
#include "mbim-device.h"
#include "mbim-helpers.h"
@@ -25,7 +21,7 @@
#include "mbim-net-port-manager.h"
#include "mbim-helpers-netlink.h"
-G_DEFINE_TYPE (MbimNetPortManager, mbim_net_port_manager, G_TYPE_OBJECT)
+G_DEFINE_ABSTRACT_TYPE (MbimNetPortManager, mbim_net_port_manager, G_TYPE_OBJECT)
struct _MbimNetPortManagerPrivate {
gchar *iface;
@@ -39,237 +35,123 @@ struct _MbimNetPortManagerPrivate {
GHashTable *transactions;
};
-/* alternative VLAN for IP session 0 if not untagged */
-#define MBIM_IPS0_VID 4094
-
-#define VLAN_DATA_TYPE "vlan"
-
/*****************************************************************************/
-static gchar *
-session_id_to_ifname (const gchar *ifname_prefix,
- guint session_id)
+void
+mbim_net_port_manager_add_link (MbimNetPortManager *self,
+ guint session_id,
+ const gchar *base_ifname,
+ const gchar *ifname_prefix,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- /*
- * Link names are in the form <PREFIX>.<SESSION ID> */
- return g_strdup_printf ("%s%u", ifname_prefix, session_id);
+ MBIM_NET_PORT_MANAGER_GET_CLASS (self)->add_link (self,
+ session_id,
+ base_ifname,
+ ifname_prefix,
+ timeout,
+ cancellable,
+ callback,
+ user_data);
}
-/*****************************************************************************/
-
-static guint
-session_id_to_vlan_id (guint session_id)
+gchar *
+mbim_net_port_manager_add_link_finish (MbimNetPortManager *self,
+ guint *session_id,
+ GAsyncResult *res,
+ GError **error)
{
- /* VLAN ID 4094 is an alternative mapping of MBIM session 0. If you create
- * a subinterface with this ID then it will take over the session 0 traffic
- * and no packets go untagged anymore. */
- return (session_id == 0 ? MBIM_IPS0_VID : session_id);
+ return MBIM_NET_PORT_MANAGER_GET_CLASS (self)->add_link_finish (self, session_id, res, error);
}
-/*****************************************************************************/
-
-static NetlinkMessage *
-netlink_message_new_link (guint vlan_id,
- gchar *ifname,
- guint base_if_index)
+void
+mbim_net_port_manager_del_link (MbimNetPortManager *self,
+ const gchar *ifname,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- NetlinkMessage *msg;
- guint linkinfo_pos, datainfo_pos;
- struct rtattr info;
-
- msg = mbim_helpers_netlink_message_new (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
- mbim_helpers_netlink_append_attribute_uint32 (msg, IFLA_LINK, base_if_index);
- mbim_helpers_netlink_append_attribute_string (msg, IFLA_IFNAME, ifname);
-
- /* Store the position of the next attribute to adjust its length later. */
- linkinfo_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg);
- mbim_helpers_netlink_append_attribute_nested (msg, IFLA_LINKINFO);
- mbim_helpers_netlink_append_attribute_string (msg, IFLA_INFO_KIND, VLAN_DATA_TYPE);
-
- /* Store the position of the next attribute to adjust its length later. */
- datainfo_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg);
- mbim_helpers_netlink_append_attribute_nested (msg, IFLA_INFO_DATA);
- mbim_helpers_netlink_append_attribute_uint16 (msg, IFLA_VLAN_ID, vlan_id);
-
- /* Use memcpy to preserve byte alignment */
- memcpy (&info, (char *) msg->data + datainfo_pos, sizeof (struct rtattr));
- info.rta_len = msg->len - datainfo_pos;
- memcpy ((char *) msg->data + datainfo_pos, &info, sizeof (struct rtattr));
-
- memcpy (&info, (char *) msg->data + linkinfo_pos, sizeof (struct rtattr));
- info.rta_len = msg->len - linkinfo_pos;
- memcpy ((char *) msg->data + linkinfo_pos, &info, sizeof (struct rtattr));
-
- return msg;
+ MBIM_NET_PORT_MANAGER_GET_CLASS (self)->del_link (self,
+ ifname,
+ timeout,
+ cancellable,
+ callback,
+ user_data);
}
-static NetlinkMessage *
-netlink_message_del_link (guint ifindex)
+gboolean
+mbim_net_port_manager_del_link_finish (MbimNetPortManager *self,
+ GAsyncResult *res,
+ GError **error)
{
- NetlinkMessage *msg;
-
- g_assert (ifindex != 0);
-
- msg = mbim_helpers_netlink_message_new (RTM_DELLINK, 0);
- mbim_helpers_netlink_get_message_header (msg)->ifreq.ifi_index = ifindex;
-
- return msg;
+ return MBIM_NET_PORT_MANAGER_GET_CLASS (self)->del_link_finish (self, res, error);
}
-/*****************************************************************************/
-
-static gboolean
-get_first_free_session_id (MbimNetPortManager *self,
- const gchar *ifname_prefix,
- guint *session_id)
+void
+mbim_net_port_manager_del_all_links (MbimNetPortManager *self,
+ const gchar *base_ifname,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- guint i;
-
- /* The minimum session id is really 0 (MBIM_DEVICE_SESSION_ID_MIN), but
- * when we have to automatically allocate a new session id we'll start at
- * 1, because 0 is also used by the non-muxed setup. */
- for (i = 1; i <= MBIM_DEVICE_SESSION_ID_MAX; i++) {
- g_autofree gchar *ifname = NULL;
-
- ifname = session_id_to_ifname (ifname_prefix, i);
- if (!if_nametoindex (ifname)) {
- *session_id = i;
- return TRUE;
- }
- }
-
- return FALSE;
+ MBIM_NET_PORT_MANAGER_GET_CLASS (self)->del_all_links (self,
+ base_ifname,
+ cancellable,
+ callback,
+ user_data);
}
-/*****************************************************************************/
-
-typedef struct {
- guint session_id;
- guint vlan_id;
- gchar *ifname;
-} AddLinkContext;
-
-static void
-add_link_context_free (AddLinkContext *ctx)
+gboolean
+mbim_net_port_manager_del_all_links_finish (MbimNetPortManager *self,
+ GAsyncResult *res,
+ GError **error)
{
- g_free (ctx->ifname);
- g_free (ctx);
+ return MBIM_NET_PORT_MANAGER_GET_CLASS (self)->del_all_links_finish (self, res, error);
}
-gchar *
-mbim_net_port_manager_add_link_finish (MbimNetPortManager *self,
- guint *session_id,
- GAsyncResult *res,
- GError **error)
+gboolean
+mbim_net_port_manager_list_links (MbimNetPortManager *self,
+ const gchar *base_ifname,
+ GPtrArray **out_links,
+ GError **error)
{
- AddLinkContext *ctx;
-
- ctx = g_task_get_task_data (G_TASK (res));
+ return MBIM_NET_PORT_MANAGER_GET_CLASS (self)->list_links (self, base_ifname, out_links, error);
+}
- if (!g_task_propagate_boolean (G_TASK (res), error)) {
- g_prefix_error (error, "Failed to add link with session id %d: ",
- ctx->session_id);
- return NULL;
- }
+/*****************************************************************************/
+/* Default implementations */
- *session_id = ctx->session_id;
- return g_steal_pointer (&ctx->ifname);
+static gboolean
+net_port_manager_del_link_finish (MbimNetPortManager *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
}
-void
-mbim_net_port_manager_add_link (MbimNetPortManager *self,
- guint session_id,
- const gchar *base_ifname,
- const gchar *ifname_prefix,
- guint timeout,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+static NetlinkMessage *
+netlink_message_del_link (guint ifindex)
{
- NetlinkMessage *msg;
- NetlinkTransaction *tr;
- GTask *task;
- GError *error = NULL;
- gssize bytes_sent;
- guint base_if_index;
- AddLinkContext *ctx;
-
- task = g_task_new (self, cancellable, callback, user_data);
-
- ctx = g_new0 (AddLinkContext, 1);
- ctx->session_id = session_id;
- g_task_set_task_data (task, ctx, (GDestroyNotify) add_link_context_free);
-
- if (ctx->session_id == MBIM_DEVICE_SESSION_ID_AUTOMATIC) {
- if (!get_first_free_session_id (self, ifname_prefix, &ctx->session_id)) {
- g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
- "Failed to find an available session ID");
- g_object_unref (task);
- return;
- }
- g_debug ("Using dynamic session ID %u", ctx->session_id);
- } else
- g_debug ("Using static session ID %u", ctx->session_id);
-
- /* validate interface to use */
- if (g_strcmp0 (self->priv->iface, base_ifname) != 0) {
- g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
- "Invalid network interface %s: expected %s",
- base_ifname, self->priv->iface);
- g_object_unref (task);
- return;
- }
-
- base_if_index = if_nametoindex (base_ifname);
- if (!base_if_index) {
- g_task_return_new_error (task, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
- "%s interface is not available",
- base_ifname);
- g_object_unref (task);
- return;
- }
-
- ctx->ifname = session_id_to_ifname (ifname_prefix, ctx->session_id);
- ctx->vlan_id = session_id_to_vlan_id (ctx->session_id);
- g_debug ("Using ifname '%s' and vlan id %u", ctx->ifname, ctx->vlan_id);
-
- msg = netlink_message_new_link (ctx->vlan_id, ctx->ifname, base_if_index);
-
- /* The task ownership is transferred to the transaction. */
- tr = mbim_helpers_netlink_transaction_new (&self->priv->current_sequence_id,
- self->priv->transactions,
- msg,
- timeout,
- task);
-
- bytes_sent = g_socket_send (self->priv->socket,
- (const gchar *) msg->data,
- msg->len,
- cancellable,
- &error);
- mbim_helpers_netlink_message_free (msg);
+ NetlinkMessage *msg;
- if (bytes_sent < 0)
- mbim_helpers_netlink_transaction_complete_with_error (tr, self->priv->transactions, error);
+ g_assert (ifindex != 0);
- g_object_unref (task);
-}
+ msg = mbim_helpers_netlink_message_new (RTM_DELLINK, 0);
+ mbim_helpers_netlink_get_message_header (msg)->ifreq.ifi_index = ifindex;
-gboolean
-mbim_net_port_manager_del_link_finish (MbimNetPortManager *self,
- GAsyncResult *res,
- GError **error)
-{
- return g_task_propagate_boolean (G_TASK (res), error);
+ return msg;
}
-void
-mbim_net_port_manager_del_link (MbimNetPortManager *self,
- const gchar *ifname,
- guint timeout,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+static void
+net_port_manager_del_link (MbimNetPortManager *self,
+ const gchar *ifname,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
guint ifindex;
NetlinkMessage *msg;
@@ -310,25 +192,6 @@ mbim_net_port_manager_del_link (MbimNetPortManager *self,
g_object_unref (task);
}
-/*****************************************************************************/
-
-gboolean
-mbim_net_port_manager_list_links (MbimNetPortManager *self,
- const gchar *base_ifname,
- GPtrArray **out_links,
- GError **error)
-{
- g_autoptr(GFile) sysfs_file = NULL;
- g_autofree gchar *sysfs_path = NULL;
-
- sysfs_path = g_strdup_printf ("/sys/class/net/%s", base_ifname);
- sysfs_file = g_file_new_for_path (sysfs_path);
-
- return mbim_helpers_list_links (sysfs_file, NULL, NULL, out_links, error);
-}
-
-/*****************************************************************************/
-
typedef struct {
GPtrArray *links;
guint link_i;
@@ -341,10 +204,10 @@ del_all_links_context_free (DelAllLinksContext *ctx)
g_slice_free (DelAllLinksContext, ctx);
}
-gboolean
-mbim_net_port_manager_del_all_links_finish (MbimNetPortManager *self,
- GAsyncResult *res,
- GError **error)
+static gboolean
+net_port_manager_del_all_links_finish (MbimNetPortManager *self,
+ GAsyncResult *res,
+ GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
@@ -353,8 +216,8 @@ static void delete_next_link (GTask *task);
static void
port_manager_del_link_ready (MbimNetPortManager *self,
- GAsyncResult *res,
- GTask *task)
+ GAsyncResult *res,
+ GTask *task)
{
DelAllLinksContext *ctx;
GError *error = NULL;
@@ -390,16 +253,16 @@ delete_next_link (GTask *task)
g_ptr_array_index (ctx->links, 0),
5,
g_task_get_cancellable (task),
- (GAsyncReadyCallback)port_manager_del_link_ready,
+ (GAsyncReadyCallback) port_manager_del_link_ready,
task);
}
-void
-mbim_net_port_manager_del_all_links (MbimNetPortManager *self,
- const gchar *base_ifname,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+static void
+net_port_manager_del_all_links (MbimNetPortManager *self,
+ const gchar *base_ifname,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
GTask *task;
DelAllLinksContext *ctx;
@@ -420,31 +283,35 @@ mbim_net_port_manager_del_all_links (MbimNetPortManager *self,
/*****************************************************************************/
-MbimNetPortManager *
-mbim_net_port_manager_new (const gchar *iface,
- GError **error)
+GHashTable *
+mbim_net_port_manager_peek_transactions (MbimNetPortManager *self)
{
- MbimNetPortManager *self;
- gint socket_fd;
- GSocket *gsocket;
- GError *inner_error = NULL;
-
- socket_fd = socket (AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
- if (socket_fd < 0) {
- g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
- "Failed to create netlink socket");
- return NULL;
- }
+ return self->priv->transactions;
+}
- gsocket = g_socket_new_from_fd (socket_fd, &inner_error);
- if (inner_error) {
- g_debug ("Could not create socket: %s", inner_error->message);
- close (socket_fd);
- g_propagate_error (error, inner_error);
- return NULL;
- }
+gchar *
+mbim_net_port_manager_peek_iface (MbimNetPortManager *self)
+{
+ return self->priv->iface;
+}
- self = g_object_new (MBIM_TYPE_NET_PORT_MANAGER, NULL);
+guint *
+mbim_net_port_manager_peek_current_sequence_id (MbimNetPortManager *self)
+{
+ return &self->priv->current_sequence_id;
+}
+
+GSocket *
+mbim_net_port_manager_peek_socket (MbimNetPortManager *self)
+{
+ return self->priv->socket;
+}
+
+void
+mbim_net_port_manager_common_setup (MbimNetPortManager *self,
+ const gchar *iface,
+ GSocket *gsocket)
+{
self->priv->iface = g_strdup (iface);
self->priv->socket = gsocket;
self->priv->current_sequence_id = 0;
@@ -456,13 +323,44 @@ mbim_net_port_manager_new (const gchar *iface,
mbim_helpers_netlink_set_callback (&self->priv->source,
self->priv->socket,
self->priv->transactions);
+}
+
+gchar *
+mbim_net_port_manager_util_session_id_to_ifname (const gchar *ifname_prefix,
+ guint session_id)
+{
+ /* Link names are in the form <PREFIX>.<SESSION ID> */
+ return g_strdup_printf ("%s%u", ifname_prefix, session_id);
+}
+
+gboolean
+mbim_net_port_manager_util_get_first_free_session_id (const gchar *ifname_prefix,
+ guint *session_id)
+{
+ guint i;
+
+ /* The minimum session id is really 0 (MBIM_DEVICE_SESSION_ID_MIN), but
+ * when we have to automatically allocate a new session id we'll start at
+ * 1, because 0 is also used by the non-muxed setup. */
+ for (i = 1; i <= MBIM_DEVICE_SESSION_ID_MAX; i++) {
+ g_autofree gchar *ifname = NULL;
- return self;
+ ifname = mbim_net_port_manager_util_session_id_to_ifname (ifname_prefix, i);
+ if (!if_nametoindex (ifname)) {
+ *session_id = i;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
}
+/*****************************************************************************/
+
static void
mbim_net_port_manager_init (MbimNetPortManager *self)
{
+ /* Initialize private data */
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MBIM_TYPE_NET_PORT_MANAGER, MbimNetPortManagerPrivate);
}
@@ -486,4 +384,9 @@ mbim_net_port_manager_class_init (MbimNetPortManagerClass *klass)
g_type_class_add_private (object_class, sizeof (MbimNetPortManagerPrivate));
object_class->finalize = finalize;
+
+ klass->del_link = net_port_manager_del_link;
+ klass->del_link_finish = net_port_manager_del_link_finish;
+ klass->del_all_links = net_port_manager_del_all_links;
+ klass->del_all_links_finish = net_port_manager_del_all_links_finish;
}
diff --git a/src/libmbim-glib/mbim-net-port-manager.h b/src/libmbim-glib/mbim-net-port-manager.h
index 45027b8..095e637 100644
--- a/src/libmbim-glib/mbim-net-port-manager.h
+++ b/src/libmbim-glib/mbim-net-port-manager.h
@@ -28,24 +28,58 @@ typedef struct _MbimNetPortManagerClass MbimNetPortManagerClass;
typedef struct _MbimNetPortManagerPrivate MbimNetPortManagerPrivate;
struct _MbimNetPortManager {
- GObject parent;
+ GObject parent;
MbimNetPortManagerPrivate *priv;
};
struct _MbimNetPortManagerClass {
GObjectClass parent;
+
+ gboolean (* list_links) (MbimNetPortManager *self,
+ const gchar *base_ifname,
+ GPtrArray **out_links,
+ GError **error);
+
+ void (* add_link) (MbimNetPortManager *self,
+ guint session_id,
+ const gchar *base_ifname,
+ const gchar *ifname_prefix,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gchar * (* add_link_finish) (MbimNetPortManager *self,
+ guint *session_id,
+ GAsyncResult *res,
+ GError **error);
+
+ void (* del_link) (MbimNetPortManager *self,
+ const gchar *ifname,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (* del_link_finish) (MbimNetPortManager *self,
+ GAsyncResult *res,
+ GError **error);
+
+ void (* del_all_links) (MbimNetPortManager *self,
+ const gchar *base_ifname,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (* del_all_links_finish) (MbimNetPortManager *self,
+ GAsyncResult *res,
+ GError **error);
};
GType mbim_net_port_manager_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimNetPortManager, g_object_unref)
-MbimNetPortManager *mbim_net_port_manager_new (const gchar *iface,
- GError **error);
-
-gboolean mbim_net_port_manager_list_links (MbimNetPortManager *self,
- const gchar *base_ifname,
- GPtrArray **out_links,
- GError **error);
+gboolean mbim_net_port_manager_list_links (MbimNetPortManager *self,
+ const gchar *base_ifname,
+ GPtrArray **out_links,
+ GError **error);
void mbim_net_port_manager_add_link (MbimNetPortManager *self,
guint session_id,
@@ -79,4 +113,22 @@ gboolean mbim_net_port_manager_del_all_links_finish (MbimNetPortManager *self
GAsyncResult *res,
GError **error);
+GHashTable *mbim_net_port_manager_peek_transactions (MbimNetPortManager *self);
+
+gchar *mbim_net_port_manager_peek_iface (MbimNetPortManager *self);
+
+guint *mbim_net_port_manager_peek_current_sequence_id (MbimNetPortManager *self);
+
+GSocket *mbim_net_port_manager_peek_socket (MbimNetPortManager *self);
+
+void mbim_net_port_manager_common_setup (MbimNetPortManager *self,
+ const gchar *iface,
+ GSocket *gsocket);
+
+gchar *mbim_net_port_manager_util_session_id_to_ifname (const gchar *ifname_prefix,
+ guint session_id);
+
+gboolean mbim_net_port_manager_util_get_first_free_session_id (const gchar *ifname_prefix,
+ guint *session_id);
+
#endif /* _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_H_ */
diff --git a/src/libmbim-glib/meson.build b/src/libmbim-glib/meson.build
index a182866..6c3774e 100644
--- a/src/libmbim-glib/meson.build
+++ b/src/libmbim-glib/meson.build
@@ -42,6 +42,7 @@ sources = files(
'mbim-helpers-netlink.c',
'mbim-message.c',
'mbim-net-port-manager.c',
+ 'mbim-net-port-manager-wdm.c',
'mbim-proxy.c',
'mbim-proxy-helpers.c',
'mbim-utils.c',