summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniele Palmas <dnlplm@gmail.com>2022-06-21 10:00:07 +0200
committerDaniele Palmas <dnlplm@gmail.com>2022-08-05 18:00:12 +0200
commit85a0849cb87912000afda852a2566dbea3cb623e (patch)
treecedc248c2962da5b3f7458b9efacbd2247a0b8a5
parentdc6901b625679a8fab72c2df11fd55d4fafef64d (diff)
downloadlibmbim-85a0849cb87912000afda852a2566dbea3cb623e.tar.gz
libmbim-glib,net-port-manager: new subclass for wwan
-rw-r--r--docs/reference/libmbim-glib/meson.build1
-rw-r--r--meson.build4
-rw-r--r--src/libmbim-glib/kernel/wwan.h34
-rw-r--r--src/libmbim-glib/mbim-device.c16
-rw-r--r--src/libmbim-glib/mbim-helpers-netlink.c13
-rw-r--r--src/libmbim-glib/mbim-helpers-netlink.h5
-rw-r--r--src/libmbim-glib/mbim-helpers.c67
-rw-r--r--src/libmbim-glib/mbim-helpers.h8
-rw-r--r--src/libmbim-glib/mbim-net-port-manager-wwan.c244
-rw-r--r--src/libmbim-glib/mbim-net-port-manager-wwan.h43
-rw-r--r--src/libmbim-glib/meson.build1
11 files changed, 427 insertions, 9 deletions
diff --git a/docs/reference/libmbim-glib/meson.build b/docs/reference/libmbim-glib/meson.build
index 803b939..335d860 100644
--- a/docs/reference/libmbim-glib/meson.build
+++ b/docs/reference/libmbim-glib/meson.build
@@ -16,6 +16,7 @@ private_headers = [
'mbim-message-private.h',
'mbim-net-port-manager.h',
'mbim-net-port-manager-wdm.h',
+ 'mbim-net-port-manager-wwan.h',
'wwan.h',
]
diff --git a/meson.build b/meson.build
index bf3428a..00ad600 100644
--- a/meson.build
+++ b/meson.build
@@ -118,6 +118,10 @@ endif
add_project_arguments(common_flags + cc_flags, language: 'c')
+if cc.check_header('linux/wwan.h')
+ add_project_arguments(['-DHAVE_WWAN_KERNEL_HEADER'], language: 'c')
+endif
+
glib_version = '2.56'
glib_dep = dependency('glib-2.0', version: '>= ' + glib_version)
diff --git a/src/libmbim-glib/kernel/wwan.h b/src/libmbim-glib/kernel/wwan.h
new file mode 100644
index 0000000..61ab8b1
--- /dev/null
+++ b/src/libmbim-glib/kernel/wwan.h
@@ -0,0 +1,34 @@
+
+#ifndef _MBIM_WWAN_H
+#define _MBIM_WWAN_H
+
+/* safe guard to avoid redefining WWAN symbols if
+ * the system provided kernel or libc headers already
+ * define them: HAVE_WWAN_KERNEL_HEADER is set by
+ * meson build system according to linux/wwan.h presence */
+#if !defined HAVE_WWAN_KERNEL_HEADER
+
+enum {
+ IFLA_WWAN_UNSPEC,
+ IFLA_WWAN_LINK_ID, /* u32 */
+
+ __IFLA_WWAN_MAX
+};
+#define IFLA_WWAN_MAX (__IFLA_WWAN_MAX - 1)
+
+/* Both IFLA_WWAN_MAX and enum entry IFLA_PARENT_DEV_NAME got included
+ * in the same kernel version 5.14-rc1 */
+enum {
+ /* device (sysfs) name as parent, used instead
+ * of IFLA_LINK where there's no parent netdev
+ */
+ IFLA_PARENT_DEV_NAME = 56,
+};
+
+#else
+
+#include <linux/wwan.h>
+
+#endif /* HAVE_WWAN_KERNEL_HEADER */
+
+#endif /* _MBIM_WWAN_H */
diff --git a/src/libmbim-glib/mbim-device.c b/src/libmbim-glib/mbim-device.c
index bfc4084..2177b0b 100644
--- a/src/libmbim-glib/mbim-device.c
+++ b/src/libmbim-glib/mbim-device.c
@@ -40,6 +40,7 @@
#include "mbim-proxy-control.h"
#include "mbim-net-port-manager.h"
#include "mbim-net-port-manager-wdm.h"
+#include "mbim-net-port-manager-wwan.h"
#include "mbim-basic-connect.h"
#include "mbim-ms-basic-connect-extensions.h"
@@ -586,15 +587,12 @@ setup_net_port_manager (MbimDevice *self,
if (self->priv->net_port_manager)
return TRUE;
- /* For now we only support link management with cdc-mbim */
reload_wwan_iface_name (self);
- if (!self->priv->wwan_iface) {
- g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_UNSUPPORTED,
- "Link management is unsupported");
- return FALSE;
- }
-
- self->priv->net_port_manager = MBIM_NET_PORT_MANAGER (mbim_net_port_manager_wdm_new (self->priv->wwan_iface, error));
+ if (!self->priv->wwan_iface)
+ /* If wwan_iface is not set wwan subsystem is probably in use */
+ self->priv->net_port_manager = MBIM_NET_PORT_MANAGER (mbim_net_port_manager_wwan_new (error));
+ else
+ 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;
}
@@ -736,7 +734,7 @@ mbim_device_delete_link (MbimDevice *self,
g_assert (self->priv->net_port_manager);
mbim_net_port_manager_del_link (self->priv->net_port_manager,
- ifname,
+ ifname,
5, /* timeout */
cancellable,
(GAsyncReadyCallback) device_del_link_ready,
diff --git a/src/libmbim-glib/mbim-helpers-netlink.c b/src/libmbim-glib/mbim-helpers-netlink.c
index 9a14086..a0e69a7 100644
--- a/src/libmbim-glib/mbim-helpers-netlink.c
+++ b/src/libmbim-glib/mbim-helpers-netlink.c
@@ -14,6 +14,11 @@
#include <linux/if_link.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+
+/* This is a built-in file, not provided by the kernel headers,
+ * used to add wwan symbols if not available */
+#include <kernel/wwan.h>
+
#include <sys/socket.h>
#include "mbim-helpers-netlink.h"
@@ -84,6 +89,14 @@ mbim_helpers_netlink_append_attribute_string (NetlinkMessage *msg,
}
void
+mbim_helpers_netlink_append_attribute_string_null (NetlinkMessage *msg,
+ gushort type,
+ const gchar *value)
+{
+ append_netlink_attribute (msg, type, value, strlen (value) + 1);
+}
+
+void
mbim_helpers_netlink_append_attribute_uint16 (NetlinkMessage *msg,
gushort type,
guint16 value)
diff --git a/src/libmbim-glib/mbim-helpers-netlink.h b/src/libmbim-glib/mbim-helpers-netlink.h
index 3c73b32..eff18e3 100644
--- a/src/libmbim-glib/mbim-helpers-netlink.h
+++ b/src/libmbim-glib/mbim-helpers-netlink.h
@@ -46,6 +46,11 @@ void mbim_helpers_netlink_append_attribute_string (NetlinkMessage *msg,
const gchar *value);
G_GNUC_INTERNAL
+void mbim_helpers_netlink_append_attribute_string_null (NetlinkMessage *msg,
+ gushort type,
+ const gchar *value);
+
+G_GNUC_INTERNAL
void mbim_helpers_netlink_append_attribute_uint16 (NetlinkMessage *msg,
gushort type,
guint16 value);
diff --git a/src/libmbim-glib/mbim-helpers.c b/src/libmbim-glib/mbim-helpers.c
index 3a37556..bec5302 100644
--- a/src/libmbim-glib/mbim-helpers.c
+++ b/src/libmbim-glib/mbim-helpers.c
@@ -163,6 +163,73 @@ mbim_helpers_list_links_wdm (GFile *sysfs_file,
return TRUE;
}
+/*****************************************************************************/
+
+gboolean
+mbim_helpers_list_links_wwan (const gchar *base_ifname,
+ GFile *sysfs_file,
+ GCancellable *cancellable,
+ GPtrArray *previous_links,
+ GPtrArray **out_links,
+ GError **error)
+{
+ g_autofree gchar *sysfs_path = NULL;
+ g_autoptr(GFileEnumerator) direnum = NULL;
+ g_autoptr(GPtrArray) links = NULL;
+
+ direnum = g_file_enumerate_children (sysfs_file,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ cancellable,
+ error);
+ if (!direnum)
+ return FALSE;
+
+ sysfs_path = g_file_get_path (sysfs_file);
+ links = g_ptr_array_new_with_free_func (g_free);
+
+ while (TRUE) {
+ GFileInfo *info;
+ g_autofree gchar *filename = NULL;
+ g_autofree gchar *link_path = NULL;
+ g_autofree gchar *real_path = NULL;
+ g_autofree gchar *basename = NULL;
+
+ if (!g_file_enumerator_iterate (direnum, &info, NULL, cancellable, error))
+ return FALSE;
+ if (!info)
+ break;
+
+ filename = g_file_info_get_attribute_as_string (info, G_FILE_ATTRIBUTE_STANDARD_NAME);
+ if (!g_strcmp0(base_ifname, filename))
+ continue;
+
+ link_path = g_strdup_printf ("%s/%s", sysfs_path, filename);
+ real_path = realpath (link_path, NULL);
+ if (!real_path)
+ continue;
+
+ basename = g_path_get_basename (real_path);
+
+ /* skip interface if it was already known */
+ if (previous_links && g_ptr_array_find_with_equal_func (previous_links, basename, g_str_equal, NULL))
+ continue;
+
+ g_ptr_array_add (links, g_steal_pointer (&basename));
+ }
+
+ if (!links || !links->len) {
+ *out_links = NULL;
+ return TRUE;
+ }
+
+ g_ptr_array_sort (links, (GCompareFunc) g_ascii_strcasecmp);
+ *out_links = g_steal_pointer (&links);
+ return TRUE;
+}
+
+/*****************************************************************************/
+
#if !GLIB_CHECK_VERSION(2,54,0)
gboolean
diff --git a/src/libmbim-glib/mbim-helpers.h b/src/libmbim-glib/mbim-helpers.h
index b314e0e..8059dfe 100644
--- a/src/libmbim-glib/mbim-helpers.h
+++ b/src/libmbim-glib/mbim-helpers.h
@@ -37,6 +37,14 @@ gboolean mbim_helpers_list_links_wdm (GFile *sysfs_file,
GPtrArray **out_links,
GError **error);
+G_GNUC_INTERNAL
+gboolean mbim_helpers_list_links_wwan (const gchar *base_ifname,
+ GFile *sysfs_file,
+ GCancellable *cancellable,
+ GPtrArray *previous_links,
+ GPtrArray **out_links,
+ GError **error);
+
#if !GLIB_CHECK_VERSION(2,54,0)
/* Pointer Array lookup with a GEqualFunc, imported from GLib 2.54 */
diff --git a/src/libmbim-glib/mbim-net-port-manager-wwan.c b/src/libmbim-glib/mbim-net-port-manager-wwan.c
new file mode 100644
index 0000000..2b00d37
--- /dev/null
+++ b/src/libmbim-glib/mbim-net-port-manager-wwan.c
@@ -0,0 +1,244 @@
+/* -*- 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>
+
+/* This is a built-in file, not provided by the kernel headers,
+ * used to add wwan symbols if not available */
+#include <kernel/wwan.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-wwan.h"
+#include "mbim-helpers-netlink.h"
+
+G_DEFINE_TYPE (MbimNetPortManagerWwan, mbim_net_port_manager_wwan, MBIM_TYPE_NET_PORT_MANAGER)
+
+#define WWAN_DATA_TYPE "wwan"
+
+/*****************************************************************************/
+
+static NetlinkMessage *
+netlink_message_new_link (guint link_id,
+ gchar *ifname,
+ const gchar *base_if_name)
+{
+ NetlinkMessage *msg;
+ guint linkinfo_pos, datainfo_pos;
+ struct rtattr info;
+
+ msg = mbim_helpers_netlink_message_new (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
+ /* IFLA_PARENT_DEV_NAME has type NLA_NUL_STRING */
+ mbim_helpers_netlink_append_attribute_string_null (msg, IFLA_PARENT_DEV_NAME, base_if_name);
+ 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, WWAN_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_uint32 (msg, IFLA_WWAN_LINK_ID, link_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_wwan_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/device/net", base_ifname);
+ sysfs_file = g_file_new_for_path (sysfs_path);
+
+ return mbim_helpers_list_links_wwan (base_ifname, sysfs_file, NULL, NULL, out_links, error);
+}
+
+/*****************************************************************************/
+
+typedef struct {
+ guint session_id;
+ guint link_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_wwan_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_wwan_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);
+
+ 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->link_id = ctx->session_id;
+ g_debug ("Using ifname '%s' and link id %u", ctx->ifname, ctx->link_id);
+
+ msg = netlink_message_new_link (ctx->link_id, ctx->ifname, base_ifname);
+
+ /* 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);
+}
+
+/*****************************************************************************/
+
+MbimNetPortManagerWwan *
+mbim_net_port_manager_wwan_new (GError **error)
+{
+ MbimNetPortManagerWwan *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_WWAN, NULL);
+
+ mbim_net_port_manager_common_setup (MBIM_NET_PORT_MANAGER (self), NULL, gsocket);
+
+ return self;
+}
+
+static void
+mbim_net_port_manager_wwan_init (MbimNetPortManagerWwan *self)
+{
+}
+
+static void
+mbim_net_port_manager_wwan_class_init (MbimNetPortManagerWwanClass *klass)
+{
+ MbimNetPortManagerClass *net_port_manager_class = MBIM_NET_PORT_MANAGER_CLASS (klass);
+
+ net_port_manager_class->list_links = mbim_net_port_manager_wwan_list_links;
+ net_port_manager_class->add_link = mbim_net_port_manager_wwan_add_link;
+ net_port_manager_class->add_link_finish = mbim_net_port_manager_wwan_add_link_finish;
+}
diff --git a/src/libmbim-glib/mbim-net-port-manager-wwan.h b/src/libmbim-glib/mbim-net-port-manager-wwan.h
new file mode 100644
index 0000000..38f1bb3
--- /dev/null
+++ b/src/libmbim-glib/mbim-net-port-manager-wwan.h
@@ -0,0 +1,43 @@
+/* -*- 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_WWAN_H_
+#define _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_WWAN_H_
+
+#include <gio/gio.h>
+#include <glib-object.h>
+
+#define MBIM_TYPE_NET_PORT_MANAGER_WWAN (mbim_net_port_manager_wwan_get_type ())
+#define MBIM_NET_PORT_MANAGER_WWAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MBIM_TYPE_NET_PORT_MANAGER_WWAN, MbimNetPortManagerWwan))
+#define MBIM_NET_PORT_MANAGER_WWAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MBIM_TYPE_NET_PORT_MANAGER_WWAN, MbimNetPortManagerWwanClass))
+#define MBIM_IS_NET_PORT_MANAGER_WWAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MBIM_TYPE_NET_PORT_MANAGER_WWAN))
+#define MBIM_IS_NET_PORT_MANAGER_WWAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MBIM_TYPE_NET_PORT_MANAGER_WWAN))
+#define MBIM_NET_PORT_MANAGER_WWAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MBIM_TYPE_NET_PORT_MANAGER_WWAN, MbimNetPortManagerWwanClass))
+
+typedef struct _MbimNetPortManagerWwan MbimNetPortManagerWwan;
+typedef struct _MbimNetPortManagerWwanClass MbimNetPortManagerWwanClass;
+
+struct _MbimNetPortManagerWwan {
+ MbimNetPortManager parent;
+};
+
+struct _MbimNetPortManagerWwanClass {
+ MbimNetPortManagerClass parent;
+};
+
+GType mbim_net_port_manager_wwan_get_type (void);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MbimNetPortManagerWwan, g_object_unref)
+
+MbimNetPortManagerWwan *mbim_net_port_manager_wwan_new (GError **error);
+
+#endif /* _LIBMBIM_GLIB_MBIM_NET_PORT_MANAGER_WWAN_H_ */
diff --git a/src/libmbim-glib/meson.build b/src/libmbim-glib/meson.build
index 6c3774e..148935c 100644
--- a/src/libmbim-glib/meson.build
+++ b/src/libmbim-glib/meson.build
@@ -43,6 +43,7 @@ sources = files(
'mbim-message.c',
'mbim-net-port-manager.c',
'mbim-net-port-manager-wdm.c',
+ 'mbim-net-port-manager-wwan.c',
'mbim-proxy.c',
'mbim-proxy-helpers.c',
'mbim-utils.c',