mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-08 11:19:16 +02:00
platform/netlink: merge branch 'th/netlink' (#67)
https://github.com/NetworkManager/NetworkManager/pull/67
This commit is contained in:
commit
3d987fe2db
12 changed files with 1882 additions and 376 deletions
|
|
@ -16,9 +16,6 @@ addons:
|
||||||
- libdbus-1-dev
|
- libdbus-1-dev
|
||||||
- libiw-dev
|
- libiw-dev
|
||||||
- libglib2.0-dev
|
- libglib2.0-dev
|
||||||
- libnl-3-dev
|
|
||||||
- libnl-route-3-dev
|
|
||||||
- libnl-genl-3-dev
|
|
||||||
- libmm-glib-dev
|
- libmm-glib-dev
|
||||||
- ppp
|
- ppp
|
||||||
- ppp-dev
|
- ppp-dev
|
||||||
|
|
@ -43,7 +40,6 @@ addons:
|
||||||
- dbus-x11
|
- dbus-x11
|
||||||
- libjansson4
|
- libjansson4
|
||||||
- libjansson-dev
|
- libjansson-dev
|
||||||
- libnl-3-dev
|
|
||||||
- libndp-dev
|
- libndp-dev
|
||||||
- automake
|
- automake
|
||||||
- dnsmasq
|
- dnsmasq
|
||||||
|
|
|
||||||
|
|
@ -1185,7 +1185,6 @@ src_cppflags = \
|
||||||
-DDHCPCD_PATH=\"$(DHCPCD_PATH)\" \
|
-DDHCPCD_PATH=\"$(DHCPCD_PATH)\" \
|
||||||
\
|
\
|
||||||
$(LIBUDEV_CFLAGS) \
|
$(LIBUDEV_CFLAGS) \
|
||||||
$(LIBNL_CFLAGS) \
|
|
||||||
$(LIBNDP_CFLAGS) \
|
$(LIBNDP_CFLAGS) \
|
||||||
$(LIBPSL_CFLAGS) \
|
$(LIBPSL_CFLAGS) \
|
||||||
$(LIBCURL_CFLAGS) \
|
$(LIBCURL_CFLAGS) \
|
||||||
|
|
@ -1643,7 +1642,6 @@ src_libNetworkManager_la_LIBADD = \
|
||||||
src/libsystemd-nm.la \
|
src/libsystemd-nm.la \
|
||||||
$(GLIB_LIBS) \
|
$(GLIB_LIBS) \
|
||||||
$(LIBUDEV_LIBS) \
|
$(LIBUDEV_LIBS) \
|
||||||
$(LIBNL_LIBS) \
|
|
||||||
$(SYSTEMD_LOGIN_LIBS) \
|
$(SYSTEMD_LOGIN_LIBS) \
|
||||||
$(LIBNDP_LIBS) \
|
$(LIBNDP_LIBS) \
|
||||||
$(DL_LIBS) \
|
$(DL_LIBS) \
|
||||||
|
|
@ -1684,8 +1682,7 @@ src_libNetworkManagerTest_la_LIBADD = \
|
||||||
src/libNetworkManager.la \
|
src/libNetworkManager.la \
|
||||||
$(CODE_COVERAGE_LDFLAGS) \
|
$(CODE_COVERAGE_LDFLAGS) \
|
||||||
$(GLIB_LIBS) \
|
$(GLIB_LIBS) \
|
||||||
$(LIBUDEV_LIBS) \
|
$(LIBUDEV_LIBS)
|
||||||
$(LIBNL_LIBS)
|
|
||||||
|
|
||||||
$(src_libNetworkManagerTest_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
|
$(src_libNetworkManagerTest_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
|
||||||
|
|
||||||
|
|
@ -1726,7 +1723,6 @@ src_nm_iface_helper_LDADD = \
|
||||||
src/libsystemd-nm.la \
|
src/libsystemd-nm.la \
|
||||||
$(GLIB_LIBS) \
|
$(GLIB_LIBS) \
|
||||||
$(LIBUDEV_LIBS) \
|
$(LIBUDEV_LIBS) \
|
||||||
$(LIBNL_LIBS) \
|
|
||||||
$(LIBNDP_LIBS) \
|
$(LIBNDP_LIBS) \
|
||||||
$(DL_LIBS)
|
$(DL_LIBS)
|
||||||
|
|
||||||
|
|
@ -2898,8 +2894,7 @@ src_platform_tests_ldflags = \
|
||||||
src_platform_tests_libadd = \
|
src_platform_tests_libadd = \
|
||||||
src/libNetworkManagerTest.la \
|
src/libNetworkManagerTest.la \
|
||||||
$(GLIB_LIBS) \
|
$(GLIB_LIBS) \
|
||||||
$(LIBUDEV_LIBS) \
|
$(LIBUDEV_LIBS)
|
||||||
$(LIBNL_LIBS)
|
|
||||||
|
|
||||||
check_programs_norun += \
|
check_programs_norun += \
|
||||||
src/platform/tests/monitor
|
src/platform/tests/monitor
|
||||||
|
|
|
||||||
|
|
@ -559,9 +559,6 @@ else
|
||||||
fi
|
fi
|
||||||
AC_SUBST(NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT)
|
AC_SUBST(NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT)
|
||||||
|
|
||||||
# libnl support for the linux platform
|
|
||||||
PKG_CHECK_MODULES(LIBNL, libnl-3.0 >= 3.2.8)
|
|
||||||
|
|
||||||
# uuid library
|
# uuid library
|
||||||
PKG_CHECK_MODULES(UUID, uuid)
|
PKG_CHECK_MODULES(UUID, uuid)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ yum install \
|
||||||
jansson-devel \
|
jansson-devel \
|
||||||
libcurl-devel \
|
libcurl-devel \
|
||||||
libndp-devel \
|
libndp-devel \
|
||||||
libnl3-devel \
|
|
||||||
libpsl-devel \
|
libpsl-devel \
|
||||||
libselinux-devel \
|
libselinux-devel \
|
||||||
libtool \
|
libtool \
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ BUILD_PACKAGES="qemu febootstrap mock rpmdevtools"
|
||||||
ARCH=i386
|
ARCH=i386
|
||||||
ROOT="${ROOT:-"fedora-20-$ARCH"}"
|
ROOT="${ROOT:-"fedora-20-$ARCH"}"
|
||||||
TREE="/var/lib/mock/$ROOT/root"
|
TREE="/var/lib/mock/$ROOT/root"
|
||||||
PACKAGES="kernel passwd git autoconf automake libtool intltool gtk-doc libnl3-devel
|
PACKAGES="kernel passwd git autoconf automake libtool intltool gtk-doc
|
||||||
dbus-glib-devel libuuid-devel nss-devel ppp-devel newt-devel libndp-devel
|
dbus-glib-devel libuuid-devel nss-devel ppp-devel newt-devel libndp-devel
|
||||||
readline-devel
|
readline-devel
|
||||||
gobject-introspection-devel
|
gobject-introspection-devel
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
%global dbus_glib_version 0.100
|
%global dbus_glib_version 0.100
|
||||||
|
|
||||||
%global wireless_tools_version 1:28-0pre9
|
%global wireless_tools_version 1:28-0pre9
|
||||||
%global libnl3_version 3.2.7
|
|
||||||
|
|
||||||
%global ppp_version %(sed -n 's/^#define\\s*VERSION\\s*"\\([^\\s]*\\)"$/\\1/p' %{_includedir}/pppd/patchlevel.h 2>/dev/null | grep . || echo bad)
|
%global ppp_version %(sed -n 's/^#define\\s*VERSION\\s*"\\([^\\s]*\\)"$/\\1/p' %{_includedir}/pppd/patchlevel.h 2>/dev/null | grep . || echo bad)
|
||||||
%global glib2_version %(pkg-config --modversion glib-2.0 2>/dev/null || echo bad)
|
%global glib2_version %(pkg-config --modversion glib-2.0 2>/dev/null || echo bad)
|
||||||
|
|
@ -130,7 +129,6 @@ BuildRequires: glib2-devel >= 2.40.0
|
||||||
BuildRequires: gobject-introspection-devel >= 0.10.3
|
BuildRequires: gobject-introspection-devel >= 0.10.3
|
||||||
BuildRequires: gettext-devel
|
BuildRequires: gettext-devel
|
||||||
BuildRequires: pkgconfig
|
BuildRequires: pkgconfig
|
||||||
BuildRequires: libnl3-devel >= %{libnl3_version}
|
|
||||||
BuildRequires: automake autoconf intltool libtool
|
BuildRequires: automake autoconf intltool libtool
|
||||||
%if %{with ppp}
|
%if %{with ppp}
|
||||||
BuildRequires: ppp-devel >= 2.4.5
|
BuildRequires: ppp-devel >= 2.4.5
|
||||||
|
|
|
||||||
|
|
@ -184,9 +184,6 @@ libudev_dep = dependency('libudev', version: '>= 175')
|
||||||
dbus_dep = dependency('dbus-1', version: '>= 1.1')
|
dbus_dep = dependency('dbus-1', version: '>= 1.1')
|
||||||
libndp_dep = dependency('libndp')
|
libndp_dep = dependency('libndp')
|
||||||
|
|
||||||
# libnl support for the linux platform
|
|
||||||
libnl_dep = dependency('libnl-3.0', version: '>= 3.2.8', required: false)
|
|
||||||
|
|
||||||
jansson_dep = dependency('jansson', version: '>= 2.5', required: false)
|
jansson_dep = dependency('jansson', version: '>= 2.5', required: false)
|
||||||
config_h.set10('WITH_JANSSON', jansson_dep.found())
|
config_h.set10('WITH_JANSSON', jansson_dep.found())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,6 @@ sources = files(
|
||||||
)
|
)
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
libnl_dep,
|
|
||||||
libnmdbus_dep,
|
libnmdbus_dep,
|
||||||
libsystemd_dep,
|
libsystemd_dep,
|
||||||
libudev_dep,
|
libudev_dep,
|
||||||
|
|
@ -170,7 +169,6 @@ sources = files(
|
||||||
deps = [
|
deps = [
|
||||||
dl_dep,
|
dl_dep,
|
||||||
libndp_dep,
|
libndp_dep,
|
||||||
libnl_dep,
|
|
||||||
# FIXME: Some files use introspection/dbus* headers, so
|
# FIXME: Some files use introspection/dbus* headers, so
|
||||||
# this dependency might be needed
|
# this dependency might be needed
|
||||||
#libnmdbus_dep,
|
#libnmdbus_dep,
|
||||||
|
|
@ -252,7 +250,6 @@ network_manager = executable(
|
||||||
deps = [
|
deps = [
|
||||||
dl_dep,
|
dl_dep,
|
||||||
libndp_dep,
|
libndp_dep,
|
||||||
libnl_dep,
|
|
||||||
libudev_dep,
|
libudev_dep,
|
||||||
nm_core_dep
|
nm_core_dep
|
||||||
]
|
]
|
||||||
|
|
@ -279,7 +276,6 @@ if enable_tests
|
||||||
)
|
)
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
libnl_dep,
|
|
||||||
libudev_dep,
|
libudev_dep,
|
||||||
nm_core_dep
|
nm_core_dep
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "nm-linux-platform.h"
|
#include "nm-linux-platform.h"
|
||||||
|
|
||||||
|
#include <poll.h>
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
@ -79,10 +80,6 @@ enum {
|
||||||
|
|
||||||
#define VLAN_FLAG_MVRP 0x8
|
#define VLAN_FLAG_MVRP 0x8
|
||||||
|
|
||||||
/* nm-internal error codes for libnl. Make sure they don't overlap. */
|
|
||||||
#define _NLE_NM_NOBUFS 500
|
|
||||||
#define _NLE_MSG_TRUNC 501
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#define IFQDISCSIZ 32
|
#define IFQDISCSIZ 32
|
||||||
|
|
@ -297,6 +294,7 @@ typedef enum {
|
||||||
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_POLL,
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_POLL,
|
||||||
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT,
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT,
|
||||||
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING,
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING,
|
||||||
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_SETNS,
|
||||||
} WaitForNlResponseResult;
|
} WaitForNlResponseResult;
|
||||||
|
|
||||||
typedef void (*WaitForNlResponseCallback) (NMPlatform *platform,
|
typedef void (*WaitForNlResponseCallback) (NMPlatform *platform,
|
||||||
|
|
@ -951,106 +949,6 @@ _nl_addattr_l (struct nlmsghdr *n,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
_nl_nlmsghdr_to_str (const struct nlmsghdr *hdr, char *buf, gsize len)
|
|
||||||
{
|
|
||||||
const char *b;
|
|
||||||
const char *s;
|
|
||||||
guint flags, flags_before;
|
|
||||||
const char *prefix;
|
|
||||||
|
|
||||||
nm_utils_to_string_buffer_init (&buf, &len);
|
|
||||||
b = buf;
|
|
||||||
|
|
||||||
switch (hdr->nlmsg_type) {
|
|
||||||
case RTM_NEWLINK: s = "RTM_NEWLINK"; break;
|
|
||||||
case RTM_DELLINK: s = "RTM_DELLINK"; break;
|
|
||||||
case RTM_NEWADDR: s = "RTM_NEWADDR"; break;
|
|
||||||
case RTM_DELADDR: s = "RTM_DELADDR"; break;
|
|
||||||
case RTM_NEWROUTE: s = "RTM_NEWROUTE"; break;
|
|
||||||
case RTM_DELROUTE: s = "RTM_DELROUTE"; break;
|
|
||||||
case RTM_NEWQDISC: s = "RTM_NEWQDISC"; break;
|
|
||||||
case RTM_DELQDISC: s = "RTM_DELQDISC"; break;
|
|
||||||
case RTM_NEWTFILTER: s = "RTM_NEWTFILTER"; break;
|
|
||||||
case RTM_DELTFILTER: s = "RTM_DELTFILTER"; break;
|
|
||||||
case NLMSG_NOOP: s = "NLMSG_NOOP"; break;
|
|
||||||
case NLMSG_ERROR: s = "NLMSG_ERROR"; break;
|
|
||||||
case NLMSG_DONE: s = "NLMSG_DONE"; break;
|
|
||||||
case NLMSG_OVERRUN: s = "NLMSG_OVERRUN"; break;
|
|
||||||
default: s = NULL; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s)
|
|
||||||
nm_utils_strbuf_append_str (&buf, &len, s);
|
|
||||||
else
|
|
||||||
nm_utils_strbuf_append (&buf, &len, "(%u)", (unsigned) hdr->nlmsg_type);
|
|
||||||
|
|
||||||
flags = hdr->nlmsg_flags;
|
|
||||||
|
|
||||||
if (!flags) {
|
|
||||||
nm_utils_strbuf_append_str (&buf, &len, ", flags 0");
|
|
||||||
goto flags_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define _F(f, n) \
|
|
||||||
G_STMT_START { \
|
|
||||||
if (NM_FLAGS_ALL (flags, f)) { \
|
|
||||||
flags &= ~(f); \
|
|
||||||
nm_utils_strbuf_append (&buf, &len, "%s%s", prefix, n); \
|
|
||||||
if (!flags) \
|
|
||||||
goto flags_done; \
|
|
||||||
prefix = ","; \
|
|
||||||
} \
|
|
||||||
} G_STMT_END
|
|
||||||
|
|
||||||
prefix = ", flags ";
|
|
||||||
flags_before = flags;
|
|
||||||
_F (NLM_F_REQUEST, "request");
|
|
||||||
_F (NLM_F_MULTI, "multi");
|
|
||||||
_F (NLM_F_ACK, "ack");
|
|
||||||
_F (NLM_F_ECHO, "echo");
|
|
||||||
_F (NLM_F_DUMP_INTR, "dump_intr");
|
|
||||||
_F (0x20 /*NLM_F_DUMP_FILTERED*/, "dump_filtered");
|
|
||||||
|
|
||||||
if (flags_before != flags)
|
|
||||||
prefix = ";";
|
|
||||||
|
|
||||||
switch (hdr->nlmsg_type) {
|
|
||||||
case RTM_NEWLINK:
|
|
||||||
case RTM_NEWADDR:
|
|
||||||
case RTM_NEWROUTE:
|
|
||||||
case RTM_NEWQDISC:
|
|
||||||
case RTM_NEWTFILTER:
|
|
||||||
_F (NLM_F_REPLACE, "replace");
|
|
||||||
_F (NLM_F_EXCL, "excl");
|
|
||||||
_F (NLM_F_CREATE, "create");
|
|
||||||
_F (NLM_F_APPEND, "append");
|
|
||||||
break;
|
|
||||||
case RTM_GETLINK:
|
|
||||||
case RTM_GETADDR:
|
|
||||||
case RTM_GETROUTE:
|
|
||||||
case RTM_DELQDISC:
|
|
||||||
case RTM_DELTFILTER:
|
|
||||||
_F (NLM_F_DUMP, "dump");
|
|
||||||
_F (NLM_F_ROOT, "root");
|
|
||||||
_F (NLM_F_MATCH, "match");
|
|
||||||
_F (NLM_F_ATOMIC, "atomic");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef _F
|
|
||||||
|
|
||||||
if (flags_before != flags)
|
|
||||||
prefix = ";";
|
|
||||||
nm_utils_strbuf_append (&buf, &len, "%s0x%04x", prefix, flags);
|
|
||||||
|
|
||||||
flags_done:
|
|
||||||
|
|
||||||
nm_utils_strbuf_append (&buf, &len, ", seq %u", (unsigned) hdr->nlmsg_seq);
|
|
||||||
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* NMPObject/netlink functions
|
* NMPObject/netlink functions
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
|
|
@ -2637,8 +2535,7 @@ _nl_msg_new_link (int nlmsg_type,
|
||||||
|
|
||||||
nm_assert (NM_IN_SET (nlmsg_type, RTM_DELLINK, RTM_NEWLINK, RTM_GETLINK));
|
nm_assert (NM_IN_SET (nlmsg_type, RTM_DELLINK, RTM_NEWLINK, RTM_GETLINK));
|
||||||
|
|
||||||
if (!(msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags)))
|
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
|
||||||
g_return_val_if_reached (NULL);
|
|
||||||
|
|
||||||
if (nlmsg_append (msg, &ifi, sizeof (ifi), NLMSG_ALIGNTO) < 0)
|
if (nlmsg_append (msg, &ifi, sizeof (ifi), NLMSG_ALIGNTO) < 0)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
@ -2680,8 +2577,6 @@ _nl_msg_new_address (int nlmsg_type,
|
||||||
nm_assert (NM_IN_SET (nlmsg_type, RTM_NEWADDR, RTM_DELADDR));
|
nm_assert (NM_IN_SET (nlmsg_type, RTM_NEWADDR, RTM_DELADDR));
|
||||||
|
|
||||||
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
|
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
|
||||||
if (!msg)
|
|
||||||
g_return_val_if_reached (NULL);
|
|
||||||
|
|
||||||
if (scope == -1) {
|
if (scope == -1) {
|
||||||
/* Allow having scope unset, and detect the scope (including IPv4 compatibility hack). */
|
/* Allow having scope unset, and detect the scope (including IPv4 compatibility hack). */
|
||||||
|
|
@ -2794,8 +2689,6 @@ _nl_msg_new_route (int nlmsg_type,
|
||||||
nm_assert (NM_IN_SET (nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE));
|
nm_assert (NM_IN_SET (nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE));
|
||||||
|
|
||||||
msg = nlmsg_alloc_simple (nlmsg_type, (int) nlmsgflags);
|
msg = nlmsg_alloc_simple (nlmsg_type, (int) nlmsgflags);
|
||||||
if (!msg)
|
|
||||||
g_return_val_if_reached (NULL);
|
|
||||||
|
|
||||||
if (nlmsg_append (msg, &rtmsg, sizeof (rtmsg), NLMSG_ALIGNTO) < 0)
|
if (nlmsg_append (msg, &rtmsg, sizeof (rtmsg), NLMSG_ALIGNTO) < 0)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
@ -2893,8 +2786,6 @@ _nl_msg_new_qdisc (int nlmsg_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
|
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
|
||||||
if (!msg)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (nlmsg_append (msg, &tcm, sizeof (tcm), NLMSG_ALIGNTO) < 0)
|
if (nlmsg_append (msg, &tcm, sizeof (tcm), NLMSG_ALIGNTO) < 0)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
@ -2969,8 +2860,6 @@ _nl_msg_new_tfilter (int nlmsg_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
|
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
|
||||||
if (!msg)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (nlmsg_append (msg, &tcm, sizeof (tcm), NLMSG_ALIGNTO) < 0)
|
if (nlmsg_append (msg, &tcm, sizeof (tcm), NLMSG_ALIGNTO) < 0)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
@ -3553,28 +3442,59 @@ delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
|
||||||
g_array_remove_index_fast (priv->delayed_action.list_wait_for_nl_response, idx);
|
g_array_remove_index_fast (priv->delayed_action.list_wait_for_nl_response, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
delayed_action_wait_for_nl_response_complete_check (NMPlatform *platform,
|
||||||
|
WaitForNlResponseResult force_result,
|
||||||
|
guint32 *out_next_seq_number,
|
||||||
|
gint64 *out_next_timeout_abs_ns,
|
||||||
|
gint64 *p_now_ns)
|
||||||
|
{
|
||||||
|
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||||
|
guint i;
|
||||||
|
guint32 next_seq_number = 0;
|
||||||
|
gint64 next_timeout_abs_ns = 0;
|
||||||
|
gint now_ns = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; ) {
|
||||||
|
const DelayedActionWaitForNlResponseData *data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i);
|
||||||
|
|
||||||
|
if (data->seq_result)
|
||||||
|
delayed_action_wait_for_nl_response_complete (platform, i, data->seq_result);
|
||||||
|
else if ( p_now_ns
|
||||||
|
&& ((now_ns ?: (now_ns = nm_utils_get_monotonic_timestamp_ns ())) >= data->timeout_abs_ns)) {
|
||||||
|
/* the caller can optionally check for timeout by providing a p_now_ns argument. */
|
||||||
|
delayed_action_wait_for_nl_response_complete (platform, i, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT);
|
||||||
|
} else if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN)
|
||||||
|
delayed_action_wait_for_nl_response_complete (platform, i, force_result);
|
||||||
|
else {
|
||||||
|
if ( next_seq_number == 0
|
||||||
|
|| next_timeout_abs_ns > data->timeout_abs_ns) {
|
||||||
|
next_seq_number = data->seq_number;
|
||||||
|
next_timeout_abs_ns = data->timeout_abs_ns;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) {
|
||||||
|
nm_assert (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE));
|
||||||
|
nm_assert (priv->delayed_action.list_wait_for_nl_response->len == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
NM_SET_OUT (out_next_seq_number, next_seq_number);
|
||||||
|
NM_SET_OUT (out_next_timeout_abs_ns, next_timeout_abs_ns);
|
||||||
|
NM_SET_OUT (p_now_ns, now_ns);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
delayed_action_wait_for_nl_response_complete_all (NMPlatform *platform,
|
delayed_action_wait_for_nl_response_complete_all (NMPlatform *platform,
|
||||||
WaitForNlResponseResult fallback_result)
|
WaitForNlResponseResult fallback_result)
|
||||||
{
|
{
|
||||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
delayed_action_wait_for_nl_response_complete_check (platform,
|
||||||
|
fallback_result,
|
||||||
if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) {
|
NULL,
|
||||||
while (priv->delayed_action.list_wait_for_nl_response->len > 0) {
|
NULL,
|
||||||
const DelayedActionWaitForNlResponseData *data;
|
NULL);
|
||||||
guint idx = priv->delayed_action.list_wait_for_nl_response->len - 1;
|
|
||||||
WaitForNlResponseResult r;
|
|
||||||
|
|
||||||
data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, idx);
|
|
||||||
|
|
||||||
/* prefer the result that we already have. */
|
|
||||||
r = data->seq_result ? : fallback_result;
|
|
||||||
|
|
||||||
delayed_action_wait_for_nl_response_complete (platform, idx, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nm_assert (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE));
|
|
||||||
nm_assert (priv->delayed_action.list_wait_for_nl_response->len == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -4051,7 +3971,7 @@ _nlh_seq_next_get (NMLinuxPlatformPrivate *priv)
|
||||||
* @response_type:
|
* @response_type:
|
||||||
* @response_out_data:
|
* @response_out_data:
|
||||||
*
|
*
|
||||||
* Returns: 0 on success or a negative errno. Beware, it's an errno, not nlerror.
|
* Returns: 0 on success or a negative errno.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
_nl_send_nlmsghdr (NMPlatform *platform,
|
_nl_send_nlmsghdr (NMPlatform *platform,
|
||||||
|
|
@ -4235,8 +4155,6 @@ do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActionType actio
|
||||||
* because we need the sequence number.
|
* because we need the sequence number.
|
||||||
*/
|
*/
|
||||||
nlmsg = nlmsg_alloc_simple (klass->rtm_gettype, NLM_F_DUMP);
|
nlmsg = nlmsg_alloc_simple (klass->rtm_gettype, NLM_F_DUMP);
|
||||||
if (!nlmsg)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( klass->obj_type == NMP_OBJECT_TYPE_QDISC
|
if ( klass->obj_type == NMP_OBJECT_TYPE_QDISC
|
||||||
|| klass->obj_type == NMP_OBJECT_TYPE_TFILTER) {
|
|| klass->obj_type == NMP_OBJECT_TYPE_TFILTER) {
|
||||||
|
|
@ -4363,7 +4281,7 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
|
||||||
obj = nmp_object_new_from_nl (platform, cache, msg, id_only);
|
obj = nmp_object_new_from_nl (platform, cache, msg, id_only);
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
_LOGT ("event-notification: %s: ignore",
|
_LOGT ("event-notification: %s: ignore",
|
||||||
_nl_nlmsghdr_to_str (msghdr, buf_nlmsghdr, sizeof (buf_nlmsghdr)));
|
nl_nlmsghdr_to_str (msghdr, buf_nlmsghdr, sizeof (buf_nlmsghdr)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4381,7 +4299,7 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
|
||||||
}
|
}
|
||||||
|
|
||||||
_LOGT ("event-notification: %s%s: %s",
|
_LOGT ("event-notification: %s%s: %s",
|
||||||
_nl_nlmsghdr_to_str (msghdr, buf_nlmsghdr, sizeof (buf_nlmsghdr)),
|
nl_nlmsghdr_to_str (msghdr, buf_nlmsghdr, sizeof (buf_nlmsghdr)),
|
||||||
is_dump ? ", in-dump" : "",
|
is_dump ? ", in-dump" : "",
|
||||||
nmp_object_to_string (obj,
|
nmp_object_to_string (obj,
|
||||||
id_only ? NMP_OBJECT_TO_STRING_ID : NMP_OBJECT_TO_STRING_PUBLIC,
|
id_only ? NMP_OBJECT_TO_STRING_ID : NMP_OBJECT_TO_STRING_PUBLIC,
|
||||||
|
|
@ -6561,15 +6479,12 @@ event_handler_recvmsgs (NMPlatform *platform, gboolean handle_events)
|
||||||
{
|
{
|
||||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||||
struct nl_sock *sk = priv->nlh;
|
struct nl_sock *sk = priv->nlh;
|
||||||
int n, err = 0, multipart = 0, interrupted = 0;
|
int n;
|
||||||
|
int err = 0;
|
||||||
|
gboolean multipart = 0;
|
||||||
|
gboolean interrupted = FALSE;
|
||||||
struct nlmsghdr *hdr;
|
struct nlmsghdr *hdr;
|
||||||
WaitForNlResponseResult seq_result;
|
WaitForNlResponseResult seq_result;
|
||||||
|
|
||||||
/*
|
|
||||||
nla is passed on to not only to nl_recv() but may also be passed
|
|
||||||
to a function pointer provided by the caller which may or may not
|
|
||||||
initialize the variable. Thomas Graf.
|
|
||||||
*/
|
|
||||||
struct sockaddr_nl nla = {0};
|
struct sockaddr_nl nla = {0};
|
||||||
nm_auto_free struct ucred *creds = NULL;
|
nm_auto_free struct ucred *creds = NULL;
|
||||||
nm_auto_free unsigned char *buf = NULL;
|
nm_auto_free unsigned char *buf = NULL;
|
||||||
|
|
@ -6577,56 +6492,28 @@ event_handler_recvmsgs (NMPlatform *platform, gboolean handle_events)
|
||||||
continue_reading:
|
continue_reading:
|
||||||
g_clear_pointer (&buf, free);
|
g_clear_pointer (&buf, free);
|
||||||
g_clear_pointer (&creds, free);
|
g_clear_pointer (&creds, free);
|
||||||
errno = 0;
|
|
||||||
n = nl_recv (sk, &nla, &buf, &creds);
|
n = nl_recv (sk, &nla, &buf, &creds);
|
||||||
|
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
/* workaround libnl3 <= 3.2.15 returning danling pointers in case nl_recv()
|
|
||||||
* fails. Fixed by libnl3 69468517d0de1675d80f24661ff57a5dbac7275c. */
|
|
||||||
buf = NULL;
|
|
||||||
creds = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (n) {
|
if (n == -NLE_MSG_TRUNC) {
|
||||||
case 0:
|
int buf_size;
|
||||||
/* Work around a libnl bug fixed in 3.2.22 (375a6294) */
|
|
||||||
if (errno == EAGAIN) {
|
|
||||||
/* EAGAIN is equal to EWOULDBLOCK. If it would not be, we'd have to
|
|
||||||
* workaround libnl3 mapping EWOULDBLOCK to -NLE_FAILURE. */
|
|
||||||
G_STATIC_ASSERT (EAGAIN == EWOULDBLOCK);
|
|
||||||
n = -NLE_AGAIN;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case -NLE_MSG_TRUNC: {
|
|
||||||
int buf_size;
|
|
||||||
|
|
||||||
/* the message receive buffer was too small. We lost one message, which
|
/* the message receive buffer was too small. We lost one message, which
|
||||||
* is unfortunate. Try to double the buffer size for the next time. */
|
* is unfortunate. Try to double the buffer size for the next time. */
|
||||||
buf_size = nl_socket_get_msg_buf_size (sk);
|
buf_size = nl_socket_get_msg_buf_size (sk);
|
||||||
if (buf_size < 512*1024) {
|
if (buf_size < 512*1024) {
|
||||||
buf_size *= 2;
|
buf_size *= 2;
|
||||||
_LOGT ("netlink: recvmsg: increase message buffer size for recvmsg() to %d bytes", buf_size);
|
_LOGT ("netlink: recvmsg: increase message buffer size for recvmsg() to %d bytes", buf_size);
|
||||||
if (nl_socket_set_msg_buf_size (sk, buf_size) < 0)
|
if (nl_socket_set_msg_buf_size (sk, buf_size) < 0)
|
||||||
nm_assert_not_reached ();
|
nm_assert_not_reached ();
|
||||||
if (!handle_events)
|
if (!handle_events)
|
||||||
goto continue_reading;
|
goto continue_reading;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
n = -_NLE_MSG_TRUNC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case -NLE_NOMEM:
|
|
||||||
if (errno == ENOBUFS) {
|
|
||||||
/* we are very much interested in a overrun of the receive buffer.
|
|
||||||
* nl_recv() maps all kinds of errors to NLE_NOMEM, so check also
|
|
||||||
* for errno explicitly. And if so, hack our own return code to signal
|
|
||||||
* the overrun. */
|
|
||||||
n = -_NLE_NM_NOBUFS;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n <= 0)
|
|
||||||
return n;
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
hdr = (struct nlmsghdr *) buf;
|
hdr = (struct nlmsghdr *) buf;
|
||||||
while (nlmsg_ok (hdr, n)) {
|
while (nlmsg_ok (hdr, n)) {
|
||||||
|
|
@ -6636,11 +6523,7 @@ continue_reading:
|
||||||
guint32 seq_number;
|
guint32 seq_number;
|
||||||
char buf_nlmsghdr[400];
|
char buf_nlmsghdr[400];
|
||||||
|
|
||||||
msg = nlmsg_convert (hdr);
|
msg = nlmsg_alloc_convert (hdr);
|
||||||
if (!msg) {
|
|
||||||
err = -NLE_NOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
nlmsg_set_proto (msg, NETLINK_ROUTE);
|
nlmsg_set_proto (msg, NETLINK_ROUTE);
|
||||||
nlmsg_set_src (msg, &nla);
|
nlmsg_set_src (msg, &nla);
|
||||||
|
|
@ -6655,13 +6538,13 @@ continue_reading:
|
||||||
}
|
}
|
||||||
|
|
||||||
_LOGt ("netlink: recvmsg: new message %s",
|
_LOGt ("netlink: recvmsg: new message %s",
|
||||||
_nl_nlmsghdr_to_str (hdr, buf_nlmsghdr, sizeof (buf_nlmsghdr)));
|
nl_nlmsghdr_to_str (hdr, buf_nlmsghdr, sizeof (buf_nlmsghdr)));
|
||||||
|
|
||||||
if (creds)
|
if (creds)
|
||||||
nlmsg_set_creds (msg, creds);
|
nlmsg_set_creds (msg, creds);
|
||||||
|
|
||||||
if (hdr->nlmsg_flags & NLM_F_MULTI)
|
if (hdr->nlmsg_flags & NLM_F_MULTI)
|
||||||
multipart = 1;
|
multipart = TRUE;
|
||||||
|
|
||||||
if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) {
|
if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) {
|
||||||
/*
|
/*
|
||||||
|
|
@ -6669,7 +6552,7 @@ continue_reading:
|
||||||
* all messages until a NLMSG_DONE is
|
* all messages until a NLMSG_DONE is
|
||||||
* received and report the inconsistency.
|
* received and report the inconsistency.
|
||||||
*/
|
*/
|
||||||
interrupted = 1;
|
interrupted = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Other side wishes to see an ack for this message */
|
/* Other side wishes to see an ack for this message */
|
||||||
|
|
@ -6684,7 +6567,7 @@ continue_reading:
|
||||||
* usually the end of a message and therefore we slip
|
* usually the end of a message and therefore we slip
|
||||||
* out of the loop by default. the user may overrule
|
* out of the loop by default. the user may overrule
|
||||||
* this action by skipping this packet. */
|
* this action by skipping this packet. */
|
||||||
multipart = 0;
|
multipart = FALSE;
|
||||||
seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
|
seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
|
||||||
} else if (hdr->nlmsg_type == NLMSG_NOOP) {
|
} else if (hdr->nlmsg_type == NLMSG_NOOP) {
|
||||||
/* Message to be ignored, the default action is to
|
/* Message to be ignored, the default action is to
|
||||||
|
|
@ -6763,9 +6646,9 @@ stop:
|
||||||
* Repeat reading. */
|
* Repeat reading. */
|
||||||
goto continue_reading;
|
goto continue_reading;
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
if (interrupted)
|
if (interrupted)
|
||||||
err = -NLE_DUMP_INTR;
|
return -NLE_DUMP_INTR;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6776,46 +6659,50 @@ event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks)
|
||||||
{
|
{
|
||||||
nm_auto_pop_netns NMPNetns *netns = NULL;
|
nm_auto_pop_netns NMPNetns *netns = NULL;
|
||||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||||
int r, nle;
|
int r;
|
||||||
struct pollfd pfd;
|
struct pollfd pfd;
|
||||||
gboolean any = FALSE;
|
gboolean any = FALSE;
|
||||||
gint64 now_ns;
|
|
||||||
int timeout_ms;
|
int timeout_ms;
|
||||||
guint i;
|
|
||||||
struct {
|
struct {
|
||||||
guint32 seq_number;
|
guint32 seq_number;
|
||||||
gint64 timeout_abs_ns;
|
gint64 timeout_abs_ns;
|
||||||
} data_next;
|
gint64 now_ns;
|
||||||
|
} next;
|
||||||
|
|
||||||
if (!nm_platform_netns_push (platform, &netns))
|
if (!nm_platform_netns_push (platform, &netns)) {
|
||||||
|
delayed_action_wait_for_nl_response_complete_all (platform,
|
||||||
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_SETNS);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
while (TRUE) {
|
for (;;) {
|
||||||
|
for (;;) {
|
||||||
while (TRUE) {
|
int nle;
|
||||||
|
|
||||||
nle = event_handler_recvmsgs (platform, TRUE);
|
nle = event_handler_recvmsgs (platform, TRUE);
|
||||||
|
|
||||||
if (nle < 0) {
|
if (nle < 0) {
|
||||||
switch (nle) {
|
switch (nle) {
|
||||||
case -NLE_AGAIN:
|
case -EAGAIN:
|
||||||
goto after_read;
|
goto after_read;
|
||||||
case -NLE_DUMP_INTR:
|
case -NLE_DUMP_INTR:
|
||||||
_LOGD ("netlink: read: uncritical failure to retrieve incoming events: %s (%d)", nl_geterror (nle), nle);
|
_LOGD ("netlink: read: uncritical failure to retrieve incoming events: %s (%d)", nl_geterror (nle), nle);
|
||||||
break;
|
break;
|
||||||
case -_NLE_MSG_TRUNC:
|
case -NLE_MSG_TRUNC:
|
||||||
case -_NLE_NM_NOBUFS:
|
case -ENOBUFS:
|
||||||
_LOGI ("netlink: read: %s. Need to resynchronize platform cache",
|
_LOGI ("netlink: read: %s. Need to resynchronize platform cache",
|
||||||
({
|
({
|
||||||
const char *_reason = "unknown";
|
const char *_reason = "unknown";
|
||||||
switch (nle) {
|
switch (nle) {
|
||||||
case -_NLE_MSG_TRUNC: _reason = "message truncated"; break;
|
case -NLE_MSG_TRUNC: _reason = "message truncated"; break;
|
||||||
case -_NLE_NM_NOBUFS: _reason = "too many netlink events"; break;
|
case -ENOBUFS: _reason = "too many netlink events"; break;
|
||||||
}
|
}
|
||||||
_reason;
|
_reason;
|
||||||
}));
|
}));
|
||||||
event_handler_recvmsgs (platform, FALSE);
|
event_handler_recvmsgs (platform, FALSE);
|
||||||
delayed_action_wait_for_nl_response_complete_all (platform, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC);
|
delayed_action_wait_for_nl_response_complete_all (platform,
|
||||||
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC);
|
||||||
|
|
||||||
delayed_action_schedule (platform,
|
delayed_action_schedule (platform,
|
||||||
DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS |
|
DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS |
|
||||||
DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES |
|
DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES |
|
||||||
|
|
@ -6839,39 +6726,23 @@ after_read:
|
||||||
if (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE))
|
if (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE))
|
||||||
return any;
|
return any;
|
||||||
|
|
||||||
now_ns = 0;
|
delayed_action_wait_for_nl_response_complete_check (platform,
|
||||||
data_next.seq_number = 0;
|
WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN,
|
||||||
data_next.timeout_abs_ns = 0;
|
&next.seq_number,
|
||||||
|
&next.timeout_abs_ns,
|
||||||
for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; ) {
|
&next.now_ns);
|
||||||
DelayedActionWaitForNlResponseData *data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i);
|
|
||||||
|
|
||||||
if (data->seq_result)
|
|
||||||
delayed_action_wait_for_nl_response_complete (platform, i, data->seq_result);
|
|
||||||
else if ((now_ns ?: (now_ns = nm_utils_get_monotonic_timestamp_ns ())) > data->timeout_abs_ns)
|
|
||||||
delayed_action_wait_for_nl_response_complete (platform, i, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT);
|
|
||||||
else {
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if ( data_next.seq_number == 0
|
|
||||||
|| data_next.timeout_abs_ns > data->timeout_abs_ns) {
|
|
||||||
data_next.seq_number = data->seq_number;
|
|
||||||
data_next.timeout_abs_ns = data->timeout_abs_ns;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !wait_for_acks
|
if ( !wait_for_acks
|
||||||
|| !NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE))
|
|| !NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE))
|
||||||
return any;
|
return any;
|
||||||
|
|
||||||
nm_assert (data_next.seq_number);
|
nm_assert (next.seq_number);
|
||||||
nm_assert (data_next.timeout_abs_ns > 0);
|
nm_assert (next.now_ns > 0);
|
||||||
nm_assert (now_ns > 0);
|
nm_assert (next.timeout_abs_ns > next.now_ns);
|
||||||
|
|
||||||
_LOGT ("netlink: read: wait for ACK for sequence number %u...", data_next.seq_number);
|
_LOGT ("netlink: read: wait for ACK for sequence number %u...", next.seq_number);
|
||||||
|
|
||||||
timeout_ms = (data_next.timeout_abs_ns - now_ns) / (NM_UTILS_NS_PER_SECOND / 1000);
|
timeout_ms = (next.timeout_abs_ns - next.now_ns) / (NM_UTILS_NS_PER_SECOND / 1000);
|
||||||
|
|
||||||
memset (&pfd, 0, sizeof (pfd));
|
memset (&pfd, 0, sizeof (pfd));
|
||||||
pfd.fd = nl_socket_get_fd (priv->nlh);
|
pfd.fd = nl_socket_get_fd (priv->nlh);
|
||||||
|
|
@ -6882,6 +6753,7 @@ after_read:
|
||||||
/* timeout and there is nothing to read. */
|
/* timeout and there is nothing to read. */
|
||||||
goto after_read;
|
goto after_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
int errsv = errno;
|
int errsv = errno;
|
||||||
|
|
||||||
|
|
@ -7152,7 +7024,8 @@ dispose (GObject *object)
|
||||||
|
|
||||||
_LOGD ("dispose");
|
_LOGD ("dispose");
|
||||||
|
|
||||||
delayed_action_wait_for_nl_response_complete_all (platform, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING);
|
delayed_action_wait_for_nl_response_complete_all (platform,
|
||||||
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING);
|
||||||
|
|
||||||
priv->delayed_action.flags = DELAYED_ACTION_TYPE_NONE;
|
priv->delayed_action.flags = DELAYED_ACTION_TYPE_NONE;
|
||||||
g_ptr_array_set_size (priv->delayed_action.list_master_connected, 0);
|
g_ptr_array_set_size (priv->delayed_action.list_master_connected, 0);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -21,40 +21,375 @@
|
||||||
#ifndef __NM_NETLINK_H__
|
#ifndef __NM_NETLINK_H__
|
||||||
#define __NM_NETLINK_H__
|
#define __NM_NETLINK_H__
|
||||||
|
|
||||||
#include <netlink/msg.h>
|
#include <linux/netlink.h>
|
||||||
#include <netlink/attr.h>
|
#include <linux/rtnetlink.h>
|
||||||
|
#include <linux/genetlink.h>
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************/
|
||||||
* libnl3 compat code
|
|
||||||
*****************************************************************************/
|
#define _NLE_BASE 100000
|
||||||
|
#define NLE_UNSPEC (_NLE_BASE + 0)
|
||||||
|
#define NLE_BUG (_NLE_BASE + 1)
|
||||||
|
#define NLE_NATIVE_ERRNO (_NLE_BASE + 2)
|
||||||
|
#define NLE_SEQ_MISMATCH (_NLE_BASE + 3)
|
||||||
|
#define NLE_MSG_TRUNC (_NLE_BASE + 4)
|
||||||
|
#define NLE_MSG_TOOSHORT (_NLE_BASE + 5)
|
||||||
|
#define NLE_DUMP_INTR (_NLE_BASE + 6)
|
||||||
|
#define NLE_ATTRSIZE (_NLE_BASE + 7)
|
||||||
|
#define NLE_BAD_SOCK (_NLE_BASE + 8)
|
||||||
|
#define NLE_NOADDR (_NLE_BASE + 9)
|
||||||
|
#define NLE_MSG_OVERFLOW (_NLE_BASE + 10)
|
||||||
|
|
||||||
|
#define _NLE_BASE_END (_NLE_BASE + 11)
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
_nl_nla_parse (struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
|
nl_errno (int err)
|
||||||
const struct nla_policy *policy)
|
|
||||||
{
|
{
|
||||||
return nla_parse (tb, maxtype, head, len, (struct nla_policy *) policy);
|
/* the error codes from our netlink implementation are plain errno
|
||||||
|
* extended with our own error in a particular range starting from
|
||||||
|
* _NLE_BASE.
|
||||||
|
*
|
||||||
|
* However, often we encode errors as negative values. This function
|
||||||
|
* normalizes the error and returns it's positive value. */
|
||||||
|
return err >= 0
|
||||||
|
? err
|
||||||
|
: ((err == G_MININT) ? NLE_BUG : -errno);
|
||||||
}
|
}
|
||||||
#define nla_parse(...) _nl_nla_parse(__VA_ARGS__)
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
_nl_nlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
|
nl_syserr2nlerr (int err)
|
||||||
int maxtype, const struct nla_policy *policy)
|
|
||||||
{
|
{
|
||||||
return nlmsg_parse (nlh, hdrlen, tb, maxtype, (struct nla_policy *) policy);
|
if (err == G_MININT)
|
||||||
|
return NLE_NATIVE_ERRNO;
|
||||||
|
if (err < 0)
|
||||||
|
err = -err;
|
||||||
|
return (err >= _NLE_BASE && err < _NLE_BASE_END)
|
||||||
|
? NLE_NATIVE_ERRNO
|
||||||
|
: err;
|
||||||
}
|
}
|
||||||
#define nlmsg_parse(...) _nl_nlmsg_parse(__VA_ARGS__)
|
|
||||||
|
const char *nl_geterror (int err);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/* Basic attribute data types */
|
||||||
|
enum {
|
||||||
|
NLA_UNSPEC, /* Unspecified type, binary data chunk */
|
||||||
|
NLA_U8, /* 8 bit integer */
|
||||||
|
NLA_U16, /* 16 bit integer */
|
||||||
|
NLA_U32, /* 32 bit integer */
|
||||||
|
NLA_U64, /* 64 bit integer */
|
||||||
|
NLA_STRING, /* NUL terminated character string */
|
||||||
|
NLA_FLAG, /* Flag */
|
||||||
|
NLA_MSECS, /* Micro seconds (64bit) */
|
||||||
|
NLA_NESTED, /* Nested attributes */
|
||||||
|
NLA_NESTED_COMPAT,
|
||||||
|
NLA_NUL_STRING,
|
||||||
|
NLA_BINARY,
|
||||||
|
NLA_S8,
|
||||||
|
NLA_S16,
|
||||||
|
NLA_S32,
|
||||||
|
NLA_S64,
|
||||||
|
__NLA_TYPE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
|
||||||
|
|
||||||
|
struct nl_msg;
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
const char *nl_nlmsgtype2str (int type, char *buf, size_t size);
|
||||||
|
|
||||||
|
const char *nl_nlmsg_flags2str (int flags, char *buf, size_t len);
|
||||||
|
|
||||||
|
const char *nl_nlmsghdr_to_str (const struct nlmsghdr *hdr, char *buf, gsize len);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
struct nla_policy {
|
||||||
|
/* Type of attribute or NLA_UNSPEC */
|
||||||
|
uint16_t type;
|
||||||
|
|
||||||
|
/* Minimal length of payload required */
|
||||||
|
uint16_t minlen;
|
||||||
|
|
||||||
|
/* Maximal length of payload allowed */
|
||||||
|
uint16_t maxlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
_nl_nla_parse_nested (struct nlattr *tb[], int maxtype, struct nlattr *nla,
|
nla_attr_size(int payload)
|
||||||
const struct nla_policy *policy)
|
|
||||||
{
|
{
|
||||||
return nla_parse_nested (tb, maxtype, nla, (struct nla_policy *) policy);
|
nm_assert (payload >= 0);
|
||||||
}
|
|
||||||
#define nla_parse_nested(...) _nl_nla_parse_nested(__VA_ARGS__)
|
|
||||||
|
|
||||||
/*****************************************************************************
|
return NLA_HDRLEN + payload;
|
||||||
* Reimplementations/copied from libnl3/genl
|
}
|
||||||
*****************************************************************************/
|
|
||||||
|
static inline int
|
||||||
|
nla_total_size (int payload)
|
||||||
|
{
|
||||||
|
return NLA_ALIGN (nla_attr_size (payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nla_padlen (int payload)
|
||||||
|
{
|
||||||
|
return nla_total_size(payload) - nla_attr_size(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nlattr *nla_reserve (struct nl_msg *msg, int attrtype, int attrlen);
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nla_len (const struct nlattr *nla)
|
||||||
|
{
|
||||||
|
return nla->nla_len - NLA_HDRLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nla_type (const struct nlattr *nla)
|
||||||
|
{
|
||||||
|
return nla->nla_type & NLA_TYPE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
nla_data (const struct nlattr *nla)
|
||||||
|
{
|
||||||
|
nm_assert (nla);
|
||||||
|
return (char *) nla + NLA_HDRLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t
|
||||||
|
nla_get_u8 (const struct nlattr *nla)
|
||||||
|
{
|
||||||
|
return *(const uint8_t *) nla_data (nla);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t
|
||||||
|
nla_get_u16 (const struct nlattr *nla)
|
||||||
|
{
|
||||||
|
return *(const uint16_t *) nla_data (nla);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
nla_get_u32(const struct nlattr *nla)
|
||||||
|
{
|
||||||
|
return *(const uint32_t *) nla_data (nla);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t nla_get_u64 (const struct nlattr *nla);
|
||||||
|
|
||||||
|
static inline char *
|
||||||
|
nla_get_string (const struct nlattr *nla)
|
||||||
|
{
|
||||||
|
return (char *) nla_data (nla);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nla_strlcpy (char *dst, const struct nlattr *nla, size_t dstsize);
|
||||||
|
|
||||||
|
int nla_memcpy (void *dest, const struct nlattr *src, int count);
|
||||||
|
|
||||||
|
int nla_put (struct nl_msg *msg, int attrtype, int datalen, const void *data);
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nla_put_string (struct nl_msg *msg, int attrtype, const char *str)
|
||||||
|
{
|
||||||
|
return nla_put(msg, attrtype, strlen(str) + 1, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NLA_PUT(msg, attrtype, attrlen, data) \
|
||||||
|
do { \
|
||||||
|
if (nla_put(msg, attrtype, attrlen, data) < 0) \
|
||||||
|
goto nla_put_failure; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define NLA_PUT_TYPE(msg, type, attrtype, value) \
|
||||||
|
do { \
|
||||||
|
type __tmp = value; \
|
||||||
|
NLA_PUT(msg, attrtype, sizeof(type), &__tmp); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define NLA_PUT_U8(msg, attrtype, value) \
|
||||||
|
NLA_PUT_TYPE(msg, uint8_t, attrtype, value)
|
||||||
|
|
||||||
|
#define NLA_PUT_U16(msg, attrtype, value) \
|
||||||
|
NLA_PUT_TYPE(msg, uint16_t, attrtype, value)
|
||||||
|
|
||||||
|
#define NLA_PUT_U32(msg, attrtype, value) \
|
||||||
|
NLA_PUT_TYPE(msg, uint32_t, attrtype, value)
|
||||||
|
|
||||||
|
#define NLA_PUT_U64(msg, attrtype, value) \
|
||||||
|
NLA_PUT_TYPE(msg, uint64_t, attrtype, value)
|
||||||
|
|
||||||
|
#define NLA_PUT_STRING(msg, attrtype, value) \
|
||||||
|
NLA_PUT(msg, attrtype, (int) strlen(value) + 1, value)
|
||||||
|
|
||||||
|
struct nlattr *nla_find (const struct nlattr *head, int len, int attrtype);
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nla_ok (const struct nlattr *nla, int remaining)
|
||||||
|
{
|
||||||
|
return remaining >= sizeof(*nla) &&
|
||||||
|
nla->nla_len >= sizeof(*nla) &&
|
||||||
|
nla->nla_len <= remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct nlattr *
|
||||||
|
nla_next(const struct nlattr *nla, int *remaining)
|
||||||
|
{
|
||||||
|
int totlen = NLA_ALIGN(nla->nla_len);
|
||||||
|
|
||||||
|
*remaining -= totlen;
|
||||||
|
return (struct nlattr *) ((char *) nla + totlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define nla_for_each_attr(pos, head, len, rem) \
|
||||||
|
for (pos = head, rem = len; \
|
||||||
|
nla_ok(pos, rem); \
|
||||||
|
pos = nla_next(pos, &(rem)))
|
||||||
|
|
||||||
|
#define nla_for_each_nested(pos, nla, rem) \
|
||||||
|
for (pos = (struct nlattr *) nla_data(nla), rem = nla_len(nla); \
|
||||||
|
nla_ok(pos, rem); \
|
||||||
|
pos = nla_next(pos, &(rem)))
|
||||||
|
|
||||||
|
void nla_nest_cancel (struct nl_msg *msg, const struct nlattr *attr);
|
||||||
|
struct nlattr *nla_nest_start (struct nl_msg *msg, int attrtype);
|
||||||
|
int nla_nest_end (struct nl_msg *msg, struct nlattr *start);
|
||||||
|
|
||||||
|
int nla_parse (struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
|
||||||
|
const struct nla_policy *policy);
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nla_parse_nested (struct nlattr *tb[], int maxtype, struct nlattr *nla,
|
||||||
|
const struct nla_policy *policy)
|
||||||
|
{
|
||||||
|
return nla_parse (tb, maxtype, nla_data(nla), nla_len(nla), policy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
struct nl_msg *nlmsg_alloc (void);
|
||||||
|
|
||||||
|
struct nl_msg *nlmsg_alloc_size (size_t max);
|
||||||
|
|
||||||
|
struct nl_msg *nlmsg_alloc_inherit (struct nlmsghdr *hdr);
|
||||||
|
|
||||||
|
struct nl_msg *nlmsg_alloc_convert (struct nlmsghdr *hdr);
|
||||||
|
|
||||||
|
struct nl_msg *nlmsg_alloc_simple (int nlmsgtype, int flags);
|
||||||
|
|
||||||
|
void *nlmsg_reserve (struct nl_msg *n, size_t len, int pad);
|
||||||
|
|
||||||
|
int nlmsg_append (struct nl_msg *n, void *data, size_t len, int pad);
|
||||||
|
|
||||||
|
void nlmsg_free (struct nl_msg *msg);
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nlmsg_size (int payload)
|
||||||
|
{
|
||||||
|
nm_assert (payload >= 0 && payload < G_MAXINT - NLMSG_HDRLEN - 4);
|
||||||
|
return NLMSG_HDRLEN + payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nlmsg_total_size (int payload)
|
||||||
|
{
|
||||||
|
return NLMSG_ALIGN (nlmsg_size (payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nlmsg_ok (const struct nlmsghdr *nlh, int remaining)
|
||||||
|
{
|
||||||
|
return (remaining >= (int)sizeof(struct nlmsghdr) &&
|
||||||
|
nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
|
||||||
|
nlh->nlmsg_len <= remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct nlmsghdr *
|
||||||
|
nlmsg_next (struct nlmsghdr *nlh, int *remaining)
|
||||||
|
{
|
||||||
|
int totlen = NLMSG_ALIGN(nlh->nlmsg_len);
|
||||||
|
|
||||||
|
*remaining -= totlen;
|
||||||
|
|
||||||
|
return (struct nlmsghdr *) ((unsigned char *) nlh + totlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nlmsg_get_proto (struct nl_msg *msg);
|
||||||
|
void nlmsg_set_proto (struct nl_msg *msg, int protocol);
|
||||||
|
|
||||||
|
void nlmsg_set_src (struct nl_msg *msg, struct sockaddr_nl *addr);
|
||||||
|
|
||||||
|
struct ucred *nlmsg_get_creds (struct nl_msg *msg);
|
||||||
|
void nlmsg_set_creds (struct nl_msg *msg, struct ucred *creds);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_nm_auto_nl_msg_cleanup (struct nl_msg **ptr)
|
||||||
|
{
|
||||||
|
nlmsg_free (*ptr);
|
||||||
|
}
|
||||||
|
#define nm_auto_nlmsg nm_auto(_nm_auto_nl_msg_cleanup)
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
nlmsg_data (const struct nlmsghdr *nlh)
|
||||||
|
{
|
||||||
|
return (unsigned char *) nlh + NLMSG_HDRLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
nlmsg_tail (const struct nlmsghdr *nlh)
|
||||||
|
{
|
||||||
|
return (unsigned char *) nlh + NLMSG_ALIGN(nlh->nlmsg_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nlmsghdr *nlmsg_hdr (struct nl_msg *n);
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nlmsg_valid_hdr(const struct nlmsghdr *nlh, int hdrlen)
|
||||||
|
{
|
||||||
|
if (nlh->nlmsg_len < nlmsg_size (hdrlen))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nlmsg_datalen (const struct nlmsghdr *nlh)
|
||||||
|
{
|
||||||
|
return nlh->nlmsg_len - NLMSG_HDRLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nlmsg_attrlen (const struct nlmsghdr *nlh, int hdrlen)
|
||||||
|
{
|
||||||
|
return NM_MAX ((int) (nlmsg_datalen (nlh) - NLMSG_ALIGN (hdrlen)), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct nlattr *
|
||||||
|
nlmsg_attrdata (const struct nlmsghdr *nlh, int hdrlen)
|
||||||
|
{
|
||||||
|
unsigned char *data = nlmsg_data(nlh);
|
||||||
|
return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct nlattr *
|
||||||
|
nlmsg_find_attr (struct nlmsghdr *nlh, int hdrlen, int attrtype)
|
||||||
|
{
|
||||||
|
return nla_find (nlmsg_attrdata (nlh, hdrlen),
|
||||||
|
nlmsg_attrlen (nlh, hdrlen),
|
||||||
|
attrtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
|
||||||
|
int maxtype, const struct nla_policy *policy);
|
||||||
|
|
||||||
|
struct nlmsghdr *nlmsg_put (struct nl_msg *n, uint32_t pid, uint32_t seq,
|
||||||
|
int type, int payload, int flags);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
void *genlmsg_put (struct nl_msg *msg, uint32_t port, uint32_t seq, int family,
|
void *genlmsg_put (struct nl_msg *msg, uint32_t port, uint32_t seq, int family,
|
||||||
int hdrlen, int flags, uint8_t cmd, uint8_t version);
|
int hdrlen, int flags, uint8_t cmd, uint8_t version);
|
||||||
|
|
@ -69,16 +404,85 @@ int genlmsg_valid_hdr (struct nlmsghdr *nlh, int hdrlen);
|
||||||
int genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
|
int genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
|
||||||
int maxtype, const struct nla_policy *policy);
|
int maxtype, const struct nla_policy *policy);
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************/
|
||||||
* helpers
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
static inline void
|
#define NL_AUTO_PORT 0
|
||||||
_nm_auto_nl_msg_cleanup (struct nl_msg **ptr)
|
#define NL_AUTO_SEQ 0
|
||||||
{
|
|
||||||
nlmsg_free (*ptr);
|
struct nl_sock;
|
||||||
}
|
|
||||||
#define nm_auto_nlmsg nm_auto(_nm_auto_nl_msg_cleanup)
|
struct nl_sock *nl_socket_alloc (void);
|
||||||
|
|
||||||
|
void nl_socket_free (struct nl_sock *sk);
|
||||||
|
|
||||||
|
int nl_socket_get_fd (const struct nl_sock *sk);
|
||||||
|
|
||||||
|
struct sockaddr_nl *nlmsg_get_dst (struct nl_msg *msg);
|
||||||
|
|
||||||
|
size_t nl_socket_get_msg_buf_size (struct nl_sock *sk);
|
||||||
|
int nl_socket_set_msg_buf_size (struct nl_sock *sk, size_t bufsize);
|
||||||
|
|
||||||
|
int nl_socket_set_buffer_size (struct nl_sock *sk, int rxbuf, int txbuf);
|
||||||
|
|
||||||
|
int nl_socket_set_passcred (struct nl_sock *sk, int state);
|
||||||
|
|
||||||
|
int nl_socket_set_nonblocking (const struct nl_sock *sk);
|
||||||
|
|
||||||
|
void nl_socket_disable_msg_peek (struct nl_sock *sk);
|
||||||
|
|
||||||
|
uint32_t nl_socket_get_local_port (const struct nl_sock *sk);
|
||||||
|
|
||||||
|
int nl_socket_add_memberships (struct nl_sock *sk, int group, ...);
|
||||||
|
|
||||||
|
int nl_connect (struct nl_sock *sk, int protocol);
|
||||||
|
|
||||||
|
int nl_recv (struct nl_sock *sk, struct sockaddr_nl *nla,
|
||||||
|
unsigned char **buf, struct ucred **creds);
|
||||||
|
|
||||||
|
int nl_send (struct nl_sock *sk, struct nl_msg *msg);
|
||||||
|
|
||||||
|
int nl_send_auto (struct nl_sock *sk, struct nl_msg *msg);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
enum nl_cb_action {
|
||||||
|
/* Proceed with wathever would come next */
|
||||||
|
NL_OK,
|
||||||
|
/* Skip this message */
|
||||||
|
NL_SKIP,
|
||||||
|
/* Stop parsing altogether and discard remaining messages */
|
||||||
|
NL_STOP,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (*nl_recvmsg_msg_cb_t) (struct nl_msg *msg, void *arg);
|
||||||
|
|
||||||
|
typedef int (*nl_recvmsg_err_cb_t) (struct sockaddr_nl *nla,
|
||||||
|
struct nlmsgerr *nlerr, void *arg);
|
||||||
|
|
||||||
|
struct nl_cb {
|
||||||
|
nl_recvmsg_msg_cb_t valid_cb;
|
||||||
|
void * valid_arg;
|
||||||
|
|
||||||
|
nl_recvmsg_msg_cb_t finish_cb;
|
||||||
|
void * finish_arg;
|
||||||
|
|
||||||
|
nl_recvmsg_msg_cb_t ack_cb;
|
||||||
|
void * ack_arg;
|
||||||
|
|
||||||
|
nl_recvmsg_err_cb_t err_cb;
|
||||||
|
void * err_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
int nl_sendmsg (struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr);
|
||||||
|
|
||||||
|
int nl_send_iovec (struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen);
|
||||||
|
|
||||||
|
void nl_complete_msg (struct nl_sock *sk, struct nl_msg *msg);
|
||||||
|
|
||||||
|
int nl_recvmsgs (struct nl_sock *sk, const struct nl_cb *cb);
|
||||||
|
|
||||||
|
int nl_wait_for_ack (struct nl_sock *sk,
|
||||||
|
const struct nl_cb *cb);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,55 +79,41 @@ probe_response (struct nl_msg *msg, void *arg)
|
||||||
static int
|
static int
|
||||||
genl_ctrl_resolve (struct nl_sock *sk, const char *name)
|
genl_ctrl_resolve (struct nl_sock *sk, const char *name)
|
||||||
{
|
{
|
||||||
struct nl_msg *msg;
|
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||||||
struct nl_cb *cb, *orig;
|
int result = -ENOMEM;
|
||||||
int rc;
|
|
||||||
int result = -NLE_OBJ_NOTFOUND;
|
|
||||||
gint32 response_data = -1;
|
gint32 response_data = -1;
|
||||||
|
const struct nl_cb cb = {
|
||||||
if (!(orig = nl_socket_get_cb (sk)))
|
.valid_cb = probe_response,
|
||||||
goto out;
|
.valid_arg = &response_data,
|
||||||
|
};
|
||||||
cb = nl_cb_clone (orig);
|
|
||||||
nl_cb_put (orig);
|
|
||||||
if (!cb)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
msg = nlmsg_alloc ();
|
msg = nlmsg_alloc ();
|
||||||
if (!msg)
|
|
||||||
goto out_cb_free;
|
|
||||||
|
|
||||||
if (!genlmsg_put (msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL,
|
if (!genlmsg_put (msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL,
|
||||||
0, 0, CTRL_CMD_GETFAMILY, 1))
|
0, 0, CTRL_CMD_GETFAMILY, 1))
|
||||||
goto out_msg_free;
|
goto out;
|
||||||
|
|
||||||
if (nla_put_string (msg, CTRL_ATTR_FAMILY_NAME, name) < 0)
|
if (nla_put_string (msg, CTRL_ATTR_FAMILY_NAME, name) < 0)
|
||||||
goto out_msg_free;
|
goto out;
|
||||||
|
|
||||||
rc = nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, &response_data);
|
result = nl_send_auto (sk, msg);
|
||||||
if (rc < 0)
|
if (result < 0)
|
||||||
goto out_msg_free;
|
goto out;
|
||||||
|
|
||||||
rc = nl_send_auto_complete (sk, msg);
|
result = nl_recvmsgs (sk, &cb);
|
||||||
if (rc < 0)
|
if (result < 0)
|
||||||
goto out_msg_free;
|
goto out;
|
||||||
|
|
||||||
rc = nl_recvmsgs (sk, cb);
|
|
||||||
if (rc < 0)
|
|
||||||
goto out_msg_free;
|
|
||||||
|
|
||||||
/* If search was successful, request may be ACKed after data */
|
/* If search was successful, request may be ACKed after data */
|
||||||
rc = nl_wait_for_ack (sk);
|
result = nl_wait_for_ack (sk, NULL);
|
||||||
if (rc < 0)
|
if (result < 0)
|
||||||
goto out_msg_free;
|
goto out;
|
||||||
|
|
||||||
if (response_data > 0)
|
if (response_data > 0)
|
||||||
result = response_data;
|
result = response_data;
|
||||||
|
else
|
||||||
|
result = -ENOENT;
|
||||||
|
|
||||||
out_msg_free:
|
|
||||||
nlmsg_free (msg);
|
|
||||||
out_cb_free:
|
|
||||||
nl_cb_put (cb);
|
|
||||||
out:
|
out:
|
||||||
if (result >= 0)
|
if (result >= 0)
|
||||||
_LOGD (LOGD_WIFI, "genl_ctrl_resolve: resolved \"%s\" as 0x%x", name, result);
|
_LOGD (LOGD_WIFI, "genl_ctrl_resolve: resolved \"%s\" as 0x%x", name, result);
|
||||||
|
|
@ -143,7 +129,6 @@ out:
|
||||||
typedef struct {
|
typedef struct {
|
||||||
WifiData parent;
|
WifiData parent;
|
||||||
struct nl_sock *nl_sock;
|
struct nl_sock *nl_sock;
|
||||||
struct nl_cb *nl_cb;
|
|
||||||
guint32 *freqs;
|
guint32 *freqs;
|
||||||
int id;
|
int id;
|
||||||
int num_freqs;
|
int num_freqs;
|
||||||
|
|
@ -178,19 +163,16 @@ error_handler (struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
|
||||||
static struct nl_msg *
|
static struct nl_msg *
|
||||||
_nl80211_alloc_msg (int id, int ifindex, int phy, guint32 cmd, guint32 flags)
|
_nl80211_alloc_msg (int id, int ifindex, int phy, guint32 cmd, guint32 flags)
|
||||||
{
|
{
|
||||||
struct nl_msg *msg;
|
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||||||
|
|
||||||
msg = nlmsg_alloc ();
|
msg = nlmsg_alloc ();
|
||||||
if (msg) {
|
genlmsg_put (msg, 0, 0, id, 0, flags, cmd, 0);
|
||||||
genlmsg_put (msg, 0, 0, id, 0, flags, cmd, 0);
|
NLA_PUT_U32 (msg, NL80211_ATTR_IFINDEX, ifindex);
|
||||||
NLA_PUT_U32 (msg, NL80211_ATTR_IFINDEX, ifindex);
|
if (phy != -1)
|
||||||
if (phy != -1)
|
NLA_PUT_U32 (msg, NL80211_ATTR_WIPHY, phy);
|
||||||
NLA_PUT_U32 (msg, NL80211_ATTR_WIPHY, phy);
|
return g_steal_pointer (&msg);
|
||||||
}
|
|
||||||
return msg;
|
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free (msg);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,39 +185,36 @@ nl80211_alloc_msg (WifiDataNl80211 *nl80211, guint32 cmd, guint32 flags)
|
||||||
/* NOTE: this function consumes 'msg' */
|
/* NOTE: this function consumes 'msg' */
|
||||||
static int
|
static int
|
||||||
_nl80211_send_and_recv (struct nl_sock *nl_sock,
|
_nl80211_send_and_recv (struct nl_sock *nl_sock,
|
||||||
struct nl_cb *nl_cb,
|
|
||||||
struct nl_msg *msg,
|
struct nl_msg *msg,
|
||||||
int (*valid_handler) (struct nl_msg *, void *),
|
int (*valid_handler) (struct nl_msg *, void *),
|
||||||
void *valid_data)
|
void *valid_data)
|
||||||
{
|
{
|
||||||
struct nl_cb *cb;
|
nm_auto_nlmsg struct nl_msg *msg_free = msg;
|
||||||
int err, done;
|
int err;
|
||||||
|
int done = 0;
|
||||||
|
const struct nl_cb cb = {
|
||||||
|
.err_cb = error_handler,
|
||||||
|
.err_arg = &done,
|
||||||
|
.finish_cb = finish_handler,
|
||||||
|
.finish_arg = &done,
|
||||||
|
.ack_cb = ack_handler,
|
||||||
|
.ack_arg = &done,
|
||||||
|
.valid_cb = valid_handler,
|
||||||
|
.valid_arg = valid_data,
|
||||||
|
};
|
||||||
|
|
||||||
g_return_val_if_fail (msg != NULL, -ENOMEM);
|
g_return_val_if_fail (msg != NULL, -ENOMEM);
|
||||||
|
|
||||||
cb = nl_cb_clone (nl_cb);
|
err = nl_send_auto (nl_sock, msg);
|
||||||
if (!cb) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = nl_send_auto_complete (nl_sock, msg);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out;
|
return err;
|
||||||
|
|
||||||
done = 0;
|
|
||||||
nl_cb_err (cb, NL_CB_CUSTOM, error_handler, &done);
|
|
||||||
nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &done);
|
|
||||||
nl_cb_set (cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &done);
|
|
||||||
if (valid_handler)
|
|
||||||
nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data);
|
|
||||||
|
|
||||||
/* Loop until one of our NL callbacks says we're done; on success
|
/* Loop until one of our NL callbacks says we're done; on success
|
||||||
* done will be 1, on error it will be < 0.
|
* done will be 1, on error it will be < 0.
|
||||||
*/
|
*/
|
||||||
while (!done) {
|
while (!done) {
|
||||||
err = nl_recvmsgs (nl_sock, cb);
|
err = nl_recvmsgs (nl_sock, &cb);
|
||||||
if (err && err != -NLE_AGAIN) {
|
if (err < 0 && err != -EAGAIN) {
|
||||||
/* Kernel scan list can change while we are dumping it, as new scan
|
/* Kernel scan list can change while we are dumping it, as new scan
|
||||||
* results from H/W can arrive. BSS info is assured to be consistent
|
* results from H/W can arrive. BSS info is assured to be consistent
|
||||||
* and we don't need consistent view of whole scan list. Hence do
|
* and we don't need consistent view of whole scan list. Hence do
|
||||||
|
|
@ -250,12 +229,9 @@ _nl80211_send_and_recv (struct nl_sock *nl_sock,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (err == 0 && done < 0)
|
|
||||||
err = done;
|
|
||||||
|
|
||||||
out:
|
if (err >= 0 && done < 0)
|
||||||
nl_cb_put (cb);
|
err = done;
|
||||||
nlmsg_free (msg);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,7 +241,7 @@ nl80211_send_and_recv (WifiDataNl80211 *nl80211,
|
||||||
int (*valid_handler) (struct nl_msg *, void *),
|
int (*valid_handler) (struct nl_msg *, void *),
|
||||||
void *valid_data)
|
void *valid_data)
|
||||||
{
|
{
|
||||||
return _nl80211_send_and_recv (nl80211->nl_sock, nl80211->nl_cb, msg,
|
return _nl80211_send_and_recv (nl80211->nl_sock, msg,
|
||||||
valid_handler, valid_data);
|
valid_handler, valid_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,8 +252,6 @@ wifi_nl80211_deinit (WifiData *parent)
|
||||||
|
|
||||||
if (nl80211->nl_sock)
|
if (nl80211->nl_sock)
|
||||||
nl_socket_free (nl80211->nl_sock);
|
nl_socket_free (nl80211->nl_sock);
|
||||||
if (nl80211->nl_cb)
|
|
||||||
nl_cb_put (nl80211->nl_cb);
|
|
||||||
g_free (nl80211->freqs);
|
g_free (nl80211->freqs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -326,7 +300,7 @@ wifi_nl80211_get_mode (WifiData *data)
|
||||||
msg = nl80211_alloc_msg (nl80211, NL80211_CMD_GET_INTERFACE, 0);
|
msg = nl80211_alloc_msg (nl80211, NL80211_CMD_GET_INTERFACE, 0);
|
||||||
|
|
||||||
if (nl80211_send_and_recv (nl80211, msg, nl80211_iface_info_handler,
|
if (nl80211_send_and_recv (nl80211, msg, nl80211_iface_info_handler,
|
||||||
&iface_info) < 0)
|
&iface_info) < 0)
|
||||||
return NM_802_11_MODE_UNKNOWN;
|
return NM_802_11_MODE_UNKNOWN;
|
||||||
|
|
||||||
return iface_info.mode;
|
return iface_info.mode;
|
||||||
|
|
@ -356,7 +330,7 @@ wifi_nl80211_set_mode (WifiData *data, const NM80211Mode mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = nl80211_send_and_recv (nl80211, msg, NULL, NULL);
|
err = nl80211_send_and_recv (nl80211, msg, NULL, NULL);
|
||||||
return err ? FALSE : TRUE;
|
return err >= 0;
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free (msg);
|
nlmsg_free (msg);
|
||||||
|
|
@ -374,7 +348,7 @@ wifi_nl80211_set_powersave (WifiData *data, guint32 powersave)
|
||||||
NLA_PUT_U32 (msg, NL80211_ATTR_PS_STATE,
|
NLA_PUT_U32 (msg, NL80211_ATTR_PS_STATE,
|
||||||
powersave == 1 ? NL80211_PS_ENABLED : NL80211_PS_DISABLED);
|
powersave == 1 ? NL80211_PS_ENABLED : NL80211_PS_DISABLED);
|
||||||
err = nl80211_send_and_recv (nl80211, msg, NULL, NULL);
|
err = nl80211_send_and_recv (nl80211, msg, NULL, NULL);
|
||||||
return err ? FALSE : TRUE;
|
return err >= 0;
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free (msg);
|
nlmsg_free (msg);
|
||||||
|
|
@ -702,7 +676,7 @@ wifi_nl80211_indicate_addressing_running (WifiData *data, gboolean running)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = nl80211_send_and_recv (nl80211, msg, NULL, NULL);
|
err = nl80211_send_and_recv (nl80211, msg, NULL, NULL);
|
||||||
return err ? FALSE : TRUE;
|
return err >= 0;
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_free (msg);
|
nlmsg_free (msg);
|
||||||
|
|
@ -991,10 +965,6 @@ wifi_nl80211_init (int ifindex)
|
||||||
if (nl80211->id < 0)
|
if (nl80211->id < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
nl80211->nl_cb = nl_cb_alloc (NL_CB_DEFAULT);
|
|
||||||
if (nl80211->nl_cb == NULL)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
nl80211->phy = -1;
|
nl80211->phy = -1;
|
||||||
|
|
||||||
msg = nl80211_alloc_msg (nl80211, NL80211_CMD_GET_WIPHY, 0);
|
msg = nl80211_alloc_msg (nl80211, NL80211_CMD_GET_WIPHY, 0);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue