summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-02-22 10:08:59 +0100
committerThomas Haller <thaller@redhat.com>2019-02-22 10:08:59 +0100
commit57d0d94ba9e4b5346c5b1678e1b440c979ee2676 (patch)
tree888d7f4c8c2eec438021fbc607313c08e7942bba
parentfefb965cfe0b83885e8e4b0c6b0fd27e5c86100d (diff)
parentbf863aba937ef50927c76c326e77fcb3c6aaa6b9 (diff)
downloadNetworkManager-57d0d94ba9e4b5346c5b1678e1b440c979ee2676.tar.gz
platform: merge branch 'th/platform-netlink-cleanup'
https://github.com/NetworkManager/NetworkManager/pull/299
-rw-r--r--shared/nm-utils/nm-hash-utils.h3
-rw-r--r--shared/nm-utils/nm-shared-utils.c58
-rw-r--r--shared/nm-utils/nm-shared-utils.h6
-rw-r--r--shared/nm-utils/tests/test-shared-general.c32
-rw-r--r--src/platform/nm-linux-platform.c642
-rw-r--r--src/platform/nm-netlink.c171
-rw-r--r--src/platform/nm-netlink.h235
-rw-r--r--src/platform/nmp-object.c11
-rw-r--r--src/platform/nmp-object.h3
-rw-r--r--src/platform/wifi/nm-wifi-utils-nl80211.c198
-rw-r--r--src/platform/wpan/nm-wpan-utils.c18
11 files changed, 864 insertions, 513 deletions
diff --git a/shared/nm-utils/nm-hash-utils.h b/shared/nm-utils/nm-hash-utils.h
index cf71a7e9f2..1a1e44f50b 100644
--- a/shared/nm-utils/nm-hash-utils.h
+++ b/shared/nm-utils/nm-hash-utils.h
@@ -122,6 +122,9 @@ nm_hash_update (NMHashState *state, const void *ptr, gsize n)
nm_hash_update ((state), &_val, sizeof (_val)); \
} G_STMT_END
+#define nm_hash_update_valp(state, val) \
+ nm_hash_update ((state), (val), sizeof (*(val))) \
+
static inline void
nm_hash_update_bool (NMHashState *state, bool val)
{
diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c
index f48513e02f..270cbb852e 100644
--- a/shared/nm-utils/nm-shared-utils.c
+++ b/shared/nm-utils/nm-shared-utils.c
@@ -38,6 +38,64 @@ const void *const _NM_PTRARRAY_EMPTY[1] = { NULL };
const NMIPAddr nm_ip_addr_zero = { };
+/* this initializes a struct in_addr/in6_addr and allows for untrusted
+ * arguments (like unsuitable @addr_family or @src_len). It's almost safe
+ * in the sense that it verifies input arguments strictly. Also, it
+ * uses memcpy() to access @src, so alignment is not an issue.
+ *
+ * Only potential pitfalls:
+ *
+ * - it allows for @addr_family to be AF_UNSPEC. If that is the case (and the
+ * caller allows for that), the caller MUST provide @out_addr_family.
+ * - when setting @dst to an IPv4 address, the trailing bytes are not touched.
+ * Meaning, if @dst is an NMIPAddr union, only the first bytes will be set.
+ * If that matter to you, clear @dst before. */
+gboolean
+nm_ip_addr_set_from_untrusted (int addr_family,
+ gpointer dst,
+ gconstpointer src,
+ gsize src_len,
+ int *out_addr_family)
+{
+ nm_assert (dst);
+
+ switch (addr_family) {
+ case AF_UNSPEC:
+ if (!out_addr_family) {
+ /* when the callers allow undefined @addr_family, they must provide
+ * an @out_addr_family argument. */
+ nm_assert_not_reached ();
+ return FALSE;
+ }
+ switch (src_len) {
+ case sizeof (struct in_addr): addr_family = AF_INET; break;
+ case sizeof (struct in6_addr): addr_family = AF_INET6; break;
+ default:
+ return FALSE;
+ }
+ break;
+ case AF_INET:
+ if (src_len != sizeof (struct in_addr))
+ return FALSE;
+ break;
+ case AF_INET6:
+ if (src_len != sizeof (struct in6_addr))
+ return FALSE;
+ break;
+ default:
+ /* when the callers allow undefined @addr_family, they must provide
+ * an @out_addr_family argument. */
+ nm_assert (out_addr_family);
+ return FALSE;
+ }
+
+ nm_assert (src);
+
+ memcpy (dst, src, src_len);
+ NM_SET_OUT (out_addr_family, addr_family);
+ return TRUE;
+}
+
/*****************************************************************************/
pid_t
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
index c70ca86e86..4591ab41ac 100644
--- a/shared/nm-utils/nm-shared-utils.h
+++ b/shared/nm-utils/nm-shared-utils.h
@@ -140,6 +140,12 @@ nm_ip_addr_set (int addr_family, gpointer dst, gconstpointer src)
: sizeof (struct in6_addr));
}
+gboolean nm_ip_addr_set_from_untrusted (int addr_family,
+ gpointer dst,
+ gconstpointer src,
+ gsize src_len,
+ int *out_addr_family);
+
static inline gboolean
nm_ip4_addr_is_localhost (in_addr_t addr4)
{
diff --git a/shared/nm-utils/tests/test-shared-general.c b/shared/nm-utils/tests/test-shared-general.c
index b262757879..d53b21d972 100644
--- a/shared/nm-utils/tests/test-shared-general.c
+++ b/shared/nm-utils/tests/test-shared-general.c
@@ -23,6 +23,7 @@
#include "nm-utils/nm-time-utils.h"
#include "nm-utils/nm-random-utils.h"
+#include "nm-utils/unaligned.h"
#include "nm-utils/nm-test-utils.h"
@@ -217,6 +218,36 @@ test_nm_ip4_addr_is_localhost (void)
/*****************************************************************************/
+static void
+test_unaligned (void)
+{
+ int shift;
+
+ for (shift = 0; shift <= 32; shift++) {
+ guint8 buf[100] = { };
+ guint8 val = 0;
+
+ while (val == 0)
+ val = nmtst_get_rand_int () % 256;
+
+ buf[shift] = val;
+
+ g_assert_cmpint (unaligned_read_le64 (&buf[shift]), ==, (guint64) val);
+ g_assert_cmpint (unaligned_read_be64 (&buf[shift]), ==, ((guint64) val) << 56);
+ g_assert_cmpint (unaligned_read_ne64 (&buf[shift]), !=, 0);
+
+ g_assert_cmpint (unaligned_read_le32 (&buf[shift]), ==, (guint32) val);
+ g_assert_cmpint (unaligned_read_be32 (&buf[shift]), ==, ((guint32) val) << 24);
+ g_assert_cmpint (unaligned_read_ne32 (&buf[shift]), !=, 0);
+
+ g_assert_cmpint (unaligned_read_le16 (&buf[shift]), ==, (guint16) val);
+ g_assert_cmpint (unaligned_read_be16 (&buf[shift]), ==, ((guint16) val) << 8);
+ g_assert_cmpint (unaligned_read_ne16 (&buf[shift]), !=, 0);
+ }
+}
+
+/*****************************************************************************/
+
NMTST_DEFINE ();
int main (int argc, char **argv)
@@ -229,6 +260,7 @@ int main (int argc, char **argv)
g_test_add_func ("/general/test_nm_strdup_int", test_nm_strdup_int);
g_test_add_func ("/general/test_nm_strndup_a", test_nm_strndup_a);
g_test_add_func ("/general/test_nm_ip4_addr_is_localhost", test_nm_ip4_addr_is_localhost);
+ g_test_add_func ("/general/test_unaligned", test_unaligned);
return g_test_run ();
}
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 09f75a80cf..f6b04833d9 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -21,23 +21,23 @@
#include "nm-linux-platform.h"
-#include <poll.h>
+#include <arpa/inet.h>
+#include <dlfcn.h>
#include <endian.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
#include <fcntl.h>
-#include <dlfcn.h>
-#include <arpa/inet.h>
-#include <netinet/icmp6.h>
-#include <netinet/in.h>
+#include <libudev.h>
#include <linux/ip.h>
#include <linux/if_arp.h>
#include <linux/if_link.h>
#include <linux/if_tun.h>
#include <linux/if_tunnel.h>
#include <linux/ip6_tunnel.h>
-#include <libudev.h>
+#include <netinet/icmp6.h>
+#include <netinet/in.h>
+#include <poll.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
#include "nm-utils.h"
#include "nm-core-internal.h"
@@ -321,8 +321,22 @@ typedef enum {
} DelayedActionType;
#define FOR_EACH_DELAYED_ACTION(iflags, flags_all) \
- for ((iflags) = (DelayedActionType) 0x1LL; (iflags) <= DELAYED_ACTION_TYPE_MAX; (iflags) <<= 1) \
- if (NM_FLAGS_ANY (flags_all, iflags))
+ for ((iflags) = (DelayedActionType) 0x1LL; \
+ ({ \
+ gboolean _good = FALSE; \
+ \
+ nm_assert (nm_utils_is_power_of_two (iflags)); \
+ \
+ while ((iflags) <= DELAYED_ACTION_TYPE_MAX) { \
+ if (NM_FLAGS_ANY ((flags_all), (iflags))) { \
+ _good = TRUE; \
+ break; \
+ } \
+ (iflags) <<= 1; \
+ } \
+ _good; \
+ }); \
+ (iflags) <<= 1)
typedef enum {
/* Negative values are errors from kernel. Add dummy member to
@@ -1099,7 +1113,7 @@ _linktype_get_type (NMPlatform *platform,
******************************************************************/
#define NLMSG_TAIL(nmsg) \
- ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+ ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN ((nmsg)->nlmsg_len)))
/* copied from iproute2's addattr_l(). */
static gboolean
@@ -1153,31 +1167,29 @@ _parse_af_inet6 (NMPlatform *platform,
guint8 *out_addr_gen_mode_inv,
gboolean *out_addr_gen_mode_valid)
{
- static const struct nla_policy policy[IFLA_INET6_MAX+1] = {
+ static const struct nla_policy policy[] = {
[IFLA_INET6_FLAGS] = { .type = NLA_U32 },
[IFLA_INET6_CACHEINFO] = { .minlen = nm_offsetofend (struct ifla_cacheinfo, retrans_time) },
[IFLA_INET6_CONF] = { .minlen = 4 },
[IFLA_INET6_STATS] = { .minlen = 8 },
[IFLA_INET6_ICMP6STATS] = { .minlen = 8 },
- [IFLA_INET6_TOKEN] = { .minlen = sizeof(struct in6_addr) },
+ [IFLA_INET6_TOKEN] = { .minlen = sizeof (struct in6_addr) },
[IFLA_INET6_ADDR_GEN_MODE] = { .type = NLA_U8 },
};
- struct nlattr *tb[IFLA_INET6_MAX+1];
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
struct in6_addr i6_token;
gboolean token_valid = FALSE;
gboolean addr_gen_mode_valid = FALSE;
guint8 i6_addr_gen_mode_inv = 0;
- err = nla_parse_nested (tb, IFLA_INET6_MAX, attr, policy);
- if (err < 0)
+ if (nla_parse_nested_arr (tb, attr, policy) < 0)
return FALSE;
- if (tb[IFLA_INET6_CONF] && nla_len(tb[IFLA_INET6_CONF]) % 4)
+ if (tb[IFLA_INET6_CONF] && nla_len (tb[IFLA_INET6_CONF]) % 4)
return FALSE;
- if (tb[IFLA_INET6_STATS] && nla_len(tb[IFLA_INET6_STATS]) % 8)
+ if (tb[IFLA_INET6_STATS] && nla_len (tb[IFLA_INET6_STATS]) % 8)
return FALSE;
- if (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) % 8)
+ if (tb[IFLA_INET6_ICMP6STATS] && nla_len (tb[IFLA_INET6_ICMP6STATS]) % 8)
return FALSE;
if (_check_addr_or_return_val (tb, IFLA_INET6_TOKEN, sizeof (struct in6_addr), FALSE)) {
@@ -1217,7 +1229,7 @@ _parse_af_inet6 (NMPlatform *platform,
static NMPObject *
_parse_lnk_gre (const char *kind, struct nlattr *info_data)
{
- static const struct nla_policy policy[IFLA_GRE_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[IFLA_GRE_LINK] = { .type = NLA_U32 },
[IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
[IFLA_GRE_OFLAGS] = { .type = NLA_U16 },
@@ -1229,13 +1241,13 @@ _parse_lnk_gre (const char *kind, struct nlattr *info_data)
[IFLA_GRE_TOS] = { .type = NLA_U8 },
[IFLA_GRE_PMTUDISC] = { .type = NLA_U8 },
};
- struct nlattr *tb[IFLA_GRE_MAX + 1];
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
NMPObject *obj;
NMPlatformLnkGre *props;
gboolean is_tap;
- if (!info_data || !kind)
+ if ( !info_data
+ || !kind)
return NULL;
if (nm_streq (kind, "gretap"))
@@ -1245,8 +1257,7 @@ _parse_lnk_gre (const char *kind, struct nlattr *info_data)
else
return NULL;
- err = nla_parse_nested (tb, IFLA_GRE_MAX, info_data, policy);
- if (err < 0)
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
return NULL;
obj = nmp_object_new (is_tap ? NMP_OBJECT_TYPE_LNK_GRETAP : NMP_OBJECT_TYPE_LNK_GRE, NULL);
@@ -1286,25 +1297,25 @@ _parse_lnk_gre (const char *kind, struct nlattr *info_data)
static NMPObject *
_parse_lnk_infiniband (const char *kind, struct nlattr *info_data)
{
- static const struct nla_policy policy[IFLA_IPOIB_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[IFLA_IPOIB_PKEY] = { .type = NLA_U16 },
[IFLA_IPOIB_MODE] = { .type = NLA_U16 },
[IFLA_IPOIB_UMCAST] = { .type = NLA_U16 },
};
- struct nlattr *tb[IFLA_IPOIB_MAX + 1];
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
NMPlatformLnkInfiniband *info;
NMPObject *obj;
- int err;
const char *mode;
- if (!info_data || g_strcmp0 (kind, "ipoib"))
+ if ( !info_data
+ || !nm_streq0 (kind, "ipoib"))
return NULL;
- err = nla_parse_nested (tb, IFLA_IPOIB_MAX, info_data, policy);
- if (err < 0)
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
return NULL;
- if (!tb[IFLA_IPOIB_PKEY] || !tb[IFLA_IPOIB_MODE])
+ if ( !tb[IFLA_IPOIB_PKEY]
+ || !tb[IFLA_IPOIB_MODE])
return NULL;
switch (nla_get_u16 (tb[IFLA_IPOIB_MODE])) {
@@ -1332,29 +1343,26 @@ _parse_lnk_infiniband (const char *kind, struct nlattr *info_data)
static NMPObject *
_parse_lnk_ip6tnl (const char *kind, struct nlattr *info_data)
{
- static const struct nla_policy policy[IFLA_IPTUN_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[IFLA_IPTUN_LINK] = { .type = NLA_U32 },
- [IFLA_IPTUN_LOCAL] = { .type = NLA_UNSPEC,
- .minlen = sizeof (struct in6_addr)},
- [IFLA_IPTUN_REMOTE] = { .type = NLA_UNSPEC,
- .minlen = sizeof (struct in6_addr)},
+ [IFLA_IPTUN_LOCAL] = { .minlen = sizeof (struct in6_addr)},
+ [IFLA_IPTUN_REMOTE] = { .minlen = sizeof (struct in6_addr)},
[IFLA_IPTUN_TTL] = { .type = NLA_U8 },
[IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 },
[IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 },
[IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
[IFLA_IPTUN_FLAGS] = { .type = NLA_U32 },
};
- struct nlattr *tb[IFLA_IPTUN_MAX + 1];
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
NMPObject *obj;
NMPlatformLnkIp6Tnl *props;
guint32 flowinfo;
- if (!info_data || g_strcmp0 (kind, "ip6tnl"))
+ if ( !info_data
+ || !nm_streq0 (kind, "ip6tnl"))
return NULL;
- err = nla_parse_nested (tb, IFLA_IPTUN_MAX, info_data, policy);
- if (err < 0)
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
return NULL;
obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_IP6TNL, NULL);
@@ -1363,9 +1371,9 @@ _parse_lnk_ip6tnl (const char *kind, struct nlattr *info_data)
if (tb[IFLA_IPTUN_LINK])
props->parent_ifindex = nla_get_u32 (tb[IFLA_IPTUN_LINK]);
if (tb[IFLA_IPTUN_LOCAL])
- memcpy (&props->local, nla_data (tb[IFLA_IPTUN_LOCAL]), sizeof (props->local));
+ props->local = *nla_data_as (struct in6_addr, tb[IFLA_IPTUN_LOCAL]);
if (tb[IFLA_IPTUN_REMOTE])
- memcpy (&props->remote, nla_data (tb[IFLA_IPTUN_REMOTE]), sizeof (props->remote));
+ props->remote = *nla_data_as (struct in6_addr, tb[IFLA_IPTUN_REMOTE]);
if (tb[IFLA_IPTUN_TTL])
props->ttl = nla_get_u8 (tb[IFLA_IPTUN_TTL]);
if (tb[IFLA_IPTUN_ENCAP_LIMIT])
@@ -1386,23 +1394,22 @@ _parse_lnk_ip6tnl (const char *kind, struct nlattr *info_data)
static NMPObject *
_parse_lnk_ip6gre (const char *kind, struct nlattr *info_data)
{
- static const struct nla_policy policy[IFLA_GRE_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[IFLA_GRE_LINK] = { .type = NLA_U32 },
[IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
[IFLA_GRE_OFLAGS] = { .type = NLA_U16 },
[IFLA_GRE_IKEY] = { .type = NLA_U32 },
[IFLA_GRE_OKEY] = { .type = NLA_U32 },
[IFLA_GRE_LOCAL] = { .type = NLA_UNSPEC,
- .minlen = sizeof (struct in6_addr)},
+ .minlen = sizeof (struct in6_addr)},
[IFLA_GRE_REMOTE] = { .type = NLA_UNSPEC,
- .minlen = sizeof (struct in6_addr)},
+ .minlen = sizeof (struct in6_addr)},
[IFLA_GRE_TTL] = { .type = NLA_U8 },
[IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 },
[IFLA_GRE_FLOWINFO] = { .type = NLA_U32 },
[IFLA_GRE_FLAGS] = { .type = NLA_U32 },
};
- struct nlattr *tb[IFLA_GRE_MAX + 1];
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
NMPObject *obj;
NMPlatformLnkIp6Tnl *props;
guint32 flowinfo;
@@ -1418,8 +1425,7 @@ _parse_lnk_ip6gre (const char *kind, struct nlattr *info_data)
else
return NULL;
- err = nla_parse_nested (tb, IFLA_GRE_MAX, info_data, policy);
- if (err < 0)
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
return NULL;
obj = nmp_object_new (is_tap ? NMP_OBJECT_TYPE_LNK_IP6GRETAP : NMP_OBJECT_TYPE_LNK_IP6GRE, NULL);
@@ -1438,9 +1444,9 @@ _parse_lnk_ip6gre (const char *kind, struct nlattr *info_data)
if (tb[IFLA_GRE_OKEY])
props->output_key = ntohl (nla_get_u32 (tb[IFLA_GRE_OKEY]));
if (tb[IFLA_GRE_LOCAL])
- memcpy (&props->local, nla_data (tb[IFLA_GRE_LOCAL]), sizeof (props->local));
+ props->local = *nla_data_as (struct in6_addr, tb[IFLA_GRE_LOCAL]);
if (tb[IFLA_GRE_REMOTE])
- memcpy (&props->remote, nla_data (tb[IFLA_GRE_REMOTE]), sizeof (props->remote));
+ props->remote = *nla_data_as (struct in6_addr, tb[IFLA_GRE_REMOTE]);
if (tb[IFLA_GRE_TTL])
props->ttl = nla_get_u8 (tb[IFLA_GRE_TTL]);
if (tb[IFLA_GRE_ENCAP_LIMIT])
@@ -1461,7 +1467,7 @@ _parse_lnk_ip6gre (const char *kind, struct nlattr *info_data)
static NMPObject *
_parse_lnk_ipip (const char *kind, struct nlattr *info_data)
{
- static const struct nla_policy policy[IFLA_IPTUN_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[IFLA_IPTUN_LINK] = { .type = NLA_U32 },
[IFLA_IPTUN_LOCAL] = { .type = NLA_U32 },
[IFLA_IPTUN_REMOTE] = { .type = NLA_U32 },
@@ -1469,16 +1475,15 @@ _parse_lnk_ipip (const char *kind, struct nlattr *info_data)
[IFLA_IPTUN_TOS] = { .type = NLA_U8 },
[IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
};
- struct nlattr *tb[IFLA_IPTUN_MAX + 1];
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
NMPObject *obj;
NMPlatformLnkIpIp *props;
- if (!info_data || g_strcmp0 (kind, "ipip"))
+ if ( !info_data
+ || !nm_streq0 (kind, "ipip"))
return NULL;
- err = nla_parse_nested (tb, IFLA_IPTUN_MAX, info_data, policy);
- if (err < 0)
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
return NULL;
obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_IPIP, NULL);
@@ -1499,28 +1504,27 @@ _parse_lnk_ipip (const char *kind, struct nlattr *info_data)
static NMPObject *
_parse_lnk_macvlan (const char *kind, struct nlattr *info_data)
{
- static const struct nla_policy policy[IFLA_MACVLAN_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
[IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 },
};
NMPlatformLnkMacvlan *props;
- struct nlattr *tb[IFLA_MACVLAN_MAX + 1];
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
NMPObject *obj;
gboolean tap;
- if (!info_data)
+ if ( !info_data
+ || !kind)
return NULL;
- if (!g_strcmp0 (kind, "macvlan"))
+ if (nm_streq (kind, "macvlan"))
tap = FALSE;
- else if (!g_strcmp0 (kind, "macvtap"))
+ else if (nm_streq (kind, "macvtap"))
tap = TRUE;
else
return NULL;
- err = nla_parse_nested (tb, IFLA_MACVLAN_MAX, info_data, policy);
- if (err < 0)
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
return NULL;
if (!tb[IFLA_MACVLAN_MODE])
@@ -1542,7 +1546,7 @@ _parse_lnk_macvlan (const char *kind, struct nlattr *info_data)
static NMPObject *
_parse_lnk_macsec (const char *kind, struct nlattr *info_data)
{
- static const struct nla_policy policy[__IFLA_MACSEC_MAX] = {
+ static const struct nla_policy policy[] = {
[IFLA_MACSEC_SCI] = { .type = NLA_U64 },
[IFLA_MACSEC_ICV_LEN] = { .type = NLA_U8 },
[IFLA_MACSEC_CIPHER_SUITE] = { .type = NLA_U64 },
@@ -1556,33 +1560,32 @@ _parse_lnk_macsec (const char *kind, struct nlattr *info_data)
[IFLA_MACSEC_REPLAY_PROTECT] = { .type = NLA_U8 },
[IFLA_MACSEC_VALIDATION] = { .type = NLA_U8 },
};
- struct nlattr *tb[__IFLA_MACSEC_MAX];
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
NMPObject *obj;
NMPlatformLnkMacsec *props;
- if (!info_data || !nm_streq0 (kind, "macsec"))
+ if ( !info_data
+ || !nm_streq0 (kind, "macsec"))
return NULL;
- err = nla_parse_nested (tb, __IFLA_MACSEC_MAX - 1, info_data, policy);
- if (err < 0)
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
return NULL;
obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_MACSEC, NULL);
props = &obj->lnk_macsec;
- props->sci = tb[IFLA_MACSEC_SCI] ? be64toh (nla_get_u64 (tb[IFLA_MACSEC_SCI])) : 0;
- props->icv_length = tb[IFLA_MACSEC_ICV_LEN] ? nla_get_u8 (tb[IFLA_MACSEC_ICV_LEN]) : 0;
- props->cipher_suite = tb [IFLA_MACSEC_CIPHER_SUITE] ? nla_get_u64 (tb[IFLA_MACSEC_CIPHER_SUITE]) : 0;
- props->window = tb [IFLA_MACSEC_WINDOW] ? nla_get_u32 (tb[IFLA_MACSEC_WINDOW]) : 0;
- props->encoding_sa = tb[IFLA_MACSEC_ENCODING_SA] ? !!nla_get_u8 (tb[IFLA_MACSEC_ENCODING_SA]) : 0;
- props->encrypt = tb[IFLA_MACSEC_ENCRYPT] ? !!nla_get_u8 (tb[IFLA_MACSEC_ENCRYPT]) : 0;
- props->protect = tb[IFLA_MACSEC_PROTECT] ? !!nla_get_u8 (tb[IFLA_MACSEC_PROTECT]) : 0;
- props->include_sci = tb[IFLA_MACSEC_INC_SCI] ? !!nla_get_u8 (tb[IFLA_MACSEC_INC_SCI]) : 0;
- props->es = tb[IFLA_MACSEC_ES] ? !!nla_get_u8 (tb[IFLA_MACSEC_ES]) : 0;
- props->scb = tb[IFLA_MACSEC_SCB] ? !!nla_get_u8 (tb[IFLA_MACSEC_SCB]) : 0;
- props->replay_protect = tb[IFLA_MACSEC_REPLAY_PROTECT] ? !!nla_get_u8 (tb[IFLA_MACSEC_REPLAY_PROTECT]) : 0;
- props->validation = tb[IFLA_MACSEC_VALIDATION] ? nla_get_u8 (tb[IFLA_MACSEC_VALIDATION]) : 0;
+ if (tb[IFLA_MACSEC_SCI]) { props->sci = nla_get_be64 (tb[IFLA_MACSEC_SCI]); }
+ if (tb[IFLA_MACSEC_ICV_LEN]) { props->icv_length = nla_get_u8 (tb[IFLA_MACSEC_ICV_LEN]); }
+ if (tb[IFLA_MACSEC_CIPHER_SUITE]) { props->cipher_suite = nla_get_u64 (tb[IFLA_MACSEC_CIPHER_SUITE]); }
+ if (tb[IFLA_MACSEC_WINDOW]) { props->window = nla_get_u32 (tb[IFLA_MACSEC_WINDOW]); }
+ if (tb[IFLA_MACSEC_ENCODING_SA]) { props->encoding_sa = !!nla_get_u8 (tb[IFLA_MACSEC_ENCODING_SA]); }
+ if (tb[IFLA_MACSEC_ENCRYPT]) { props->encrypt = !!nla_get_u8 (tb[IFLA_MACSEC_ENCRYPT]); }
+ if (tb[IFLA_MACSEC_PROTECT]) { props->protect = !!nla_get_u8 (tb[IFLA_MACSEC_PROTECT]); }
+ if (tb[IFLA_MACSEC_INC_SCI]) { props->include_sci = !!nla_get_u8 (tb[IFLA_MACSEC_INC_SCI]); }
+ if (tb[IFLA_MACSEC_ES]) { props->es = !!nla_get_u8 (tb[IFLA_MACSEC_ES]); }
+ if (tb[IFLA_MACSEC_SCB]) { props->scb = !!nla_get_u8 (tb[IFLA_MACSEC_SCB]); }
+ if (tb[IFLA_MACSEC_REPLAY_PROTECT]) { props->replay_protect = !!nla_get_u8 (tb[IFLA_MACSEC_REPLAY_PROTECT]); }
+ if (tb[IFLA_MACSEC_VALIDATION]) { props->validation = nla_get_u8 (tb[IFLA_MACSEC_VALIDATION]); }
return obj;
}
@@ -1592,7 +1595,7 @@ _parse_lnk_macsec (const char *kind, struct nlattr *info_data)
static NMPObject *
_parse_lnk_sit (const char *kind, struct nlattr *info_data)
{
- static const struct nla_policy policy[IFLA_IPTUN_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[IFLA_IPTUN_LINK] = { .type = NLA_U32 },
[IFLA_IPTUN_LOCAL] = { .type = NLA_U32 },
[IFLA_IPTUN_REMOTE] = { .type = NLA_U32 },
@@ -1602,16 +1605,15 @@ _parse_lnk_sit (const char *kind, struct nlattr *info_data)
[IFLA_IPTUN_FLAGS] = { .type = NLA_U16 },
[IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
};
- struct nlattr *tb[IFLA_IPTUN_MAX + 1];
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
NMPObject *obj;
NMPlatformLnkSit *props;
- if (!info_data || g_strcmp0 (kind, "sit"))
+ if ( !info_data
+ || !nm_streq0 (kind, "sit"))
return NULL;
- err = nla_parse_nested (tb, IFLA_IPTUN_MAX, info_data, policy);
- if (err < 0)
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
return NULL;
obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_SIT, NULL);
@@ -1634,7 +1636,7 @@ _parse_lnk_sit (const char *kind, struct nlattr *info_data)
static NMPObject *
_parse_lnk_tun (const char *kind, struct nlattr *info_data)
{
- static const struct nla_policy policy[IFLA_TUN_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[IFLA_TUN_OWNER] = { .type = NLA_U32 },
[IFLA_TUN_GROUP] = { .type = NLA_U32 },
[IFLA_TUN_TYPE] = { .type = NLA_U8 },
@@ -1645,22 +1647,19 @@ _parse_lnk_tun (const char *kind, struct nlattr *info_data)
[IFLA_TUN_NUM_QUEUES] = { .type = NLA_U32 },
[IFLA_TUN_NUM_DISABLED_QUEUES] = { .type = NLA_U32 },
};
- struct nlattr *tb[IFLA_TUN_MAX + 1];
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
NMPObject *obj;
NMPlatformLnkTun *props;
- if (!info_data || !nm_streq0 (kind, "tun"))
+ if ( !info_data
+ || !nm_streq0 (kind, "tun"))
return NULL;
- err = nla_parse_nested (tb, IFLA_TUN_MAX, info_data, policy);
- if (err < 0)
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
return NULL;
- if (!tb[IFLA_TUN_TYPE]) {
- /* we require at least a type. */
+ if (!tb[IFLA_TUN_TYPE])
return NULL;
- }
obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_TUN, NULL);
props = &obj->lnk_tun;
@@ -1707,7 +1706,7 @@ _vlan_qos_mapping_from_nla (struct nlattr *nlattr,
array = g_ptr_array_new ();
nla_for_each_nested (nla, nlattr, remaining) {
- if (nla_len (nla) < sizeof(NMVlanQosMapping))
+ if (nla_len (nla) < sizeof (NMVlanQosMapping))
return FALSE;
g_ptr_array_add (array, nla_data (nla));
}
@@ -1748,22 +1747,22 @@ _vlan_qos_mapping_from_nla (struct nlattr *nlattr,
static NMPObject *
_parse_lnk_vlan (const char *kind, struct nlattr *info_data)
{
- static const struct nla_policy policy[IFLA_VLAN_MAX+1] = {
+ static const struct nla_policy policy[] = {
[IFLA_VLAN_ID] = { .type = NLA_U16 },
[IFLA_VLAN_FLAGS] = { .minlen = nm_offsetofend (struct ifla_vlan_flags, flags) },
[IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED },
[IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED },
[IFLA_VLAN_PROTOCOL] = { .type = NLA_U16 },
};
- struct nlattr *tb[IFLA_VLAN_MAX+1];
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
nm_auto_nmpobj NMPObject *obj = NULL;
NMPObject *obj_result;
- if (!info_data || g_strcmp0 (kind, "vlan"))
+ if ( !info_data
+ || !nm_streq0 (kind, "vlan"))
return NULL;
- if ((err = nla_parse_nested (tb, IFLA_VLAN_MAX, info_data, policy)) < 0)
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
return NULL;
if (!tb[IFLA_VLAN_ID])
@@ -1775,7 +1774,7 @@ _parse_lnk_vlan (const char *kind, struct nlattr *info_data)
if (tb[IFLA_VLAN_FLAGS]) {
struct ifla_vlan_flags flags;
- nla_memcpy (&flags, tb[IFLA_VLAN_FLAGS], sizeof(flags));
+ nla_memcpy (&flags, tb[IFLA_VLAN_FLAGS], sizeof (flags));
obj->lnk_vlan.flags = flags.flags;
}
@@ -1833,7 +1832,7 @@ struct nm_ifla_vxlan_port_range {
static NMPObject *
_parse_lnk_vxlan (const char *kind, struct nlattr *info_data)
{
- static const struct nla_policy policy[IFLA_VXLAN_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[IFLA_VXLAN_ID] = { .type = NLA_U32 },
[IFLA_VXLAN_GROUP] = { .type = NLA_U32 },
[IFLA_VXLAN_GROUP6] = { .type = NLA_UNSPEC,
@@ -1856,16 +1855,14 @@ _parse_lnk_vxlan (const char *kind, struct nlattr *info_data)
[IFLA_VXLAN_PORT] = { .type = NLA_U16 },
};
NMPlatformLnkVxlan *props;
- struct nlattr *tb[IFLA_VXLAN_MAX + 1];
- struct nm_ifla_vxlan_port_range *range;
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
NMPObject *obj;
- if (!info_data || g_strcmp0 (kind, "vxlan"))
+ if ( !info_data
+ || !nm_streq0 (kind, "vxlan"))
return NULL;
- err = nla_parse_nested (tb, IFLA_VXLAN_MAX, info_data, policy);
- if (err < 0)
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
return NULL;
obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_VXLAN, NULL);
@@ -1880,10 +1877,10 @@ _parse_lnk_vxlan (const char *kind, struct nlattr *info_data)
props->group = nla_get_u32 (tb[IFLA_VXLAN_GROUP]);
if (tb[IFLA_VXLAN_LOCAL])
props->local = nla_get_u32 (tb[IFLA_VXLAN_LOCAL]);
- if (tb[IFLA_VXLAN_GROUP6])
- memcpy (&props->group6, nla_data (tb[IFLA_VXLAN_GROUP6]), sizeof (props->group6));
if (tb[IFLA_VXLAN_LOCAL6])
- memcpy (&props->local6, nla_data (tb[IFLA_VXLAN_LOCAL6]), sizeof (props->local6));
+ props->local6 = *nla_data_as (struct in6_addr, tb[IFLA_VXLAN_LOCAL6]);
+ if (tb[IFLA_VXLAN_GROUP6])
+ props->group6 = *nla_data_as (struct in6_addr, tb[IFLA_VXLAN_GROUP6]);
if (tb[IFLA_VXLAN_AGEING])
props->ageing = nla_get_u32 (tb[IFLA_VXLAN_AGEING]);
@@ -1898,7 +1895,9 @@ _parse_lnk_vxlan (const char *kind, struct nlattr *info_data)
props->dst_port = ntohs (nla_get_u16 (tb[IFLA_VXLAN_PORT]));
if (tb[IFLA_VXLAN_PORT_RANGE]) {
- range = nla_data (tb[IFLA_VXLAN_PORT_RANGE]);
+ struct nm_ifla_vxlan_port_range *range;
+
+ range = nla_data_as (struct nm_ifla_vxlan_port_range, tb[IFLA_VXLAN_PORT_RANGE]);
props->src_port_min = ntohs (range->low);
props->src_port_max = ntohs (range->high);
}
@@ -1923,16 +1922,16 @@ static gboolean
_wireguard_update_from_allowed_ips_nla (NMPWireGuardAllowedIP *allowed_ip,
struct nlattr *nlattr)
{
- static const struct nla_policy policy[WGALLOWEDIP_A_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[WGALLOWEDIP_A_FAMILY] = { .type = NLA_U16 },
[WGALLOWEDIP_A_IPADDR] = { .minlen = sizeof (struct in_addr) },
[WGALLOWEDIP_A_CIDR_MASK] = { .type = NLA_U8 },
};
- struct nlattr *tb[WGALLOWEDIP_A_MAX + 1];
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
int family;
int addr_len;
- if (nla_parse_nested (tb, WGALLOWEDIP_A_MAX, nlattr, policy) < 0)
+ if (nla_parse_nested_arr (tb, nlattr, policy) < 0)
return FALSE;
if (!tb[WGALLOWEDIP_A_FAMILY])
@@ -1972,7 +1971,7 @@ _wireguard_update_from_peers_nla (CList *peers,
GArray **p_allowed_ips,
struct nlattr *peer_attr)
{
- static const struct nla_policy policy[WGPEER_A_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[WGPEER_A_PUBLIC_KEY] = { .minlen = NMP_WIREGUARD_PUBLIC_KEY_LEN },
[WGPEER_A_PRESHARED_KEY] = { },
[WGPEER_A_FLAGS] = { .type = NLA_U32 },
@@ -1983,10 +1982,10 @@ _wireguard_update_from_peers_nla (CList *peers,
[WGPEER_A_TX_BYTES] = { .type = NLA_U64 },
[WGPEER_A_ALLOWEDIPS] = { .type = NLA_NESTED },
};
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
WireGuardPeerConstruct *peer_c;
- struct nlattr *tb[WGPEER_A_MAX + 1];
- if (nla_parse_nested (tb, WGPEER_A_MAX, peer_attr, policy) < 0)
+ if (nla_parse_nested_arr (tb, peer_attr, policy) < 0)
return FALSE;
if (!tb[WGPEER_A_PUBLIC_KEY])
@@ -2016,7 +2015,7 @@ _wireguard_update_from_peers_nla (CList *peers,
nm_sock_addr_union_cpy_untrusted (&peer_c->data.endpoint,
tb[WGPEER_A_ENDPOINT] ? nla_data (tb[WGPEER_A_ENDPOINT]) : NULL,
- tb[WGPEER_A_ENDPOINT] ? nla_len (tb[WGPEER_A_ENDPOINT]) : 0);
+ tb[WGPEER_A_ENDPOINT] ? nla_len (tb[WGPEER_A_ENDPOINT]) : 0);
if (tb[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL])
peer_c->data.persistent_keepalive_interval = nla_get_u16 (tb[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]);
@@ -2069,7 +2068,7 @@ typedef struct {
static int
_wireguard_get_device_cb (struct nl_msg *msg, void *arg)
{
- static const struct nla_policy policy[WGDEVICE_A_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[WGDEVICE_A_IFINDEX] = { .type = NLA_U32 },
[WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .maxlen = IFNAMSIZ },
[WGDEVICE_A_PRIVATE_KEY] = { },
@@ -2079,12 +2078,10 @@ _wireguard_get_device_cb (struct nl_msg *msg, void *arg)
[WGDEVICE_A_FWMARK] = { .type = NLA_U32 },
[WGDEVICE_A_PEERS] = { .type = NLA_NESTED },
};
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
WireGuardParseData *parse_data = arg;
- struct nlattr *tb[WGDEVICE_A_MAX + 1];
- int nlerr;
- nlerr = genlmsg_parse (nlmsg_hdr (msg), 0, tb, WGDEVICE_A_MAX, policy);
- if (nlerr < 0)
+ if (genlmsg_parse_arr (nlmsg_hdr (msg), 0, tb, policy) < 0)
return NL_SKIP;
if (tb[WGDEVICE_A_IFINDEX]) {
@@ -2649,7 +2646,7 @@ link_wireguard_change (NMPlatform *platform,
static NMPObject *
_new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr *nlh, gboolean id_only)
{
- static const struct nla_policy policy[IFLA_MAX+1] = {
+ static const struct nla_policy policy[] = {
[IFLA_IFNAME] = { .type = NLA_STRING,
.maxlen = IFNAMSIZ },
[IFLA_MTU] = { .type = NLA_U32 },
@@ -2676,18 +2673,12 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
[IFLA_PHYS_PORT_ID] = { .type = NLA_UNSPEC },
[IFLA_NET_NS_PID] = { .type = NLA_U32 },
[IFLA_NET_NS_FD] = { .type = NLA_U32 },
- };
- static const struct nla_policy policy_link_info[IFLA_INFO_MAX+1] = {
- [IFLA_INFO_KIND] = { .type = NLA_STRING },
- [IFLA_INFO_DATA] = { .type = NLA_NESTED },
- [IFLA_INFO_XSTATS] = { .type = NLA_NESTED },
+ [IFLA_LINK_NETNSID] = { },
};
const struct ifinfomsg *ifi;
- struct nlattr *tb[IFLA_MAX+1];
- struct nlattr *li[IFLA_INFO_MAX+1];
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
struct nlattr *nl_info_data = NULL;
const char *nl_info_kind = NULL;
- int err;
nm_auto_nmpobj NMPObject *obj = NULL;
gboolean completed_from_cache_val = FALSE;
gboolean *completed_from_cache = cache ? &completed_from_cache_val : NULL;
@@ -2701,6 +2692,7 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
if (!nlmsg_valid_hdr (nlh, sizeof (*ifi)))
return NULL;
+
ifi = nlmsg_data (nlh);
if (ifi->ifi_family != AF_UNSPEC)
@@ -2713,13 +2705,12 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
if (id_only)
return g_steal_pointer (&obj);
- err = nlmsg_parse (nlh, sizeof (*ifi), tb, IFLA_MAX, policy);
- if (err < 0)
+ if (nlmsg_parse_arr (nlh, sizeof (*ifi), tb, policy) < 0)
return NULL;
if (!tb[IFLA_IFNAME])
return NULL;
- nla_strlcpy(obj->link.name, tb[IFLA_IFNAME], IFNAMSIZ);
+ nla_strlcpy (obj->link.name, tb[IFLA_IFNAME], IFNAMSIZ);
if (!obj->link.name[0])
return NULL;
@@ -2741,8 +2732,14 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
obj->link.mtu = nla_get_u32 (tb[IFLA_MTU]);
if (tb[IFLA_LINKINFO]) {
- err = nla_parse_nested (li, IFLA_INFO_MAX, tb[IFLA_LINKINFO], policy_link_info);
- if (err < 0)
+ static const struct nla_policy policy_link_info[] = {
+ [IFLA_INFO_KIND] = { .type = NLA_STRING },
+ [IFLA_INFO_DATA] = { .type = NLA_NESTED },
+ [IFLA_INFO_XSTATS] = { .type = NLA_NESTED },
+ };
+ struct nlattr *li[G_N_ELEMENTS (policy_link_info)];
+
+ if (nla_parse_nested_arr (li, tb[IFLA_LINKINFO], policy_link_info) < 0)
return NULL;
if (li[IFLA_INFO_KIND])
@@ -2752,18 +2749,12 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
}
if (tb[IFLA_STATS64]) {
- /* tb[IFLA_STATS64] is only guaranteed to be 32bit-aligned,
- * so in general we can't access the rtnl_link_stats64 struct
- * members directly on 64bit architectures. */
- char *stats = nla_data (tb[IFLA_STATS64]);
-
-#define READ_STAT64(member) \
- unaligned_read_ne64 (stats + offsetof (struct rtnl_link_stats64, member))
+ const char *stats = nla_data (tb[IFLA_STATS64]);
- obj->link.rx_packets = READ_STAT64 (rx_packets);
- obj->link.rx_bytes = READ_STAT64 (rx_bytes);
- obj->link.tx_packets = READ_STAT64 (tx_packets);
- obj->link.tx_bytes = READ_STAT64 (tx_bytes);
+ obj->link.rx_packets = unaligned_read_ne64 (&stats[G_STRUCT_OFFSET (struct rtnl_link_stats64, rx_packets)]);
+ obj->link.rx_bytes = unaligned_read_ne64 (&stats[G_STRUCT_OFFSET (struct rtnl_link_stats64, rx_bytes)]);
+ obj->link.tx_packets = unaligned_read_ne64 (&stats[G_STRUCT_OFFSET (struct rtnl_link_stats64, tx_packets)]);
+ obj->link.tx_bytes = unaligned_read_ne64 (&stats[G_STRUCT_OFFSET (struct rtnl_link_stats64, tx_bytes)]);
}
obj->link.n_ifi_flags = ifi->ifi_flags;
@@ -2991,14 +2982,14 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
static NMPObject *
_new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
{
- static const struct nla_policy policy[IFA_MAX+1] = {
+ static const struct nla_policy policy[] = {
[IFA_LABEL] = { .type = NLA_STRING,
- .maxlen = IFNAMSIZ },
+ .maxlen = IFNAMSIZ },
[IFA_CACHEINFO] = { .minlen = nm_offsetofend (struct ifa_cacheinfo, tstamp) },
+ [IFA_FLAGS] = { },
};
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
const struct ifaddrmsg *ifa;
- struct nlattr *tb[IFA_MAX+1];
- int err;
gboolean is_v4;
nm_auto_nmpobj NMPObject *obj = NULL;
int addr_len;
@@ -3006,14 +2997,15 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
if (!nlmsg_valid_hdr (nlh, sizeof (*ifa)))
return NULL;
- ifa = nlmsg_data(nlh);
+
+ ifa = nlmsg_data (nlh);
if (!NM_IN_SET (ifa->ifa_family, AF_INET, AF_INET6))
return NULL;
+
is_v4 = ifa->ifa_family == AF_INET;
- err = nlmsg_parse (nlh, sizeof(*ifa), tb, IFA_MAX, policy);
- if (err < 0)
+ if (nlmsg_parse_arr (nlh, sizeof (*ifa), tb, policy) < 0)
return NULL;
addr_len = is_v4
@@ -3082,8 +3074,9 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
timestamp = 0;
/* IPv6 only */
if (tb[IFA_CACHEINFO]) {
- const struct ifa_cacheinfo *ca = nla_data(tb[IFA_CACHEINFO]);
+ const struct ifa_cacheinfo *ca;
+ ca = nla_data_as (struct ifa_cacheinfo, tb[IFA_CACHEINFO]);
lifetime = ca->ifa_valid;
preferred = ca->ifa_prefered;
timestamp = ca->tstamp;
@@ -3102,7 +3095,7 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
static NMPObject *
_new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
{
- static const struct nla_policy policy[RTA_MAX+1] = {
+ static const struct nla_policy policy[] = {
[RTA_TABLE] = { .type = NLA_U32 },
[RTA_IIF] = { .type = NLA_U32 },
[RTA_OIF] = { .type = NLA_U32 },
@@ -3114,8 +3107,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
[RTA_MULTIPATH] = { .type = NLA_NESTED },
};
const struct rtmsg *rtm;
- struct nlattr *tb[RTA_MAX + 1];
- int err;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
gboolean is_v4;
nm_auto_nmpobj NMPObject *obj = NULL;
int addr_len;
@@ -3123,13 +3115,21 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
gboolean is_present;
int ifindex;
NMIPAddr gateway;
- } nh;
+ } nh = {
+ .is_present = FALSE,
+ };
guint32 mss;
- guint32 window = 0, cwnd = 0, initcwnd = 0, initrwnd = 0, mtu = 0, lock = 0;
+ guint32 window = 0;
+ guint32 cwnd = 0;
+ guint32 initcwnd = 0;
+ guint32 initrwnd = 0;
+ guint32 mtu = 0;
+ guint32 lock = 0;
if (!nlmsg_valid_hdr (nlh, sizeof (*rtm)))
return NULL;
- rtm = nlmsg_data(nlh);
+
+ rtm = nlmsg_data (nlh);
/*****************************************************************
* only handle ~normal~ routes.
@@ -3141,8 +3141,10 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
if (rtm->rtm_type != RTN_UNICAST)
return NULL;
- err = nlmsg_parse (nlh, sizeof (struct rtmsg), tb, RTA_MAX, policy);
- if (err < 0)
+ if (nlmsg_parse_arr (nlh,
+ sizeof (struct rtmsg),
+ tb,
+ policy) < 0)
return NULL;
/*****************************************************************/
@@ -3159,39 +3161,49 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
* parse nexthops. Only handle routes with one nh.
*****************************************************************/
- memset (&nh, 0, sizeof (nh));
-
if (tb[RTA_MULTIPATH]) {
- struct rtnexthop *rtnh = nla_data (tb[RTA_MULTIPATH]);
- size_t tlen = nla_len(tb[RTA_MULTIPATH]);
+ size_t tlen = nla_len (tb[RTA_MULTIPATH]);
+ struct rtnexthop *rtnh;
+
+ if (tlen < sizeof (*rtnh))
+ goto rta_multipath_done;
+
+ rtnh = nla_data_as (struct rtnexthop, tb[RTA_MULTIPATH]);
+
+ if (tlen < rtnh->rtnh_len)
+ goto rta_multipath_done;
- while (tlen >= sizeof(*rtnh) && tlen >= rtnh->rtnh_len) {
+ while (TRUE) {
if (nh.is_present) {
/* we don't support multipath routes. */
return NULL;
}
- nh.is_present = TRUE;
+ nh.is_present = TRUE;
nh.ifindex = rtnh->rtnh_ifindex;
- if (rtnh->rtnh_len > sizeof(*rtnh)) {
- struct nlattr *ntb[RTA_MAX + 1];
+ if (rtnh->rtnh_len > sizeof (*rtnh)) {
+ struct nlattr *ntb[G_N_ELEMENTS (policy)];
- err = nla_parse (ntb, RTA_MAX, (struct nlattr *)
- RTNH_DATA(rtnh),
- rtnh->rtnh_len - sizeof (*rtnh),
- policy);
- if (err < 0)
+ if (nla_parse_arr (ntb,
+ (struct nlattr *) RTNH_DATA (rtnh),
+ rtnh->rtnh_len - sizeof (*rtnh),
+ policy) < 0)
return NULL;
if (_check_addr_or_return_null (ntb, RTA_GATEWAY, addr_len))
memcpy (&nh.gateway, nla_data (ntb[RTA_GATEWAY]), addr_len);
}
- tlen -= RTNH_ALIGN(rtnh->rtnh_len);
- rtnh = RTNH_NEXT(rtnh);
+ if (tlen < RTNH_ALIGN (rtnh->rtnh_len) + sizeof (*rtnh))
+ goto rta_multipath_done;
+
+ tlen -= RTNH_ALIGN (rtnh->rtnh_len);
+ rtnh = RTNH_NEXT (rtnh);
}
+rta_multipath_done:
+ ;
}
if ( tb[RTA_OIF]
@@ -3225,8 +3237,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
mss = 0;
if (tb[RTA_METRICS]) {
- struct nlattr *mtb[RTAX_MAX + 1];
- static const struct nla_policy rtax_policy[RTAX_MAX + 1] = {
+ static const struct nla_policy rtax_policy[] = {
[RTAX_LOCK] = { .type = NLA_U32 },
[RTAX_ADVMSS] = { .type = NLA_U32 },
[RTAX_WINDOW] = { .type = NLA_U32 },
@@ -3235,9 +3246,9 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
[RTAX_INITRWND] = { .type = NLA_U32 },
[RTAX_MTU] = { .type = NLA_U32 },
};
+ struct nlattr *mtb[G_N_ELEMENTS (rtax_policy)];
- err = nla_parse_nested (mtb, RTAX_MAX, tb[RTA_METRICS], rtax_policy);
- if (err < 0)
+ if (nla_parse_nested_arr (mtb, tb[RTA_METRICS], rtax_policy) < 0)
return NULL;
if (mtb[RTAX_LOCK])
@@ -3272,7 +3283,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
obj->ip_route.plen = rtm->rtm_dst_len;
if (tb[RTA_PRIORITY])
- obj->ip_route.metric = nla_get_u32(tb[RTA_PRIORITY]);
+ obj->ip_route.metric = nla_get_u32 (tb[RTA_PRIORITY]);
if (is_v4)
obj->ip4_route.gateway = nh.gateway.addr4;
@@ -3329,25 +3340,24 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
static NMPObject *
_new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only)
{
- NMPObject *obj = NULL;
- const struct tcmsg *tcm;
- struct nlattr *tb[TCA_MAX + 1];
- int err;
- static const struct nla_policy policy[TCA_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[TCA_KIND] = { .type = NLA_STRING },
};
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
+ const struct tcmsg *tcm;
+ NMPObject *obj;
- if (!nlmsg_valid_hdr (nlh, sizeof (*tcm)))
- return NULL;
- tcm = nlmsg_data (nlh);
-
- err = nlmsg_parse (nlh, sizeof (*tcm), tb, TCA_MAX, policy);
- if (err < 0)
+ if (nlmsg_parse_arr (nlh,
+ sizeof (*tcm),
+ tb,
+ policy) < 0)
return NULL;
if (!tb[TCA_KIND])
return NULL;
+ tcm = nlmsg_data (nlh);
+
obj = nmp_object_new (NMP_OBJECT_TYPE_QDISC, NULL);
obj->qdisc.kind = g_intern_string (nla_get_string (tb[TCA_KIND]));
@@ -3363,25 +3373,21 @@ _new_from_nl_qdisc (struct nlmsghdr *nlh, gboolean id_only)
static NMPObject *
_new_from_nl_tfilter (struct nlmsghdr *nlh, gboolean id_only)
{
- NMPObject *obj = NULL;
- const struct tcmsg *tcm;
- struct nlattr *tb[TCA_MAX + 1];
- int err;
- static const struct nla_policy policy[TCA_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[TCA_KIND] = { .type = NLA_STRING },
};
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
+ NMPObject *obj = NULL;
+ const struct tcmsg *tcm;
- if (!nlmsg_valid_hdr (nlh, sizeof (*tcm)))
- return NULL;
- tcm = nlmsg_data (nlh);
-
- err = nlmsg_parse (nlh, sizeof (*tcm), tb, TCA_MAX, policy);
- if (err < 0)
+ if (nlmsg_parse_arr (nlh, sizeof (*tcm), tb, policy) < 0)
return NULL;
if (!tb[TCA_KIND])
return NULL;
+ tcm = nlmsg_data (nlh);
+
obj = nmp_object_new (NMP_OBJECT_TYPE_TFILTER, NULL);
obj->tfilter.kind = g_intern_string (nla_get_string (tb[TCA_KIND]));
@@ -3503,14 +3509,14 @@ _nl_msg_new_link_set_linkinfo (struct nl_msg *msg,
NLA_PUT_STRING (msg, IFLA_INFO_KIND, kind);
if (veth_peer) {
- struct ifinfomsg ifi = { };
+ const struct ifinfomsg ifi = { };
struct nlattr *data, *info_peer;
if (!(data = nla_nest_start (msg, IFLA_INFO_DATA)))
goto nla_put_failure;
if (!(info_peer = nla_nest_start (msg, 1 /*VETH_INFO_PEER*/)))
goto nla_put_failure;
- if (nlmsg_append (msg, &ifi, sizeof (ifi), NLMSG_ALIGNTO) < 0)
+ if (nlmsg_append_struct (msg, &ifi) < 0)
goto nla_put_failure;
NLA_PUT_STRING (msg, IFLA_IFNAME, veth_peer);
nla_nest_end (msg, info_peer);
@@ -3614,7 +3620,7 @@ _nl_msg_new_link_set_linkinfo_vlan (struct nl_msg *msg,
for (i = 0; i < egress_qos_len; i++) {
if (VLAN_XGRESS_PRIO_VALID (egress_qos[i].to)) {
if (!qos) {
- if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS)))
+ if (!(qos = nla_nest_start (msg, IFLA_VLAN_EGRESS_QOS)))
goto nla_put_failure;
}
NLA_PUT (msg, i, sizeof (egress_qos[i]), &egress_qos[i]);
@@ -3622,7 +3628,7 @@ _nl_msg_new_link_set_linkinfo_vlan (struct nl_msg *msg,
}
if (qos)
- nla_nest_end(msg, qos);
+ nla_nest_end (msg, qos);
}
nla_nest_end (msg, data);
@@ -3641,8 +3647,8 @@ _nl_msg_new_link (int nlmsg_type,
unsigned flags_mask,
unsigned flags_set)
{
- struct nl_msg *msg;
- struct ifinfomsg ifi = {
+ nm_auto_nlmsg struct nl_msg *msg = NULL;
+ const struct ifinfomsg ifi = {
.ifi_change = flags_mask,
.ifi_flags = flags_set,
.ifi_index = ifindex,
@@ -3652,15 +3658,15 @@ _nl_msg_new_link (int nlmsg_type,
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
- if (nlmsg_append (msg, &ifi, sizeof (ifi), NLMSG_ALIGNTO) < 0)
+ if (nlmsg_append_struct (msg, &ifi) < 0)
goto nla_put_failure;
if (ifname)
NLA_PUT_STRING (msg, IFLA_IFNAME, ifname);
- return msg;
+ return g_steal_pointer (&msg);
+
nla_put_failure:
- nlmsg_free (msg);
g_return_val_if_reached (NULL);
}
@@ -3679,7 +3685,7 @@ _nl_msg_new_address (int nlmsg_type,
guint32 preferred,
const char *label)
{
- struct nl_msg *msg;
+ nm_auto_nlmsg struct nl_msg *msg = NULL;
struct ifaddrmsg am = {
.ifa_family = family,
.ifa_index = ifindex,
@@ -3706,7 +3712,7 @@ _nl_msg_new_address (int nlmsg_type,
addr_len = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);
- if (nlmsg_append (msg, &am, sizeof (am), NLMSG_ALIGNTO) < 0)
+ if (nlmsg_append_struct (msg, &am) < 0)
goto nla_put_failure;
if (address)
@@ -3737,7 +3743,7 @@ _nl_msg_new_address (int nlmsg_type,
.ifa_prefered = preferred,
};
- NLA_PUT (msg, IFA_CACHEINFO, sizeof(ca), &ca);
+ NLA_PUT (msg, IFA_CACHEINFO, sizeof (ca), &ca);
}
if (flags & ~((guint32) 0xFF)) {
@@ -3750,10 +3756,9 @@ _nl_msg_new_address (int nlmsg_type,
NLA_PUT_U32 (msg, IFA_FLAGS, flags);
}
- return msg;
+ return g_steal_pointer (&msg);
nla_put_failure:
- nlmsg_free (msg);
g_return_val_if_reached (NULL);
}
@@ -3773,12 +3778,12 @@ _nl_msg_new_route (int nlmsg_type,
guint16 nlmsgflags,
const NMPObject *obj)
{
- struct nl_msg *msg;
+ nm_auto_nlmsg struct nl_msg *msg = NULL;
const NMPClass *klass = NMP_OBJECT_GET_CLASS (obj);
gboolean is_v4 = klass->addr_family == AF_INET;
const guint32 lock = ip_route_get_lock_flag (NMP_OBJECT_CAST_IP_ROUTE (obj));
const guint32 table = nm_platform_route_table_uncoerce (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced, TRUE);
- struct rtmsg rtmsg = {
+ const struct rtmsg rtmsg = {
.rtm_family = klass->addr_family,
.rtm_tos = is_v4
? obj->ip4_route.tos
@@ -3805,7 +3810,7 @@ _nl_msg_new_route (int nlmsg_type,
msg = nlmsg_alloc_simple (nlmsg_type, (int) nlmsgflags);
- if (nlmsg_append (msg, &rtmsg, sizeof (rtmsg), NLMSG_ALIGNTO) < 0)
+ if (nlmsg_append_struct (msg, &rtmsg) < 0)
goto nla_put_failure;
addr_len = is_v4
@@ -3863,7 +3868,7 @@ _nl_msg_new_route (int nlmsg_type,
if (lock)
NLA_PUT_U32 (msg, RTAX_LOCK, lock);
- nla_nest_end(msg, metrics);
+ nla_nest_end (msg, metrics);
}
/* We currently don't have need for multi-hop routes... */
@@ -3879,10 +3884,9 @@ _nl_msg_new_route (int nlmsg_type,
&& obj->ip6_route.rt_pref != NM_ICMPV6_ROUTER_PREF_MEDIUM)
NLA_PUT_U8 (msg, RTA_PREF, obj->ip6_route.rt_pref);
- return msg;
+ return g_steal_pointer (&msg);
nla_put_failure:
- nlmsg_free (msg);
g_return_val_if_reached (NULL);
}
@@ -3891,8 +3895,8 @@ _nl_msg_new_qdisc (int nlmsg_type,
int nlmsg_flags,
const NMPlatformQdisc *qdisc)
{
- struct nl_msg *msg;
- struct tcmsg tcm = {
+ nm_auto_nlmsg struct nl_msg *msg = NULL;
+ const struct tcmsg tcm = {
.tcm_family = qdisc->addr_family,
.tcm_ifindex = qdisc->ifindex,
.tcm_handle = qdisc->handle,
@@ -3902,14 +3906,14 @@ _nl_msg_new_qdisc (int nlmsg_type,
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
- if (nlmsg_append (msg, &tcm, sizeof (tcm), NLMSG_ALIGNTO) < 0)
+ if (nlmsg_append_struct (msg, &tcm) < 0)
goto nla_put_failure;
NLA_PUT_STRING (msg, TCA_KIND, qdisc->kind);
- return msg;
+ return g_steal_pointer (&msg);
+
nla_put_failure:
- nlmsg_free (msg);
g_return_val_if_reached (NULL);
}
@@ -3963,10 +3967,10 @@ _nl_msg_new_tfilter (int nlmsg_type,
int nlmsg_flags,
const NMPlatformTfilter *tfilter)
{
- struct nl_msg *msg;
+ nm_auto_nlmsg struct nl_msg *msg = NULL;
struct nlattr *tc_options;
struct nlattr *act_tab;
- struct tcmsg tcm = {
+ const struct tcmsg tcm = {
.tcm_family = tfilter->addr_family,
.tcm_ifindex = tfilter->ifindex,
.tcm_handle = tfilter->handle,
@@ -3976,7 +3980,7 @@ _nl_msg_new_tfilter (int nlmsg_type,
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
- if (nlmsg_append (msg, &tcm, sizeof (tcm), NLMSG_ALIGNTO) < 0)
+ if (nlmsg_append_struct (msg, &tcm) < 0)
goto nla_put_failure;
NLA_PUT_STRING (msg, TCA_KIND, tfilter->kind);
@@ -3994,9 +3998,9 @@ _nl_msg_new_tfilter (int nlmsg_type,
nla_nest_end (msg, act_tab);
- return msg;
+ return g_steal_pointer (&msg);
+
nla_put_failure:
- nlmsg_free (msg);
g_return_val_if_reached (NULL);
}
@@ -4643,9 +4647,8 @@ delayed_action_handle_one (NMPlatform *platform)
priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_REFRESH_ALL;
if (_LOGt_ENABLED ()) {
- FOR_EACH_DELAYED_ACTION (iflags, flags) {
+ FOR_EACH_DELAYED_ACTION (iflags, flags)
_LOGt_delayed_action (iflags, NULL, "handle");
- }
}
delayed_action_handle_REFRESH_ALL (platform, flags);
@@ -4729,9 +4732,8 @@ delayed_action_schedule (NMPlatform *platform, DelayedActionType action_type, gp
priv->delayed_action.flags |= action_type;
if (_LOGt_ENABLED ()) {
- FOR_EACH_DELAYED_ACTION (iflags, action_type) {
+ FOR_EACH_DELAYED_ACTION (iflags, action_type)
_LOGt_delayed_action (iflags, user_data, "schedule");
- }
}
}
@@ -5078,7 +5080,7 @@ _nl_send_nlmsghdr (NMPlatform *platform,
};
struct msghdr msg = {
.msg_name = &nladdr,
- .msg_namelen = sizeof(nladdr),
+ .msg_namelen = sizeof (nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
@@ -5193,6 +5195,59 @@ do_request_link (NMPlatform *platform, int ifindex, const char *name)
delayed_action_handle_all (platform, FALSE);
}
+static struct nl_msg *
+_nl_msg_new_dump (NMPObjectType obj_type,
+ int preferred_addr_family)
+{
+ nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
+ const NMPClass *klass;
+
+ klass = nmp_class_from_type (obj_type);
+
+ nm_assert (klass);
+ nm_assert (klass->rtm_gettype > 0);
+
+ nlmsg = nlmsg_alloc_simple (klass->rtm_gettype, NLM_F_DUMP);
+
+ if (klass->addr_family != AF_UNSPEC) {
+ /* if the class specifies a particular address family, then it is preferred. */
+ nm_assert (NM_IN_SET (preferred_addr_family, AF_UNSPEC, klass->addr_family));
+ preferred_addr_family = klass->addr_family;
+ }
+
+ switch (klass->obj_type) {
+ case NMP_OBJECT_TYPE_QDISC:
+ case NMP_OBJECT_TYPE_TFILTER:
+ {
+ const struct tcmsg tcmsg = {
+ .tcm_family = preferred_addr_family,
+ };
+
+ if (nlmsg_append_struct (nlmsg, &tcmsg) < 0)
+ g_return_val_if_reached (NULL);
+ }
+ break;
+ case NMP_OBJECT_TYPE_LINK:
+ case NMP_OBJECT_TYPE_IP4_ADDRESS:
+ case NMP_OBJECT_TYPE_IP6_ADDRESS:
+ case NMP_OBJECT_TYPE_IP4_ROUTE:
+ case NMP_OBJECT_TYPE_IP6_ROUTE:
+ {
+ const struct rtgenmsg gmsg = {
+ .rtgen_family = preferred_addr_family,
+ };
+
+ if (nlmsg_append_struct (nlmsg, &gmsg) < 0)
+ g_return_val_if_reached (NULL);
+ }
+ break;
+ default:
+ g_return_val_if_reached (NULL);
+ }
+
+ return g_steal_pointer (&nlmsg);
+}
+
static void
do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActionType action_type)
{
@@ -5203,16 +5258,18 @@ do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActionType actio
action_type &= DELAYED_ACTION_TYPE_REFRESH_ALL;
FOR_EACH_DELAYED_ACTION (iflags, action_type) {
+ NMPLookup lookup;
+
priv->pruning[delayed_action_refresh_all_to_idx (iflags)] = TRUE;
+ nmp_lookup_init_obj_type (&lookup,
+ delayed_action_refresh_to_object_type (iflags));
nmp_cache_dirty_set_all (nm_platform_get_cache (platform),
- delayed_action_refresh_to_object_type (iflags));
+ &lookup);
}
FOR_EACH_DELAYED_ACTION (iflags, action_type) {
NMPObjectType obj_type = delayed_action_refresh_to_object_type (iflags);
- const NMPClass *klass = nmp_class_from_type (obj_type);
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
- int nle;
int *out_refresh_all_in_progress;
out_refresh_all_in_progress = &priv->delayed_action.refresh_all_in_progress[delayed_action_refresh_all_to_idx (iflags)];
@@ -5230,31 +5287,23 @@ do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActionType actio
event_handler_read_netlink (platform, FALSE);
- /* reimplement
- * nl_rtgen_request (sk, klass->rtm_gettype, klass->addr_family, NLM_F_DUMP);
- * because we need the sequence number.
- */
- nlmsg = nlmsg_alloc_simple (klass->rtm_gettype, NLM_F_DUMP);
+ nlmsg = _nl_msg_new_dump (obj_type, AF_UNSPEC);
+ if (!nlmsg)
+ goto next_after_fail;
- if ( klass->obj_type == NMP_OBJECT_TYPE_QDISC
- || klass->obj_type == NMP_OBJECT_TYPE_TFILTER) {
- struct tcmsg tcmsg = {
- .tcm_family = AF_UNSPEC,
- };
- nle = nlmsg_append (nlmsg, &tcmsg, sizeof (tcmsg), NLMSG_ALIGNTO);
- } else {
- struct rtgenmsg gmsg = {
- .rtgen_family = klass->addr_family,
- };
- nle = nlmsg_append (nlmsg, &gmsg, sizeof (gmsg), NLMSG_ALIGNTO);
- }
- if (nle < 0)
- continue;
+ if (_nl_send_nlmsg (platform,
+ nlmsg,
+ NULL,
+ NULL,
+ DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS,
+ out_refresh_all_in_progress) < 0)
+ goto next_after_fail;
- if (_nl_send_nlmsg (platform, nlmsg, NULL, NULL, DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS, out_refresh_all_in_progress) < 0) {
- nm_assert (*out_refresh_all_in_progress > 0);
- *out_refresh_all_in_progress -= 1;
- }
+ continue;
+
+next_after_fail:
+ nm_assert (*out_refresh_all_in_progress > 0);
+ *out_refresh_all_in_progress -= 1;
}
}
@@ -5341,9 +5390,9 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
NMPCacheOpsType cache_op;
struct nlmsghdr *msghdr;
char buf_nlmsghdr[400];
- gboolean id_only = FALSE;
+ gboolean is_del = FALSE;
+ gboolean is_dump = FALSE;
NMPCache *cache = nm_platform_get_cache (platform);
- gboolean is_dump;
msghdr = nlmsg_hdr (msg);
@@ -5354,37 +5403,38 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
if (!handle_events)
return;
- if (NM_IN_SET (msghdr->nlmsg_type, RTM_DELLINK, RTM_DELADDR, RTM_DELROUTE)) {
+ if (NM_IN_SET (msghdr->nlmsg_type, RTM_DELLINK,
+ RTM_DELADDR,
+ RTM_DELROUTE,
+ RTM_DELQDISC,
+ RTM_DELTFILTER)) {
/* The event notifies about a deleted object. We don't need to initialize all
* fields of the object. */
- id_only = TRUE;
+ is_del = TRUE;
}
- obj = nmp_object_new_from_nl (platform, cache, msg, id_only);
+ obj = nmp_object_new_from_nl (platform, cache, msg, is_del);
if (!obj) {
_LOGT ("event-notification: %s: ignore",
nl_nlmsghdr_to_str (msghdr, buf_nlmsghdr, sizeof (buf_nlmsghdr)));
return;
}
- switch (msghdr->nlmsg_type) {
- case RTM_NEWADDR:
- case RTM_NEWLINK:
- case RTM_NEWROUTE:
- case RTM_NEWQDISC:
- case RTM_NEWTFILTER:
+ if ( !is_del
+ && NM_IN_SET (msghdr->nlmsg_type, RTM_NEWADDR,
+ RTM_NEWLINK,
+ RTM_NEWROUTE,
+ RTM_NEWQDISC,
+ RTM_NEWTFILTER)) {
is_dump = delayed_action_refresh_all_in_progress (platform,
delayed_action_refresh_from_object_type (NMP_OBJECT_GET_TYPE (obj)));
- break;
- default:
- is_dump = FALSE;
}
_LOGT ("event-notification: %s%s: %s",
nl_nlmsghdr_to_str (msghdr, buf_nlmsghdr, sizeof (buf_nlmsghdr)),
is_dump ? ", in-dump" : "",
nmp_object_to_string (obj,
- id_only ? NMP_OBJECT_TO_STRING_ID : NMP_OBJECT_TO_STRING_PUBLIC,
+ is_del ? NMP_OBJECT_TO_STRING_ID : NMP_OBJECT_TO_STRING_PUBLIC,
NULL, 0));
{
@@ -7868,16 +7918,18 @@ continue_reading:
if ( NM_FLAGS_HAS (hdr->nlmsg_flags, NLM_F_ACK_TLVS)
&& hdr->nlmsg_len >= sizeof (*e) + e->msg.nlmsg_len) {
- static const struct nla_policy policy[NLMSGERR_ATTR_MAX + 1] = {
+ static const struct nla_policy policy[] = {
[NLMSGERR_ATTR_MSG] = { .type = NLA_STRING },
[NLMSGERR_ATTR_OFFS] = { .type = NLA_U32 },
};
- struct nlattr *tb[NLMSGERR_ATTR_MAX + 1];
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
struct nlattr *tlvs;
tlvs = (struct nlattr *) ((char *) e + sizeof (*e) + e->msg.nlmsg_len - NLMSG_HDRLEN);
- if (!nla_parse (tb, NLMSGERR_ATTR_MAX, tlvs,
- hdr->nlmsg_len - sizeof (*e) - e->msg.nlmsg_len, policy)) {
+ if (nla_parse_arr (tb,
+ tlvs,
+ hdr->nlmsg_len - sizeof (*e) - e->msg.nlmsg_len,
+ policy) >= 0) {
if (tb[NLMSGERR_ATTR_MSG])
extack_msg = nla_get_string (tb[NLMSGERR_ATTR_MSG]);
}
diff --git a/src/platform/nm-netlink.c b/src/platform/nm-netlink.c
index 3aac1998b6..71506a2c37 100644
--- a/src/platform/nm-netlink.c
+++ b/src/platform/nm-netlink.c
@@ -102,21 +102,30 @@ nl_nlmsghdr_to_str (const struct nlmsghdr *hdr, char *buf, gsize 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;
+ case RTM_GETLINK: s = "RTM_GETLINK"; break;
+ case RTM_NEWLINK: s = "RTM_NEWLINK"; break;
+ case RTM_DELLINK: s = "RTM_DELLINK"; break;
+ case RTM_SETLINK: s = "RTM_SETLINK"; break;
+ case RTM_GETADDR: s = "RTM_GETADDR"; break;
+ case RTM_NEWADDR: s = "RTM_NEWADDR"; break;
+ case RTM_DELADDR: s = "RTM_DELADDR"; break;
+ case RTM_GETROUTE: s = "RTM_GETROUTE"; break;
+ case RTM_NEWROUTE: s = "RTM_NEWROUTE"; break;
+ case RTM_DELROUTE: s = "RTM_DELROUTE"; break;
+ case RTM_GETRULE: s = "RTM_GETRULE"; break;
+ case RTM_NEWRULE: s = "RTM_NEWRULE"; break;
+ case RTM_DELRULE: s = "RTM_DELRULE"; break;
+ case RTM_GETQDISC: s = "RTM_GETQDISC"; break;
+ case RTM_NEWQDISC: s = "RTM_NEWQDISC"; break;
+ case RTM_DELQDISC: s = "RTM_DELQDISC"; break;
+ case RTM_GETTFILTER: s = "RTM_GETTFILTER"; 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)
@@ -205,6 +214,8 @@ nlmsg_reserve (struct nl_msg *n, size_t len, int pad)
size_t nlmsg_len = n->nm_nlh->nlmsg_len;
size_t tlen;
+ nm_assert (pad >= 0);
+
if (len > n->nm_size)
return NULL;
@@ -259,11 +270,12 @@ nlmsg_alloc_size (size_t len)
if (len < sizeof (struct nlmsghdr))
len = sizeof (struct nlmsghdr);
- nm = g_slice_new0 (struct nl_msg);
-
- nm->nm_protocol = -1;
- nm->nm_size = len;
- nm->nm_nlh = g_malloc0 (len);
+ nm = g_slice_new (struct nl_msg);
+ *nm = (struct nl_msg) {
+ .nm_protocol = -1,
+ .nm_size = len,
+ .nm_nlh = g_malloc0 (len),
+ };
nm->nm_nlh->nlmsg_len = nlmsg_total_size (0);
return nm;
}
@@ -318,10 +330,18 @@ void nlmsg_free (struct nl_msg *msg)
/*****************************************************************************/
int
-nlmsg_append (struct nl_msg *n, void *data, size_t len, int pad)
+nlmsg_append (struct nl_msg *n,
+ const void *data,
+ size_t len,
+ int pad)
{
void *tmp;
+ nm_assert (n);
+ nm_assert (data);
+ nm_assert (len > 0);
+ nm_assert (pad >= 0);
+
tmp = nlmsg_reserve (n, len, pad);
if (tmp == NULL)
return -ENOMEM;
@@ -365,48 +385,77 @@ nlmsg_put (struct nl_msg *n, uint32_t pid, uint32_t seq,
return nlh;
}
-uint64_t
-nla_get_u64 (const struct nlattr *nla)
-{
- uint64_t tmp = 0;
-
- if (nla && nla_len (nla) >= sizeof (tmp))
- memcpy (&tmp, nla_data (nla), sizeof (tmp));
-
- return tmp;
-}
-
size_t
-nla_strlcpy (char *dst, const struct nlattr *nla, size_t dstsize)
-{
- size_t srclen = nla_len (nla);
- const char *src = nla_data (nla);
-
- if (srclen > 0 && src[srclen - 1] == '\0')
- srclen--;
+nla_strlcpy (char *dst,
+ const struct nlattr *nla,
+ size_t dstsize)
+{
+ const char *src;
+ size_t srclen;
+ size_t len;
+
+ /* - Always writes @dstsize bytes to @dst
+ * - Copies the first non-NUL characters to @dst.
+ * Any characters after the first NUL bytes in @nla are ignored.
+ * - If the string @nla is longer than @dstsize, the string
+ * gets truncated. @dst will always be NUL terminated. */
+
+ if (G_UNLIKELY (dstsize <= 1)) {
+ if (dstsize == 1)
+ dst[0] = '\0';
+ if ( nla
+ && (srclen = nla_len (nla)) > 0)
+ return strnlen (nla_data (nla), srclen);
+ return 0;
+ }
- if (dstsize > 0) {
- size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
+ nm_assert (dst);
- memset (dst, 0, dstsize);
- memcpy (dst, src, len);
+ if (nla) {
+ srclen = nla_len (nla);
+ if (srclen > 0) {
+ src = nla_data (nla);
+ srclen = strnlen (src, srclen);
+ if (srclen > 0) {
+ len = NM_MIN (dstsize - 1, srclen);
+ memcpy (dst, src, len);
+ memset (&dst[len], 0, dstsize - len);
+ return srclen;
+ }
+ }
}
- return srclen;
+ memset (dst, 0, dstsize);
+ return 0;
}
-int
-nla_memcpy (void *dest, const struct nlattr *src, int count)
+size_t
+nla_memcpy (void *dst, const struct nlattr *nla, size_t dstsize)
{
- int minlen;
+ size_t len;
+ int srclen;
- if (!src)
+ if (!nla)
return 0;
- minlen = NM_MIN (count, (int) nla_len (src));
- memcpy (dest, nla_data (src), minlen);
+ srclen = nla_len (nla);
+
+ if (srclen <= 0) {
+ nm_assert (srclen == 0);
+ return 0;
+ }
+
+ len = NM_MIN ((size_t) srclen, dstsize);
+ if (len > 0) {
+ /* there is a crucial difference between nla_strlcpy() and nla_memcpy().
+ * The former always write @dstsize bytes (akin to strncpy()), here, we only
+ * write the bytes that we actually have (leaving the remainder undefined). */
+ memcpy (dst,
+ nla_data (nla),
+ len);
+ }
- return minlen;
+ return srclen;
}
int
@@ -546,7 +595,11 @@ validate_nla (const struct nlattr *nla, int maxtype,
return -NME_UNSPEC;
if (pt->type == NLA_STRING) {
- const char *data = nla_data (nla);
+ const char *data;
+
+ nm_assert (minlen > 0);
+
+ data = nla_data (nla);
if (data[nla_len (nla) - 1] != '\0')
return -NME_UNSPEC;
}
@@ -572,15 +625,13 @@ nla_parse (struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
if (policy) {
nmerr = validate_nla (nla, maxtype, policy);
if (nmerr < 0)
- goto errout;
+ return nmerr;
}
tb[type] = nla;
}
- nmerr = 0;
-errout:
- return nmerr;
+ return 0;
}
/*****************************************************************************/
@@ -719,21 +770,21 @@ genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
static int
_genl_parse_getfamily (struct nl_msg *msg, void *arg)
{
- static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
+ static const struct nla_policy ctrl_policy[] = {
[CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
[CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING,
- .maxlen = GENL_NAMSIZ },
+ .maxlen = GENL_NAMSIZ },
[CTRL_ATTR_VERSION] = { .type = NLA_U32 },
[CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 },
[CTRL_ATTR_MAXATTR] = { .type = NLA_U32 },
[CTRL_ATTR_OPS] = { .type = NLA_NESTED },
[CTRL_ATTR_MCAST_GROUPS] = { .type = NLA_NESTED },
};
- struct nlattr *tb[CTRL_ATTR_MAX+1];
+ struct nlattr *tb[G_N_ELEMENTS (ctrl_policy)];
struct nlmsghdr *nlh = nlmsg_hdr (msg);
gint32 *response_data = arg;
- if (genlmsg_parse (nlh, 0, tb, CTRL_ATTR_MAX, ctrl_policy))
+ if (genlmsg_parse_arr (nlh, 0, tb, ctrl_policy) < 0)
return NL_SKIP;
if (tb[CTRL_ATTR_FAMILY_ID])
diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h
index a344c5f2f6..094a3c6fde 100644
--- a/src/platform/nm-netlink.h
+++ b/src/platform/nm-netlink.h
@@ -25,6 +25,8 @@
#include <linux/rtnetlink.h>
#include <linux/genetlink.h>
+#include "nm-utils/unaligned.h"
+
/*****************************************************************************/
#define NLMSGERR_ATTR_UNUSED 0
@@ -87,8 +89,26 @@ struct nla_policy {
/*****************************************************************************/
+/* static asserts that @tb and @policy are suitable arguments to nla_parse(). */
+#define _nl_static_assert_tb(tb, policy) \
+ G_STMT_START { \
+ \
+ G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (tb) > 0); \
+ \
+ /* we allow @policy to be either NULL or a C array. */ \
+ G_STATIC_ASSERT_EXPR ( sizeof (policy) == sizeof (NULL) \
+ || G_N_ELEMENTS (tb) == (sizeof (policy) / sizeof (struct nla_policy))); \
+ \
+ /* For above check to work, we don't support policy being an array with same size as
+ * sizeof(NULL), otherwise, the compile time check breaks down. */ \
+ G_STATIC_ASSERT_EXPR (sizeof (NULL) != G_N_ELEMENTS (tb) * sizeof (struct nla_policy)); \
+ \
+ } G_STMT_END
+
+/*****************************************************************************/
+
static inline int
-nla_attr_size(int payload)
+nla_attr_size (int payload)
{
nm_assert (payload >= 0);
@@ -104,7 +124,7 @@ nla_total_size (int payload)
static inline int
nla_padlen (int payload)
{
- return nla_total_size(payload) - nla_attr_size(payload);
+ return nla_total_size (payload) - nla_attr_size (payload);
}
struct nlattr *nla_reserve (struct nl_msg *msg, int attrtype, int attrlen);
@@ -112,32 +132,56 @@ 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;
+ nm_assert (nla);
+ nm_assert (nla->nla_len >= NLA_HDRLEN);
+
+ return ((int) nla->nla_len) - NLA_HDRLEN;
}
static inline int
nla_type (const struct nlattr *nla)
{
+ nm_assert (nla_len (nla) >= 0);
+
return nla->nla_type & NLA_TYPE_MASK;
}
static inline void *
nla_data (const struct nlattr *nla)
{
- nm_assert (nla);
- return (char *) nla + NLA_HDRLEN;
+ nm_assert (nla_len (nla) >= 0);
+
+ return &(((char *) nla)[NLA_HDRLEN]);
}
+#define nla_data_as(type, nla) \
+ ({ \
+ const struct nlattr *_nla = (nla); \
+ \
+ nm_assert (nla_len (_nla) >= sizeof (type)); \
+ \
+ /* note that casting the pointer is undefined behavior in C, if
+ * the data has wrong alignment. Netlink data is aligned to 4 bytes,
+ * that means, if the alignment is larger than 4, this is invalid. */ \
+ G_STATIC_ASSERT_EXPR (_nm_alignof (type) <= NLA_ALIGNTO); \
+ \
+ (type *) nla_data (_nla); \
+ })
+
static inline uint8_t
nla_get_u8 (const struct nlattr *nla)
{
- return *(const uint8_t *) nla_data (nla);
+ nm_assert (nla_len (nla) >= sizeof (uint8_t));
+
+ return *((const uint8_t *) nla_data (nla));
}
-static inline uint8_t
+static inline int8_t
nla_get_s8 (const struct nlattr *nla)
{
- return *(const int8_t *) nla_data (nla);
+ nm_assert (nla_len (nla) >= sizeof (int8_t));
+
+ return *((const int8_t *) nla_data (nla));
}
static inline uint8_t
@@ -152,39 +196,80 @@ nla_get_u8_cond (/*const*/ struct nlattr *const*tb, int attr, uint8_t default_va
static inline uint16_t
nla_get_u16 (const struct nlattr *nla)
{
- return *(const uint16_t *) nla_data (nla);
+ nm_assert (nla_len (nla) >= sizeof (uint16_t));
+
+ return *((const uint16_t *) nla_data (nla));
}
static inline uint32_t
-nla_get_u32(const struct nlattr *nla)
+nla_get_u32 (const struct nlattr *nla)
{
- return *(const uint32_t *) nla_data (nla);
+ nm_assert (nla_len (nla) >= sizeof (uint32_t));
+
+ return *((const uint32_t *) nla_data (nla));
}
static inline int32_t
-nla_get_s32(const struct nlattr *nla)
+nla_get_s32 (const struct nlattr *nla)
{
- return *(const int32_t *) nla_data (nla);
+ nm_assert (nla_len (nla) >= sizeof (int32_t));
+
+ return *((const int32_t *) nla_data (nla));
}
-uint64_t nla_get_u64 (const struct nlattr *nla);
+static inline uint64_t
+nla_get_u64 (const struct nlattr *nla)
+{
+ nm_assert (nla_len (nla) >= sizeof (uint64_t));
+
+ return unaligned_read_ne64 (nla_data (nla));
+}
+
+static inline uint64_t
+nla_get_be64 (const struct nlattr *nla)
+{
+ nm_assert (nla_len (nla) >= sizeof (uint64_t));
+
+ return unaligned_read_be64 (nla_data (nla));
+}
static inline char *
nla_get_string (const struct nlattr *nla)
{
+ nm_assert (nla_len (nla) >= 0);
+
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);
+size_t nla_memcpy (void *dst, const struct nlattr *nla, size_t dstsize);
+
+#define nla_memcpy_checked_size(dst, nla, dstsize) \
+ G_STMT_START { \
+ void *const _dst = (dst); \
+ const struct nlattr *const _nla = (nla); \
+ const size_t _dstsize = (dstsize); \
+ size_t _srcsize; \
+ \
+ /* assert that, if @nla is given, that it has the exact expected
+ * size. This implies that the caller previously verified the length
+ * of the attribute (via minlen/maxlen at nla_parse()). */ \
+ \
+ if (_nla) { \
+ _srcsize = nla_memcpy (_dst, _nla, _dstsize); \
+ nm_assert (_srcsize == _dstsize); \
+ } \
+ } G_STMT_END
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);
+ nm_assert (str);
+
+ return nla_put (msg, attrtype, strlen (str) + 1, str);
}
static inline int
@@ -207,54 +292,54 @@ nla_put_uint32 (struct nl_msg *msg, int attrtype, uint32_t val)
#define NLA_PUT(msg, attrtype, attrlen, data) \
G_STMT_START { \
- if (nla_put(msg, attrtype, attrlen, data) < 0) \
+ if (nla_put (msg, attrtype, attrlen, data) < 0) \
goto nla_put_failure; \
} G_STMT_END
#define NLA_PUT_TYPE(msg, type, attrtype, value) \
G_STMT_START { \
type __nla_tmp = value; \
- NLA_PUT(msg, attrtype, sizeof(type), &__nla_tmp); \
+ NLA_PUT (msg, attrtype, sizeof (type), &__nla_tmp); \
} G_STMT_END
#define NLA_PUT_U8(msg, attrtype, value) \
- NLA_PUT_TYPE(msg, uint8_t, attrtype, value)
+ NLA_PUT_TYPE (msg, uint8_t, attrtype, value)
#define NLA_PUT_S8(msg, attrtype, value) \
- NLA_PUT_TYPE(msg, int8_t, attrtype, value)
+ NLA_PUT_TYPE (msg, int8_t, attrtype, value)
#define NLA_PUT_U16(msg, attrtype, value) \
- NLA_PUT_TYPE(msg, uint16_t, 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)
+ NLA_PUT_TYPE (msg, uint32_t, attrtype, value)
#define NLA_PUT_S32(msg, attrtype, value) \
- NLA_PUT_TYPE(msg, int32_t, attrtype, value)
+ NLA_PUT_TYPE (msg, int32_t, attrtype, value)
#define NLA_PUT_U64(msg, attrtype, value) \
- NLA_PUT_TYPE(msg, uint64_t, 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)
+ NLA_PUT (msg, attrtype, (int) strlen (value) + 1, value)
#define NLA_PUT_FLAG(msg, attrtype) \
- NLA_PUT(msg, attrtype, 0, NULL)
+ NLA_PUT (msg, attrtype, 0, NULL)
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 >= (int) sizeof(*nla) &&
- nla->nla_len >= sizeof(*nla) &&
+ return remaining >= (int) sizeof (*nla) &&
+ nla->nla_len >= sizeof (*nla) &&
nla->nla_len <= remaining;
}
static inline struct nlattr *
-nla_next(const struct nlattr *nla, int *remaining)
+nla_next (const struct nlattr *nla, int *remaining)
{
- int totlen = NLA_ALIGN(nla->nla_len);
+ int totlen = NLA_ALIGN (nla->nla_len);
*remaining -= totlen;
return (struct nlattr *) ((char *) nla + totlen);
@@ -262,28 +347,47 @@ nla_next(const struct nlattr *nla, int *remaining)
#define nla_for_each_attr(pos, head, len, rem) \
for (pos = head, rem = len; \
- nla_ok(pos, rem); \
- pos = nla_next(pos, &(rem)))
+ 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)))
+ 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,
+int nla_parse (struct nlattr *tb[],
+ int maxtype,
+ struct nlattr *head,
+ int len,
const struct nla_policy *policy);
+#define nla_parse_arr(tb, head, len, policy) \
+ ({ \
+ _nl_static_assert_tb ((tb), (policy)); \
+ \
+ nla_parse ((tb), G_N_ELEMENTS (tb) - 1, (head), (len), (policy)); \
+ })
+
static inline int
-nla_parse_nested (struct nlattr *tb[], int maxtype, struct nlattr *nla,
+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);
+ return nla_parse (tb, maxtype, nla_data (nla), nla_len (nla), policy);
}
+#define nla_parse_nested_arr(tb, nla, policy) \
+ ({ \
+ _nl_static_assert_tb ((tb), (policy)); \
+ \
+ nla_parse_nested ((tb), G_N_ELEMENTS (tb) - 1, (nla), (policy)); \
+ })
+
/*****************************************************************************/
struct nl_msg *nlmsg_alloc (void);
@@ -296,7 +400,13 @@ 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);
+int nlmsg_append (struct nl_msg *n,
+ const void *data,
+ size_t len,
+ int pad);
+
+#define nlmsg_append_struct(n, data) \
+ nlmsg_append (n, (data), sizeof (*(data)), NLMSG_ALIGNTO)
void nlmsg_free (struct nl_msg *msg);
@@ -316,15 +426,15 @@ nlmsg_total_size (int payload)
static inline int
nlmsg_ok (const struct nlmsghdr *nlh, int remaining)
{
- return (remaining >= (int)sizeof(struct nlmsghdr) &&
- nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
+ 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);
+ int totlen = NLMSG_ALIGN (nlh->nlmsg_len);
*remaining -= totlen;
@@ -344,7 +454,7 @@ _nm_auto_nl_msg_cleanup (struct nl_msg **ptr)
{
nlmsg_free (*ptr);
}
-#define nm_auto_nlmsg nm_auto(_nm_auto_nl_msg_cleanup)
+#define nm_auto_nlmsg nm_auto (_nm_auto_nl_msg_cleanup)
static inline void *
nlmsg_data (const struct nlmsghdr *nlh)
@@ -355,13 +465,13 @@ nlmsg_data (const struct nlmsghdr *nlh)
static inline void *
nlmsg_tail (const struct nlmsghdr *nlh)
{
- return (unsigned char *) nlh + NLMSG_ALIGN(nlh->nlmsg_len);
+ 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)
+nlmsg_valid_hdr (const struct nlmsghdr *nlh, int hdrlen)
{
if (nlh->nlmsg_len < nlmsg_size (hdrlen))
return 0;
@@ -384,8 +494,8 @@ nlmsg_attrlen (const struct nlmsghdr *nlh, int hdrlen)
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));
+ unsigned char *data = nlmsg_data (nlh);
+ return (struct nlattr *) (data + NLMSG_ALIGN (hdrlen));
}
static inline struct nlattr *
@@ -396,8 +506,19 @@ nlmsg_find_attr (struct nlmsghdr *nlh, int hdrlen, int attrtype)
attrtype);
}
-int nlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
- int maxtype, const struct nla_policy *policy);
+int nlmsg_parse (struct nlmsghdr *nlh,
+ int hdrlen,
+ struct nlattr *tb[],
+ int maxtype,
+ const struct nla_policy *policy);
+
+#define nlmsg_parse_arr(nlh, hdrlen, tb, policy) \
+ ({ \
+ _nl_static_assert_tb ((tb), (policy)); \
+ G_STATIC_ASSERT_EXPR ((hdrlen) >= 0); \
+ \
+ nlmsg_parse ((nlh), (hdrlen), (tb), G_N_ELEMENTS (tb) - 1, (policy)); \
+ })
struct nlmsghdr *nlmsg_put (struct nl_msg *n, uint32_t pid, uint32_t seq,
int type, int payload, int flags);
@@ -499,8 +620,20 @@ struct nlattr *genlmsg_attrdata (const struct genlmsghdr *gnlh, int hdrlen);
int genlmsg_len (const struct genlmsghdr *gnlh);
int genlmsg_attrlen (const struct genlmsghdr *gnlh, int hdrlen);
int genlmsg_valid_hdr (struct nlmsghdr *nlh, int hdrlen);
-int genlmsg_parse (struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
- int maxtype, const struct nla_policy *policy);
+
+int genlmsg_parse (struct nlmsghdr *nlh,
+ int hdrlen,
+ struct nlattr *tb[],
+ int maxtype,
+ const struct nla_policy *policy);
+
+#define genlmsg_parse_arr(nlh, hdrlen, tb, policy) \
+ ({ \
+ _nl_static_assert_tb ((tb), (policy)); \
+ G_STATIC_ASSERT_EXPR ((hdrlen) >= 0); \
+ \
+ genlmsg_parse ((nlh), (hdrlen), (tb), G_N_ELEMENTS (tb) - 1, (policy)); \
+ })
int genl_ctrl_resolve (struct nl_sock *sk, const char *name);
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index 8c180c0b6a..ba84672a1e 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -2920,15 +2920,15 @@ nmp_cache_update_link_master_connected (NMPCache *cache,
/*****************************************************************************/
void
-nmp_cache_dirty_set_all (NMPCache *cache, NMPObjectType obj_type)
+nmp_cache_dirty_set_all (NMPCache *cache,
+ const NMPLookup *lookup)
{
- NMPObject obj_needle;
-
nm_assert (cache);
+ nm_assert (lookup);
nm_dedup_multi_index_dirty_set_head (cache->multi_idx,
- _idx_type_get (cache, NMP_CACHE_ID_TYPE_OBJECT_TYPE),
- _nmp_object_stackinit_from_type (&obj_needle, obj_type));
+ _idx_type_get (cache, lookup->cache_id_type),
+ &lookup->selector_obj);
}
/*****************************************************************************/
@@ -2977,7 +2977,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.sizeof_data = sizeof (NMPObjectLink),
.sizeof_public = sizeof (NMPlatformLink),
.obj_type_name = "link",
- .addr_family = AF_UNSPEC,
.rtm_gettype = RTM_GETLINK,
.signal_type_id = NM_PLATFORM_SIGNAL_ID_LINK,
.signal_type = NM_PLATFORM_SIGNAL_LINK_CHANGED,
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index 4649441bc5..32775efa83 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -771,7 +771,8 @@ NMPCacheOpsType nmp_cache_update_link_master_connected (NMPCache *cache,
const NMPObject **out_obj_old,
const NMPObject **out_obj_new);
-void nmp_cache_dirty_set_all (NMPCache *cache, NMPObjectType obj_type);
+void nmp_cache_dirty_set_all (NMPCache *cache,
+ const NMPLookup *lookup);
NMPCache *nmp_cache_new (NMDedupMultiIndex *multi_idx, gboolean use_udev);
void nmp_cache_free (NMPCache *cache);
diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.c b/src/platform/wifi/nm-wifi-utils-nl80211.c
index f03ae9c1f7..4f7ede9757 100644
--- a/src/platform/wifi/nm-wifi-utils-nl80211.c
+++ b/src/platform/wifi/nm-wifi-utils-nl80211.c
@@ -181,8 +181,10 @@ nl80211_iface_info_handler (struct nl_msg *msg, void *arg)
struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg));
struct nlattr *tb[NL80211_ATTR_MAX + 1];
- if (nla_parse (tb, NL80211_ATTR_MAX, genlmsg_attrdata (gnlh, 0),
- genlmsg_attrlen (gnlh, 0), NULL) < 0)
+ if (nla_parse_arr (tb,
+ genlmsg_attrdata (gnlh, 0),
+ genlmsg_attrlen (gnlh, 0),
+ NULL) < 0)
return NL_SKIP;
if (!tb[NL80211_ATTR_IFTYPE])
@@ -276,16 +278,18 @@ nl80211_get_wake_on_wlan_handler (struct nl_msg *msg, void *arg)
struct nlattr *trig[NUM_NL80211_WOWLAN_TRIG];
struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg));
- nla_parse (attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
- genlmsg_attrlen(gnlh, 0), NULL);
+ nla_parse_arr (attrs,
+ genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0),
+ NULL);
if (!attrs[NL80211_ATTR_WOWLAN_TRIGGERS])
return NL_SKIP;
- nla_parse (trig, MAX_NL80211_WOWLAN_TRIG,
- nla_data (attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
- nla_len (attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
- NULL);
+ nla_parse_arr (trig,
+ nla_data (attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
+ nla_len (attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
+ NULL);
*wowl = NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE;
if (trig[NL80211_WOWLAN_TRIG_ANY])
@@ -412,33 +416,35 @@ find_ssid (guint8 *ies, guint32 ies_len,
static int
nl80211_bss_dump_handler (struct nl_msg *msg, void *arg)
{
+ static const struct nla_policy bss_policy[] = {
+ [NL80211_BSS_TSF] = { .type = NLA_U64 },
+ [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
+ [NL80211_BSS_BSSID] = { .minlen = ETH_ALEN },
+ [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
+ [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
+ [NL80211_BSS_INFORMATION_ELEMENTS] = { },
+ [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
+ [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
+ [NL80211_BSS_STATUS] = { .type = NLA_U32 },
+ };
struct nl80211_bss_info *info = arg;
struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg));
struct nlattr *tb[NL80211_ATTR_MAX + 1];
- struct nlattr *bss[NL80211_BSS_MAX + 1];
- static const struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
- [NL80211_BSS_TSF] = { .type = NLA_U64 },
- [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
- [NL80211_BSS_BSSID] = { },
- [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
- [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
- [NL80211_BSS_INFORMATION_ELEMENTS] = { },
- [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
- [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
- [NL80211_BSS_STATUS] = { .type = NLA_U32 },
- };
+ struct nlattr *bss[G_N_ELEMENTS (bss_policy)];
guint32 status;
- if (nla_parse (tb, NL80211_ATTR_MAX, genlmsg_attrdata (gnlh, 0),
- genlmsg_attrlen (gnlh, 0), NULL) < 0)
+ if (nla_parse_arr (tb,
+ genlmsg_attrdata (gnlh, 0),
+ genlmsg_attrlen (gnlh, 0),
+ NULL) < 0)
return NL_SKIP;
if (tb[NL80211_ATTR_BSS] == NULL)
return NL_SKIP;
- if (nla_parse_nested (bss, NL80211_BSS_MAX,
- tb[NL80211_ATTR_BSS],
- bss_policy))
+ if (nla_parse_nested_arr (bss,
+ tb[NL80211_ATTR_BSS],
+ bss_policy))
return NL_SKIP;
if (bss[NL80211_BSS_STATUS] == NULL)
@@ -458,21 +464,22 @@ nl80211_bss_dump_handler (struct nl_msg *msg, void *arg)
info->freq = nla_get_u32 (bss[NL80211_BSS_FREQUENCY]);
if (bss[NL80211_BSS_SIGNAL_UNSPEC])
- info->beacon_signal =
- nla_get_u8 (bss[NL80211_BSS_SIGNAL_UNSPEC]);
+ info->beacon_signal = nla_get_u8 (bss[NL80211_BSS_SIGNAL_UNSPEC]);
if (bss[NL80211_BSS_SIGNAL_MBM])
- info->beacon_signal =
- nl80211_xbm_to_percent (nla_get_u32 (bss[NL80211_BSS_SIGNAL_MBM]), 100);
+ info->beacon_signal = nl80211_xbm_to_percent (nla_get_u32 (bss[NL80211_BSS_SIGNAL_MBM]), 100);
if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
guint8 *ssid;
guint32 ssid_len;
find_ssid (nla_data (bss[NL80211_BSS_INFORMATION_ELEMENTS]),
- nla_len (bss[NL80211_BSS_INFORMATION_ELEMENTS]),
- &ssid, &ssid_len);
- if (ssid && ssid_len && ssid_len <= sizeof (info->ssid)) {
+ nla_len (bss[NL80211_BSS_INFORMATION_ELEMENTS]),
+ &ssid,
+ &ssid_len);
+ if ( ssid
+ && ssid_len
+ && ssid_len <= sizeof (info->ssid)) {
memcpy (info->ssid, ssid, ssid_len);
info->ssid_len = ssid_len;
}
@@ -547,49 +554,50 @@ struct nl80211_station_info {
static int
nl80211_station_handler (struct nl_msg *msg, void *arg)
{
- struct nl80211_station_info *info = arg;
- struct nlattr *tb[NL80211_ATTR_MAX + 1];
- struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg));
- struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
- struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
- static const struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
+ static const struct nla_policy stats_policy[] = {
[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
- [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
- [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
- [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
- [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
- [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
- [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
- [NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
- [NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
- [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
+ [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+ [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
+ [NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
+ [NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
+ [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
};
-
- static const struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
- [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
- [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
+ static const struct nla_policy rate_policy[] = {
+ [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
+ [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
[NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
- [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
};
+ struct nlattr *rinfo[G_N_ELEMENTS (rate_policy)];
+ struct nlattr *sinfo[G_N_ELEMENTS (stats_policy)];
+ struct nl80211_station_info *info = arg;
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg));
- if (nla_parse (tb, NL80211_ATTR_MAX, genlmsg_attrdata (gnlh, 0),
- genlmsg_attrlen (gnlh, 0), NULL) < 0)
+ if (nla_parse_arr (tb,
+ genlmsg_attrdata (gnlh, 0),
+ genlmsg_attrlen (gnlh, 0),
+ NULL) < 0)
return NL_SKIP;
if (tb[NL80211_ATTR_STA_INFO] == NULL)
return NL_SKIP;
- if (nla_parse_nested (sinfo, NL80211_STA_INFO_MAX,
- tb[NL80211_ATTR_STA_INFO],
- stats_policy))
+ if (nla_parse_nested_arr (sinfo,
+ tb[NL80211_ATTR_STA_INFO],
+ stats_policy))
return NL_SKIP;
if (sinfo[NL80211_STA_INFO_TX_BITRATE] == NULL)
return NL_SKIP;
- if (nla_parse_nested (rinfo, NL80211_RATE_INFO_MAX,
- sinfo[NL80211_STA_INFO_TX_BITRATE],
- rate_policy))
+ if (nla_parse_nested_arr (rinfo,
+ sinfo[NL80211_STA_INFO_TX_BITRATE],
+ rate_policy))
return NL_SKIP;
if (rinfo[NL80211_RATE_INFO_BITRATE] == NULL)
@@ -714,37 +722,40 @@ struct nl80211_device_info {
static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg)
{
+ static const struct nla_policy freq_policy[] = {
+ [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
+ [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
+#ifdef NL80211_FREQUENCY_ATTR_NO_IR
+ [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG },
+#else
+ [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
+#endif
+ [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
+ };
struct nlattr *tb[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg));
struct nl80211_device_info *info = arg;
NMWifiUtilsNl80211 *self = info->self;
struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
- struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
+ struct nlattr *tb_freq[G_N_ELEMENTS (freq_policy)];
struct nlattr *nl_band;
struct nlattr *nl_freq;
int rem_freq;
int rem_band;
int freq_idx;
- static const struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
- [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
- [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
-#ifdef NL80211_FREQUENCY_ATTR_NO_IR
- [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG },
-#else
- [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
- [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
-#endif
- [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
- [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
- };
+
#ifdef NL80211_FREQUENCY_ATTR_NO_IR
- G_STATIC_ASSERT (NL80211_FREQUENCY_ATTR_PASSIVE_SCAN == NL80211_FREQUENCY_ATTR_NO_IR && NL80211_FREQUENCY_ATTR_NO_IBSS == NL80211_FREQUENCY_ATTR_NO_IR);
+ G_STATIC_ASSERT_EXPR (NL80211_FREQUENCY_ATTR_PASSIVE_SCAN == NL80211_FREQUENCY_ATTR_NO_IR && NL80211_FREQUENCY_ATTR_NO_IBSS == NL80211_FREQUENCY_ATTR_NO_IR);
#else
- G_STATIC_ASSERT (NL80211_FREQUENCY_ATTR_PASSIVE_SCAN != NL80211_FREQUENCY_ATTR_NO_IBSS);
+ G_STATIC_ASSERT_EXPR (NL80211_FREQUENCY_ATTR_PASSIVE_SCAN != NL80211_FREQUENCY_ATTR_NO_IBSS);
#endif
- if (nla_parse (tb, NL80211_ATTR_MAX, genlmsg_attrdata (gnlh, 0),
- genlmsg_attrlen (gnlh, 0), NULL) < 0)
+ if (nla_parse_arr (tb,
+ genlmsg_attrdata (gnlh, 0),
+ genlmsg_attrlen (gnlh, 0),
+ NULL) < 0)
return NL_SKIP;
if ( tb[NL80211_ATTR_WIPHY] == NULL
@@ -790,14 +801,17 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg)
info->num_freqs = 0;
nla_for_each_nested (nl_band, tb[NL80211_ATTR_WIPHY_BANDS], rem_band) {
- if (nla_parse_nested (tb_band, NL80211_BAND_ATTR_MAX, nl_band,
- NULL) < 0)
+ if (nla_parse_nested_arr (tb_band,
+ nl_band,
+ NULL) < 0)
return NL_SKIP;
- nla_for_each_nested (nl_freq, tb_band[NL80211_BAND_ATTR_FREQS],
+ nla_for_each_nested (nl_freq,
+ tb_band[NL80211_BAND_ATTR_FREQS],
rem_freq) {
- if (nla_parse_nested (tb_freq, NL80211_FREQUENCY_ATTR_MAX,
- nl_freq, freq_policy) < 0)
+ if (nla_parse_nested_arr (tb_freq,
+ nl_freq,
+ freq_policy) < 0)
continue;
if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
@@ -812,21 +826,22 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg)
freq_idx = 0;
nla_for_each_nested (nl_band, tb[NL80211_ATTR_WIPHY_BANDS], rem_band) {
- if (nla_parse_nested (tb_band, NL80211_BAND_ATTR_MAX, nl_band,
- NULL) < 0)
+ if (nla_parse_nested_arr (tb_band,
+ nl_band,
+ NULL) < 0)
return NL_SKIP;
nla_for_each_nested (nl_freq, tb_band[NL80211_BAND_ATTR_FREQS],
rem_freq) {
- if (nla_parse_nested (tb_freq, NL80211_FREQUENCY_ATTR_MAX,
- nl_freq, freq_policy) < 0)
+ if (nla_parse_nested_arr (tb_freq,
+ nl_freq,
+ freq_policy) < 0)
continue;
if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
continue;
- info->freqs[freq_idx] =
- nla_get_u32 (tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
+ info->freqs[freq_idx] = nla_get_u32 (tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
info->caps |= NM_WIFI_DEVICE_CAP_FREQ_VALID;
@@ -841,11 +856,10 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg)
/* Read security/encryption support */
if (tb[NL80211_ATTR_CIPHER_SUITES]) {
- int num;
- int i;
- __u32 *ciphers = nla_data (tb[NL80211_ATTR_CIPHER_SUITES]);
+ guint32 *ciphers = nla_data (tb[NL80211_ATTR_CIPHER_SUITES]);
+ guint i, num;
- num = nla_len (tb[NL80211_ATTR_CIPHER_SUITES]) / sizeof (__u32);
+ num = nla_len (tb[NL80211_ATTR_CIPHER_SUITES]) / sizeof (guint32);
for (i = 0; i < num; i++) {
switch (ciphers[i]) {
case WLAN_CIPHER_SUITE_WEP40:
diff --git a/src/platform/wpan/nm-wpan-utils.c b/src/platform/wpan/nm-wpan-utils.c
index 4ae1770ffe..b7a51e9bf2 100644
--- a/src/platform/wpan/nm-wpan-utils.c
+++ b/src/platform/wpan/nm-wpan-utils.c
@@ -153,17 +153,19 @@ struct nl802154_interface {
static int
nl802154_get_interface_handler (struct nl_msg *msg, void *arg)
{
+ static const struct nla_policy nl802154_policy[] = {
+ [NL802154_ATTR_PAN_ID] = { .type = NLA_U16 },
+ [NL802154_ATTR_SHORT_ADDR] = { .type = NLA_U16 },
+ };
+ struct nlattr *tb[G_N_ELEMENTS (nl802154_policy)];
struct nl802154_interface *info = arg;
struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg));
- struct nlattr *tb[NL802154_ATTR_MAX + 1] = { 0, };
- static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX + 1] = {
- [NL802154_ATTR_PAN_ID] = { .type = NLA_U16 },
- [NL802154_ATTR_SHORT_ADDR] = { .type = NLA_U16 },
- };
- if (nla_parse (tb, NL802154_ATTR_MAX, genlmsg_attrdata (gnlh, 0),
- genlmsg_attrlen (gnlh, 0), nl802154_policy) < 0)
- return NL_SKIP;
+ if (nla_parse_arr (tb,
+ genlmsg_attrdata (gnlh, 0),
+ genlmsg_attrlen (gnlh, 0),
+ nl802154_policy) < 0)
+ return NL_SKIP;
if (tb[NL802154_ATTR_PAN_ID])
info->pan_id = le16toh (nla_get_u16 (tb[NL802154_ATTR_PAN_ID]));