summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniele Palmas <dnlplm@gmail.com>2022-06-05 22:30:38 +0200
committerDaniele Palmas <dnlplm@gmail.com>2022-08-05 18:00:12 +0200
commit601e0dcfea4ec6e56b7dfe2bfbc70ae49a4f3e3a (patch)
tree74c891a6c52263bbb84a90440f98d71108773aee
parent462325fb113b5de67a784135612ef9ee33cc8f8e (diff)
downloadlibmbim-601e0dcfea4ec6e56b7dfe2bfbc70ae49a4f3e3a.tar.gz
libmbim-glib,net-port-manager: refactor netlink implementation to new files
In preparation for wwan support.
-rw-r--r--docs/reference/libmbim-glib/meson.build1
-rw-r--r--src/libmbim-glib/mbim-helpers-netlink.c298
-rw-r--r--src/libmbim-glib/mbim-helpers-netlink.h98
-rw-r--r--src/libmbim-glib/mbim-net-port-manager.c355
-rw-r--r--src/libmbim-glib/meson.build1
5 files changed, 441 insertions, 312 deletions
diff --git a/docs/reference/libmbim-glib/meson.build b/docs/reference/libmbim-glib/meson.build
index 3dcc67e..29c6adc 100644
--- a/docs/reference/libmbim-glib/meson.build
+++ b/docs/reference/libmbim-glib/meson.build
@@ -12,6 +12,7 @@ src_dirs = [
private_headers = [
'mbim-helpers.h',
+ 'mbim-helpers-netlink.h',
'mbim-message-private.h',
'mbim-net-port-manager.h',
]
diff --git a/src/libmbim-glib/mbim-helpers-netlink.c b/src/libmbim-glib/mbim-helpers-netlink.c
new file mode 100644
index 0000000..9a14086
--- /dev/null
+++ b/src/libmbim-glib/mbim-helpers-netlink.c
@@ -0,0 +1,298 @@
+/* -*- 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 <sys/socket.h>
+
+#include "mbim-helpers-netlink.h"
+
+/*****************************************************************************/
+/*
+ * Netlink message construction functions
+ */
+
+NetlinkHeader *
+mbim_helpers_netlink_get_message_header (NetlinkMessage *msg)
+{
+ return (NetlinkHeader *) (msg->data);
+}
+
+guint
+mbim_helpers_netlink_get_pos_of_next_attr (NetlinkMessage *msg)
+{
+ return NLMSG_ALIGN (msg->len);
+}
+
+static void
+append_netlink_attribute (NetlinkMessage *msg,
+ gushort type,
+ gconstpointer value,
+ gushort len)
+{
+ guint attr_len;
+ guint old_len;
+ guint next_attr_rel_pos;
+ char *next_attr_abs_pos;
+ struct rtattr new_attr;
+
+ /* Expand the buffer to hold the new attribute */
+ attr_len = RTA_ALIGN (RTA_LENGTH (len));
+ old_len = msg->len;
+ next_attr_rel_pos = mbim_helpers_netlink_get_pos_of_next_attr (msg);
+
+ g_byte_array_set_size (msg, next_attr_rel_pos + attr_len);
+ /* fill new bytes with zero, since some padding is added between attributes. */
+ memset ((char *) msg->data + old_len, 0, msg->len - old_len);
+
+ new_attr.rta_type = type;
+ new_attr.rta_len = RTA_LENGTH (len);
+ next_attr_abs_pos = (char *) msg->data + next_attr_rel_pos;
+ memcpy (next_attr_abs_pos, &new_attr, sizeof (struct rtattr));
+
+ if (value)
+ memcpy (RTA_DATA (next_attr_abs_pos), value, len);
+
+ /* Update the total netlink message length */
+ mbim_helpers_netlink_get_message_header (msg)->msghdr.nlmsg_len = msg->len;
+}
+
+void
+mbim_helpers_netlink_append_attribute_nested (NetlinkMessage *msg,
+ gushort type)
+{
+ append_netlink_attribute (msg, type, NULL, 0);
+}
+
+void
+mbim_helpers_netlink_append_attribute_string (NetlinkMessage *msg,
+ gushort type,
+ const gchar *value)
+{
+ append_netlink_attribute (msg, type, value, strlen (value));
+}
+
+void
+mbim_helpers_netlink_append_attribute_uint16 (NetlinkMessage *msg,
+ gushort type,
+ guint16 value)
+{
+ append_netlink_attribute (msg, type, &value, sizeof (value));
+}
+
+void
+mbim_helpers_netlink_append_attribute_uint32 (NetlinkMessage *msg,
+ gushort type,
+ guint32 value)
+{
+ append_netlink_attribute (msg, type, &value, sizeof (value));
+}
+
+NetlinkMessage *
+mbim_helpers_netlink_message_new (guint16 type,
+ guint16 extra_flags)
+{
+ NetlinkMessage *msg;
+ NetlinkHeader *hdr;
+
+ int size = sizeof (NetlinkHeader);
+
+ msg = g_byte_array_new ();
+ g_byte_array_set_size (msg, size);
+ memset ((char *) msg->data, 0, size);
+
+ hdr = mbim_helpers_netlink_get_message_header (msg);
+ hdr->msghdr.nlmsg_len = msg->len;
+ hdr->msghdr.nlmsg_type = type;
+ hdr->msghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | extra_flags;
+ hdr->ifreq.ifi_family = AF_UNSPEC;
+ return msg;
+}
+
+void
+mbim_helpers_netlink_message_free (NetlinkMessage *msg)
+{
+ g_byte_array_unref (msg);
+}
+
+/*****************************************************************************/
+/*
+ * Transaction management functions
+ */
+
+static gboolean
+transaction_timed_out (NetlinkTransaction *tr,
+ GHashTable *transactions)
+{
+ GTask *task;
+ guint32 sequence_id;
+
+ task = g_steal_pointer (&tr->completion_task);
+ sequence_id = tr->sequence_id;
+
+ g_hash_table_remove (transactions,
+ GUINT_TO_POINTER (tr->sequence_id));
+
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_TIMED_OUT,
+ "Netlink message with sequence ID %u timed out",
+ sequence_id);
+
+ g_object_unref (task);
+ return G_SOURCE_REMOVE;
+}
+
+void
+mbim_helpers_netlink_transaction_complete_with_error (NetlinkTransaction *tr,
+ GHashTable *transactions,
+ GError *error)
+{
+ GTask *task;
+
+ task = g_steal_pointer (&tr->completion_task);
+
+ g_hash_table_remove (transactions,
+ GUINT_TO_POINTER (tr->sequence_id));
+
+ g_task_return_error (task, error);
+ g_object_unref (task);
+}
+
+void
+mbim_helpers_netlink_transaction_complete (NetlinkTransaction *tr,
+ GHashTable *transactions,
+ gint saved_errno)
+{
+ GTask *task;
+ guint32 sequence_id;
+
+ task = g_steal_pointer (&tr->completion_task);
+ sequence_id = tr->sequence_id;
+
+ g_hash_table_remove (transactions,
+ GUINT_TO_POINTER (tr->sequence_id));
+
+ if (!saved_errno) {
+ g_task_return_boolean (task, TRUE);
+ } else {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ g_io_error_from_errno (saved_errno),
+ "Netlink message with transaction %u failed: %s",
+ sequence_id,
+ g_strerror (saved_errno));
+ }
+
+ g_object_unref (task);
+}
+
+void
+mbim_helpers_netlink_transaction_free (NetlinkTransaction *tr)
+{
+ g_assert (tr->completion_task == NULL);
+ g_source_destroy (tr->timeout_source);
+ g_source_unref (tr->timeout_source);
+ g_slice_free (NetlinkTransaction, tr);
+}
+
+NetlinkTransaction *
+mbim_helpers_netlink_transaction_new (guint *sequence_id,
+ GHashTable *transactions,
+ NetlinkMessage *msg,
+ guint timeout,
+ GTask *task)
+{
+ NetlinkTransaction *tr;
+
+ tr = g_slice_new0 (NetlinkTransaction);
+ tr->sequence_id = ++(*sequence_id);
+ mbim_helpers_netlink_get_message_header (msg)->msghdr.nlmsg_seq = tr->sequence_id;
+ if (timeout) {
+ tr->timeout_source = g_timeout_source_new_seconds (timeout);
+ g_source_set_callback (tr->timeout_source,
+ (GSourceFunc) transaction_timed_out,
+ tr,
+ NULL);
+ g_source_attach (tr->timeout_source,
+ g_main_context_get_thread_default ());
+ }
+ tr->completion_task = g_object_ref (task);
+
+ g_hash_table_insert (transactions,
+ GUINT_TO_POINTER (tr->sequence_id),
+ tr);
+ return tr;
+}
+
+/*****************************************************************************/
+
+static gboolean
+netlink_message_cb (GSocket *socket,
+ GIOCondition condition,
+ GHashTable *transactions)
+{
+ GError *error = NULL;
+ gchar buf[512];
+ int bytes_received;
+ unsigned int buffer_len;
+ struct nlmsghdr *hdr;
+
+ if (condition & G_IO_HUP || condition & G_IO_ERR) {
+ g_warning ("[netlink] socket connection closed.");
+ return G_SOURCE_REMOVE;
+ }
+
+ bytes_received = g_socket_receive (socket, buf, sizeof (buf), NULL, &error);
+
+ if (bytes_received < 0) {
+ g_warning ("[netlink] socket i/o failure: %s", error->message);
+ g_error_free (error);
+ return G_SOURCE_REMOVE;
+ }
+
+ buffer_len = (unsigned int ) bytes_received;
+ for (hdr = (struct nlmsghdr *) buf; NLMSG_OK (hdr, buffer_len);
+ NLMSG_NEXT (hdr, buffer_len)) {
+ NetlinkTransaction *tr;
+ struct nlmsgerr *err;
+
+ if (hdr->nlmsg_type != NLMSG_ERROR)
+ continue;
+
+ tr = g_hash_table_lookup (transactions,
+ GUINT_TO_POINTER (hdr->nlmsg_seq));
+ if (!tr)
+ continue;
+
+ err = NLMSG_DATA (buf);
+ mbim_helpers_netlink_transaction_complete (tr, transactions, err->error);
+ }
+ return G_SOURCE_CONTINUE;
+}
+
+void
+mbim_helpers_netlink_set_callback (GSource **source,
+ GSocket *socket,
+ GHashTable *transactions)
+{
+ *source = g_socket_create_source (socket,
+ G_IO_IN | G_IO_ERR | G_IO_HUP,
+ NULL);
+ g_source_set_callback (*source,
+ (GSourceFunc) netlink_message_cb,
+ transactions,
+ NULL);
+ g_source_attach (*source, g_main_context_get_thread_default ());
+}
diff --git a/src/libmbim-glib/mbim-helpers-netlink.h b/src/libmbim-glib/mbim-helpers-netlink.h
new file mode 100644
index 0000000..3c73b32
--- /dev/null
+++ b/src/libmbim-glib/mbim-helpers-netlink.h
@@ -0,0 +1,98 @@
+/* -*- 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_HELPERS_NETLINK_H_
+#define _LIBMBIM_GLIB_MBIM_HELPERS_NETLINK_H_
+
+#if !defined (LIBMBIM_GLIB_COMPILATION)
+#error "This is a private header!!"
+#endif
+
+#include <glib.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+typedef GByteArray NetlinkMessage;
+
+typedef struct {
+ struct nlmsghdr msghdr;
+ struct ifinfomsg ifreq;
+} NetlinkHeader;
+
+G_GNUC_INTERNAL
+NetlinkHeader *mbim_helpers_netlink_get_message_header (NetlinkMessage *msg);
+
+G_GNUC_INTERNAL
+guint mbim_helpers_netlink_get_pos_of_next_attr (NetlinkMessage *msg);
+
+G_GNUC_INTERNAL
+void mbim_helpers_netlink_append_attribute_nested (NetlinkMessage *msg,
+ gushort type);
+
+G_GNUC_INTERNAL
+void mbim_helpers_netlink_append_attribute_string (NetlinkMessage *msg,
+ gushort type,
+ const gchar *value);
+
+G_GNUC_INTERNAL
+void mbim_helpers_netlink_append_attribute_uint16 (NetlinkMessage *msg,
+ gushort type,
+ guint16 value);
+
+G_GNUC_INTERNAL
+void mbim_helpers_netlink_append_attribute_uint32 (NetlinkMessage *msg,
+ gushort type,
+ guint32 value);
+
+G_GNUC_INTERNAL
+NetlinkMessage *mbim_helpers_netlink_message_new (guint16 type,
+ guint16 extra_flags);
+
+G_GNUC_INTERNAL
+void mbim_helpers_netlink_message_free (NetlinkMessage *msg);
+
+typedef struct {
+ guint32 sequence_id;
+ GSource *timeout_source;
+ GTask *completion_task;
+} NetlinkTransaction;
+
+G_GNUC_INTERNAL
+void mbim_helpers_netlink_transaction_complete_with_error (NetlinkTransaction *tr,
+ GHashTable *transactions,
+ GError *error);
+
+G_GNUC_INTERNAL
+void mbim_helpers_netlink_transaction_complete (NetlinkTransaction *tr,
+ GHashTable *transactions,
+ gint saved_errno);
+
+G_GNUC_INTERNAL
+void mbim_helpers_netlink_transaction_free (NetlinkTransaction *tr);
+
+G_GNUC_INTERNAL
+NetlinkTransaction *mbim_helpers_netlink_transaction_new (guint *sequence_id,
+ GHashTable *transactions,
+ NetlinkMessage *msg,
+ guint timeout,
+ GTask *task);
+
+G_GNUC_INTERNAL
+void mbim_helpers_netlink_set_callback (GSource **source,
+ GSocket *socket,
+ GHashTable *transactions);
+
+G_END_DECLS
+
+#endif /* _LIBMBIM_GLIB_MBIM_HELPERS_NETLINK_H_ */
diff --git a/src/libmbim-glib/mbim-net-port-manager.c b/src/libmbim-glib/mbim-net-port-manager.c
index 032ed3f..5958660 100644
--- a/src/libmbim-glib/mbim-net-port-manager.c
+++ b/src/libmbim-glib/mbim-net-port-manager.c
@@ -23,6 +23,7 @@
#include "mbim-helpers.h"
#include "mbim-error-types.h"
#include "mbim-net-port-manager.h"
+#include "mbim-helpers-netlink.h"
G_DEFINE_TYPE (MbimNetPortManager, mbim_net_port_manager, G_TYPE_OBJECT)
@@ -55,232 +56,6 @@ session_id_to_ifname (const gchar *ifname_prefix,
}
/*****************************************************************************/
-/*
- * Netlink message construction functions
- */
-
-typedef GByteArray NetlinkMessage;
-
-typedef struct {
- struct nlmsghdr msghdr;
- struct ifinfomsg ifreq;
-} NetlinkHeader;
-
-static NetlinkHeader *
-netlink_message_header (NetlinkMessage *msg)
-{
- return (NetlinkHeader *) (msg->data);
-}
-
-static guint
-get_pos_of_next_attr (NetlinkMessage *msg)
-{
- return NLMSG_ALIGN (msg->len);
-}
-
-static void
-append_netlink_attribute (NetlinkMessage *msg,
- gushort type,
- gconstpointer value,
- gushort len)
-{
- guint attr_len;
- guint old_len;
- guint next_attr_rel_pos;
- char *next_attr_abs_pos;
- struct rtattr new_attr;
-
- /* Expand the buffer to hold the new attribute */
- attr_len = RTA_ALIGN (RTA_LENGTH (len));
- old_len = msg->len;
- next_attr_rel_pos = get_pos_of_next_attr (msg);
-
- g_byte_array_set_size (msg, next_attr_rel_pos + attr_len);
- /* fill new bytes with zero, since some padding is added between attributes. */
- memset ((char *) msg->data + old_len, 0, msg->len - old_len);
-
- new_attr.rta_type = type;
- new_attr.rta_len = RTA_LENGTH (len);
- next_attr_abs_pos = (char *) msg->data + next_attr_rel_pos;
- memcpy (next_attr_abs_pos, &new_attr, sizeof (struct rtattr));
-
- if (value)
- memcpy (RTA_DATA (next_attr_abs_pos), value, len);
-
- /* Update the total netlink message length */
- netlink_message_header (msg)->msghdr.nlmsg_len = msg->len;
-}
-
-static void
-append_netlink_attribute_nested (NetlinkMessage *msg,
- gushort type)
-{
- append_netlink_attribute (msg, type, NULL, 0);
-}
-
-static void
-append_netlink_attribute_string (NetlinkMessage *msg,
- gushort type,
- const gchar *value)
-{
- append_netlink_attribute (msg, type, value, strlen (value));
-}
-
-static void
-append_netlink_attribute_uint16 (NetlinkMessage *msg,
- gushort type,
- guint16 value)
-{
- append_netlink_attribute (msg, type, &value, sizeof (value));
-}
-
-static void
-append_netlink_attribute_uint32 (NetlinkMessage *msg,
- gushort type,
- guint32 value)
-{
- append_netlink_attribute (msg, type, &value, sizeof (value));
-}
-
-static NetlinkMessage *
-netlink_message_new (guint16 type,
- guint16 extra_flags)
-{
- NetlinkMessage *msg;
- NetlinkHeader *hdr;
-
- int size = sizeof (NetlinkHeader);
-
- msg = g_byte_array_new ();
- g_byte_array_set_size (msg, size);
- memset ((char *) msg->data, 0, size);
-
- hdr = netlink_message_header (msg);
- hdr->msghdr.nlmsg_len = msg->len;
- hdr->msghdr.nlmsg_type = type;
- hdr->msghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | extra_flags;
- hdr->ifreq.ifi_family = AF_UNSPEC;
- return msg;
-}
-
-static void
-netlink_message_free (NetlinkMessage *msg)
-{
- g_byte_array_unref (msg);
-}
-
-/*****************************************************************************/
-
-typedef struct {
- MbimNetPortManager *manager;
- guint32 sequence_id;
- GSource *timeout_source;
- GTask *completion_task;
-} Transaction;
-
-static gboolean
-transaction_timed_out (Transaction *tr)
-{
- GTask *task;
- guint32 sequence_id;
-
- task = g_steal_pointer (&tr->completion_task);
- sequence_id = tr->sequence_id;
-
- g_hash_table_remove (tr->manager->priv->transactions,
- GUINT_TO_POINTER (tr->sequence_id));
-
- g_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_TIMED_OUT,
- "Netlink message with sequence ID %u timed out",
- sequence_id);
-
- g_object_unref (task);
- return G_SOURCE_REMOVE;
-}
-
-static void
-transaction_complete_with_error (Transaction *tr,
- GError *error)
-{
- GTask *task;
-
- task = g_steal_pointer (&tr->completion_task);
-
- g_hash_table_remove (tr->manager->priv->transactions,
- GUINT_TO_POINTER (tr->sequence_id));
-
- g_task_return_error (task, error);
- g_object_unref (task);
-}
-
-static void
-transaction_complete (Transaction *tr,
- gint saved_errno)
-{
- GTask *task;
- guint32 sequence_id;
-
- task = g_steal_pointer (&tr->completion_task);
- sequence_id = tr->sequence_id;
-
- g_hash_table_remove (tr->manager->priv->transactions,
- GUINT_TO_POINTER (tr->sequence_id));
-
- if (!saved_errno) {
- g_task_return_boolean (task, TRUE);
- } else {
- g_task_return_new_error (task,
- G_IO_ERROR,
- g_io_error_from_errno (saved_errno),
- "Netlink message with transaction %u failed: %s",
- sequence_id,
- g_strerror (saved_errno));
- }
-
- g_object_unref (task);
-}
-
-static void
-transaction_free (Transaction *tr)
-{
- g_assert (tr->completion_task == NULL);
- g_source_destroy (tr->timeout_source);
- g_source_unref (tr->timeout_source);
- g_slice_free (Transaction, tr);
-}
-
-static Transaction *
-transaction_new (MbimNetPortManager *manager,
- NetlinkMessage *msg,
- guint timeout,
- GTask *task)
-{
- Transaction *tr;
-
- tr = g_slice_new0 (Transaction);
- tr->manager = manager;
- tr->sequence_id = ++manager->priv->current_sequence_id;
- netlink_message_header (msg)->msghdr.nlmsg_seq = tr->sequence_id;
- if (timeout) {
- tr->timeout_source = g_timeout_source_new_seconds (timeout);
- g_source_set_callback (tr->timeout_source,
- (GSourceFunc) transaction_timed_out,
- tr,
- NULL);
- g_source_attach (tr->timeout_source,
- g_main_context_get_thread_default ());
- }
- tr->completion_task = g_object_ref (task);
-
- g_hash_table_insert (manager->priv->transactions,
- GUINT_TO_POINTER (tr->sequence_id),
- tr);
- return tr;
-}
-
-/*****************************************************************************/
static guint
session_id_to_vlan_id (guint session_id)
@@ -302,19 +77,19 @@ netlink_message_new_link (guint vlan_id,
guint linkinfo_pos, datainfo_pos;
struct rtattr info;
- msg = netlink_message_new (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
- append_netlink_attribute_uint32 (msg, IFLA_LINK, base_if_index);
- append_netlink_attribute_string (msg, IFLA_IFNAME, ifname);
+ 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 = get_pos_of_next_attr (msg);
- append_netlink_attribute_nested (msg, IFLA_LINKINFO);
- append_netlink_attribute_string (msg, IFLA_INFO_KIND, VLAN_DATA_TYPE);
+ 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 = get_pos_of_next_attr (msg);
- append_netlink_attribute_nested (msg, IFLA_INFO_DATA);
- append_netlink_attribute_uint16 (msg, IFLA_VLAN_ID, vlan_id);
+ 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));
@@ -335,8 +110,8 @@ netlink_message_del_link (guint ifindex)
g_assert (ifindex != 0);
- msg = netlink_message_new (RTM_DELLINK, 0);
- netlink_message_header (msg)->ifreq.ifi_index = ifindex;
+ msg = mbim_helpers_netlink_message_new (RTM_DELLINK, 0);
+ mbim_helpers_netlink_get_message_header (msg)->ifreq.ifi_index = ifindex;
return msg;
}
@@ -344,52 +119,6 @@ netlink_message_del_link (guint ifindex)
/*****************************************************************************/
static gboolean
-netlink_message_cb (GSocket *socket,
- GIOCondition condition,
- MbimNetPortManager *self)
-{
- GError *error = NULL;
- gchar buf[512];
- int bytes_received;
- unsigned int buffer_len;
- struct nlmsghdr *hdr;
-
- if (condition & G_IO_HUP || condition & G_IO_ERR) {
- g_warning ("[netlink] socket connection closed.");
- return G_SOURCE_REMOVE;
- }
-
- bytes_received = g_socket_receive (socket, buf, sizeof (buf), NULL, &error);
-
- if (bytes_received < 0) {
- g_warning ("[netlink] socket i/o failure: %s", error->message);
- g_error_free (error);
- return G_SOURCE_REMOVE;
- }
-
- buffer_len = (unsigned int ) bytes_received;
- for (hdr = (struct nlmsghdr *) buf; NLMSG_OK (hdr, buffer_len);
- NLMSG_NEXT (hdr, buffer_len)) {
- Transaction *tr;
- struct nlmsgerr *err;
-
- if (hdr->nlmsg_type != NLMSG_ERROR)
- continue;
-
- tr = g_hash_table_lookup (self->priv->transactions,
- GUINT_TO_POINTER (hdr->nlmsg_seq));
- if (!tr)
- continue;
-
- err = NLMSG_DATA (buf);
- transaction_complete (tr, err->error);
- }
- return G_SOURCE_CONTINUE;
-}
-
-/*****************************************************************************/
-
-static gboolean
get_first_free_session_id (MbimNetPortManager *self,
const gchar *ifname_prefix,
guint *session_id)
@@ -457,13 +186,13 @@ mbim_net_port_manager_add_link (MbimNetPortManager *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- NetlinkMessage *msg;
- Transaction *tr;
- GTask *task;
- GError *error = NULL;
- gssize bytes_sent;
- guint base_if_index;
- AddLinkContext *ctx;
+ 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);
@@ -507,17 +236,21 @@ mbim_net_port_manager_add_link (MbimNetPortManager *self,
msg = netlink_message_new_link (ctx->vlan_id, ctx->ifname, base_if_index);
/* The task ownership is transferred to the transaction. */
- tr = transaction_new (self, msg, timeout, task);
+ 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);
- netlink_message_free (msg);
+ mbim_helpers_netlink_message_free (msg);
if (bytes_sent < 0)
- transaction_complete_with_error (tr, error);
+ mbim_helpers_netlink_transaction_complete_with_error (tr, self->priv->transactions, error);
g_object_unref (task);
}
@@ -538,12 +271,12 @@ mbim_net_port_manager_del_link (MbimNetPortManager *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- guint ifindex;
- NetlinkMessage *msg;
- Transaction *tr;
- GTask *task;
- GError *error = NULL;
- gssize bytes_sent;
+ guint ifindex;
+ NetlinkMessage *msg;
+ NetlinkTransaction *tr;
+ GTask *task;
+ GError *error = NULL;
+ gssize bytes_sent;
task = g_task_new (self, cancellable, callback, user_data);
@@ -558,17 +291,21 @@ mbim_net_port_manager_del_link (MbimNetPortManager *self,
msg = netlink_message_del_link (ifindex);
/* The task ownership is transferred to the transaction. */
- tr = transaction_new (self, msg, timeout, task);
+ 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);
- netlink_message_free (msg);
+ mbim_helpers_netlink_message_free (msg);
if (bytes_sent < 0)
- transaction_complete_with_error (tr, error);
+ mbim_helpers_netlink_transaction_complete_with_error (tr, self->priv->transactions, error);
g_object_unref (task);
}
@@ -710,21 +447,15 @@ mbim_net_port_manager_new (const gchar *iface,
self = g_object_new (MBIM_TYPE_NET_PORT_MANAGER, NULL);
self->priv->iface = g_strdup (iface);
self->priv->socket = gsocket;
- self->priv->source = g_socket_create_source (self->priv->socket,
- G_IO_IN | G_IO_ERR | G_IO_HUP,
- NULL);
- g_source_set_callback (self->priv->source,
- (GSourceFunc) netlink_message_cb,
- self,
- NULL);
- g_source_attach (self->priv->source, g_main_context_get_thread_default ());
-
self->priv->current_sequence_id = 0;
self->priv->transactions =
g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
- (GDestroyNotify) transaction_free);
+ (GDestroyNotify) mbim_helpers_netlink_transaction_free);
+ mbim_helpers_netlink_set_callback (&self->priv->source,
+ self->priv->socket,
+ self->priv->transactions);
return self;
}
diff --git a/src/libmbim-glib/meson.build b/src/libmbim-glib/meson.build
index dee6368..a182866 100644
--- a/src/libmbim-glib/meson.build
+++ b/src/libmbim-glib/meson.build
@@ -39,6 +39,7 @@ sources = files(
'mbim-compat.c',
'mbim-device.c',
'mbim-helpers.c',
+ 'mbim-helpers-netlink.c',
'mbim-message.c',
'mbim-net-port-manager.c',
'mbim-proxy.c',