]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-netlink: rename NLType and friends
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 25 Jul 2022 05:11:00 +0000 (14:11 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 5 Aug 2022 18:53:51 +0000 (03:53 +0900)
In sd-netlink, we use 'type' for naming many variables with different type,
and worst of all, function like `type_get_type()` exists. That makes the
code hard to understood.

Let's rename
- NLType -> NLAPolicy
- NLTypeSystem -> NLAPolicySet
- NLTypeSystemUnion -> NLAPolicySetUnion
- type_get_type() -> policy_get_type()
- type_get_type_system() -> policy_get_policy_set(), and so on.

This also changes the type of attribute taken by e.g.
`sd_netlink_message_append_string()` from `unsigned short` -> `uint16_t`
to make the variable size clearer.

src/libsystemd/sd-netlink/netlink-genl.c
src/libsystemd/sd-netlink/netlink-internal.h
src/libsystemd/sd-netlink/netlink-message.c
src/libsystemd/sd-netlink/netlink-socket.c
src/libsystemd/sd-netlink/netlink-types-genl.c
src/libsystemd/sd-netlink/netlink-types-internal.h
src/libsystemd/sd-netlink/netlink-types-nfnl.c
src/libsystemd/sd-netlink/netlink-types-rtnl.c
src/libsystemd/sd-netlink/netlink-types.c
src/libsystemd/sd-netlink/netlink-types.h
src/systemd/sd-netlink.h

index 74be75d4067f3eae2295d226b62ecb30cffe83f5..aeb4b8a68680dd52dbea8af9e8dc688099947dd8 100644 (file)
@@ -12,7 +12,7 @@
 typedef struct GenericNetlinkFamily {
         sd_netlink *genl;
 
-        const NLTypeSystem *type_system;
+        const NLAPolicySet *policy_set;
 
         uint16_t id; /* a.k.a nlmsg_type */
         char *name;
@@ -56,14 +56,14 @@ void genl_clear_family(sd_netlink *nl) {
 static int genl_family_new_unsupported(
                 sd_netlink *nl,
                 const char *family_name,
-                const NLTypeSystem *type_system) {
+                const NLAPolicySet *policy_set) {
 
         _cleanup_(genl_family_freep) GenericNetlinkFamily *f = NULL;
         int r;
 
         assert(nl);
         assert(family_name);
-        assert(type_system);
+        assert(policy_set);
 
         /* Kernel does not support the genl family? To prevent from resolving the family name again,
          * let's store the family with zero id to indicate that. */
@@ -73,7 +73,7 @@ static int genl_family_new_unsupported(
                 return -ENOMEM;
 
         *f = (GenericNetlinkFamily) {
-                .type_system = type_system,
+                .policy_set = policy_set,
         };
 
         f->name = strdup(family_name);
@@ -92,7 +92,7 @@ static int genl_family_new_unsupported(
 static int genl_family_new(
                 sd_netlink *nl,
                 const char *expected_family_name,
-                const NLTypeSystem *type_system,
+                const NLAPolicySet *policy_set,
                 sd_netlink_message *message,
                 const GenericNetlinkFamily **ret) {
 
@@ -103,7 +103,7 @@ static int genl_family_new(
 
         assert(nl);
         assert(expected_family_name);
-        assert(type_system);
+        assert(policy_set);
         assert(message);
         assert(ret);
 
@@ -112,7 +112,7 @@ static int genl_family_new(
                 return -ENOMEM;
 
         *f = (GenericNetlinkFamily) {
-                .type_system = type_system,
+                .policy_set = policy_set,
         };
 
         r = sd_genl_message_get_family_name(nl, message, &family_name);
@@ -205,13 +205,13 @@ static int genl_family_new(
         return 0;
 }
 
-static const NLTypeSystem *genl_family_get_type_system(const GenericNetlinkFamily *family) {
+static const NLAPolicySet *genl_family_get_policy_set(const GenericNetlinkFamily *family) {
         assert(family);
 
-        if (family->type_system)
-                return family->type_system;
+        if (family->policy_set)
+                return family->policy_set;
 
-        return genl_get_type_system_by_name(family->name);
+        return genl_get_policy_set_by_name(family->name);
 }
 
 static int genl_message_new(
@@ -221,7 +221,7 @@ static int genl_message_new(
                 sd_netlink_message **ret) {
 
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
-        const NLTypeSystem *type_system;
+        const NLAPolicySet *policy_set;
         int r;
 
         assert(nl);
@@ -229,11 +229,11 @@ static int genl_message_new(
         assert(family);
         assert(ret);
 
-        type_system = genl_family_get_type_system(family);
-        if (!type_system)
+        policy_set = genl_family_get_policy_set(family);
+        if (!policy_set)
                 return -EOPNOTSUPP;
 
-        r = message_new_full(nl, family->id, type_system,
+        r = message_new_full(nl, family->id, policy_set,
                              sizeof(struct genlmsghdr) + family->additional_header_size, &m);
         if (r < 0)
                 return r;
@@ -254,7 +254,7 @@ static int genl_family_get_by_name_internal(
                 const GenericNetlinkFamily **ret) {
 
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
-        const NLTypeSystem *type_system;
+        const NLAPolicySet *policy_set;
         int r;
 
         assert(nl);
@@ -263,8 +263,8 @@ static int genl_family_get_by_name_internal(
         assert(name);
         assert(ret);
 
-        type_system = genl_get_type_system_by_name(name);
-        if (!type_system)
+        policy_set = genl_get_policy_set_by_name(name);
+        if (!policy_set)
                 return -EOPNOTSUPP;
 
         r = genl_message_new(nl, ctrl, CTRL_CMD_GETFAMILY, &req);
@@ -276,11 +276,11 @@ static int genl_family_get_by_name_internal(
                 return r;
 
         if (sd_netlink_call(nl, req, 0, &reply) < 0) {
-                (void) genl_family_new_unsupported(nl, name, type_system);
+                (void) genl_family_new_unsupported(nl, name, policy_set);
                 return -EOPNOTSUPP;
         }
 
-        return genl_family_new(nl, name, type_system, reply, ret);
+        return genl_family_new(nl, name, policy_set, reply, ret);
 }
 
 static int genl_family_get_by_name(sd_netlink *nl, const char *name, const GenericNetlinkFamily **ret) {
@@ -335,10 +335,10 @@ static int genl_family_get_by_id(sd_netlink *nl, uint16_t id, const GenericNetli
         return -ENOENT;
 }
 
-int genl_get_type_system_and_header_size(
+int genl_get_policy_set_and_header_size(
                 sd_netlink *nl,
                 uint16_t id,
-                const NLTypeSystem **ret_type_system,
+                const NLAPolicySet **ret_policy_set,
                 size_t *ret_header_size) {
 
         const GenericNetlinkFamily *f;
@@ -351,14 +351,14 @@ int genl_get_type_system_and_header_size(
         if (r < 0)
                 return r;
 
-        if (ret_type_system) {
-                const NLTypeSystem *t;
+        if (ret_policy_set) {
+                const NLAPolicySet *p;
 
-                t = genl_family_get_type_system(f);
-                if (!t)
+                p = genl_family_get_policy_set(f);
+                if (!p)
                         return -EOPNOTSUPP;
 
-                *ret_type_system = t;
+                *ret_policy_set = p;
         }
         if (ret_header_size)
                 *ret_header_size = sizeof(struct genlmsghdr) + f->additional_header_size;
@@ -420,7 +420,7 @@ _public_ int sd_genl_message_get_command(sd_netlink *nl, sd_netlink_message *m,
         if (r < 0)
                 return r;
 
-        r = genl_get_type_system_and_header_size(nl, nlmsg_type, NULL, &size);
+        r = genl_get_policy_set_and_header_size(nl, nlmsg_type, NULL, &size);
         if (r < 0)
                 return r;
 
index e3bb80e496ca6f0f4df0220a7486c5472dd97399..514f22511c342dab8109cd7627736d5b0ca04a8b 100644 (file)
@@ -109,7 +109,7 @@ struct netlink_attribute {
 };
 
 struct netlink_container {
-        const struct NLTypeSystem *type_system; /* the type system of the container */
+        const struct NLAPolicySet *policy_set; /* the policy set of the container */
         size_t offset; /* offset from hdr to the start of the container */
         struct netlink_attribute *attributes;
         uint16_t max_attribute; /* the maximum attribute in container */
@@ -133,7 +133,7 @@ int message_new_empty(sd_netlink *nl, sd_netlink_message **ret);
 int message_new_full(
                 sd_netlink *nl,
                 uint16_t nlmsg_type,
-                const NLTypeSystem *type_system,
+                const NLAPolicySet *policy_set,
                 size_t header_size,
                 sd_netlink_message **ret);
 int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type);
index f76827d42c54c486c01c0b6990ad29cee35497a2..093527a20def330467d23bc93ef620c7dbea5277 100644 (file)
@@ -46,7 +46,7 @@ int message_new_empty(sd_netlink *nl, sd_netlink_message **ret) {
 int message_new_full(
                 sd_netlink *nl,
                 uint16_t nlmsg_type,
-                const NLTypeSystem *type_system,
+                const NLAPolicySet *policy_set,
                 size_t header_size,
                 sd_netlink_message **ret) {
 
@@ -55,7 +55,7 @@ int message_new_full(
         int r;
 
         assert(nl);
-        assert(type_system);
+        assert(policy_set);
         assert(ret);
 
         size = NLMSG_SPACE(header_size);
@@ -65,7 +65,7 @@ int message_new_full(
         if (r < 0)
                 return r;
 
-        m->containers[0].type_system = type_system;
+        m->containers[0].policy_set = policy_set;
 
         m->hdr = malloc0(size);
         if (!m->hdr)
@@ -79,19 +79,19 @@ int message_new_full(
         return 0;
 }
 
-int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type) {
-        const NLTypeSystem *type_system;
+int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type) {
+        const NLAPolicySet *policy_set;
         size_t size;
         int r;
 
         assert_return(nl, -EINVAL);
         assert_return(ret, -EINVAL);
 
-        r = type_system_root_get_type_system_and_header_size(nl, type, &type_system, &size);
+        r = netlink_get_policy_set_and_header_size(nl, nlmsg_type, &policy_set, &size);
         if (r < 0)
                 return r;
 
-        return message_new_full(nl, type, type_system, size, ret);
+        return message_new_full(nl, nlmsg_type, policy_set, size, ret);
 }
 
 int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret) {
@@ -146,11 +146,11 @@ _public_ sd_netlink_message* sd_netlink_message_unref(sd_netlink_message *m) {
         return NULL;
 }
 
-_public_ int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type) {
+_public_ int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *ret) {
         assert_return(m, -EINVAL);
-        assert_return(type, -EINVAL);
+        assert_return(ret, -EINVAL);
 
-        *type = m->hdr->nlmsg_type;
+        *ret = m->hdr->nlmsg_type;
 
         return 0;
 }
@@ -170,9 +170,8 @@ _public_ int sd_netlink_message_is_broadcast(sd_netlink_message *m) {
         return m->multicast_group != 0;
 }
 
-/* If successful the updated message will be correctly aligned, if
-   unsuccessful the old message is untouched. */
-static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *data, size_t data_length) {
+/* If successful the updated message will be correctly aligned, if unsuccessful the old message is untouched. */
+static int add_rtattr(sd_netlink_message *m, uint16_t attr_type, const void *data, size_t data_length) {
         size_t message_length;
         struct nlmsghdr *new_hdr;
         struct rtattr *rta;
@@ -200,7 +199,7 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da
         /* get pointer to the attribute we are about to add */
         rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
 
-        rtattr_append_attribute_internal(rta, type, data, data_length);
+        rtattr_append_attribute_internal(rta, attr_type, data, data_length);
 
         /* if we are inside containers, extend them */
         for (unsigned i = 0; i < m->n_containers; i++)
@@ -214,24 +213,24 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da
         return offset;
 }
 
-static int message_attribute_has_type(sd_netlink_message *m, size_t *out_size, uint16_t attribute_type, uint16_t data_type) {
-        const NLType *type;
+static int message_attribute_has_type(sd_netlink_message *m, size_t *ret_size, uint16_t attr_type, NLAType type) {
+        const NLAPolicy *policy;
 
         assert(m);
 
-        type = type_system_get_type(m->containers[m->n_containers].type_system, attribute_type);
-        if (!type)
+        policy = policy_set_get_policy(m->containers[m->n_containers].policy_set, attr_type);
+        if (!policy)
                 return -EOPNOTSUPP;
 
-        if (type_get_type(type) != data_type)
+        if (policy_get_type(policy) != type)
                 return -EINVAL;
 
-        if (out_size)
-                *out_size = type_get_size(type);
+        if (ret_size)
+                *ret_size = policy_get_size(policy);
         return 0;
 }
 
-_public_ int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data) {
+_public_ int sd_netlink_message_append_string(sd_netlink_message *m, uint16_t attr_type, const char *data) {
         size_t length, size;
         int r;
 
@@ -239,7 +238,7 @@ _public_ int sd_netlink_message_append_string(sd_netlink_message *m, unsigned sh
         assert_return(!m->sealed, -EPERM);
         assert_return(data, -EINVAL);
 
-        r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_STRING);
+        r = message_attribute_has_type(m, &size, attr_type, NETLINK_TYPE_STRING);
         if (r < 0)
                 return r;
 
@@ -250,14 +249,14 @@ _public_ int sd_netlink_message_append_string(sd_netlink_message *m, unsigned sh
         } else
                 length = strlen(data);
 
-        r = add_rtattr(m, type, data, length + 1);
+        r = add_rtattr(m, attr_type, data, length + 1);
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_strv(sd_netlink_message *m, unsigned short type, char * const *data) {
+_public_ int sd_netlink_message_append_strv(sd_netlink_message *m, uint16_t attr_type, char * const *data) {
         size_t length, size;
         int r;
 
@@ -265,7 +264,7 @@ _public_ int sd_netlink_message_append_strv(sd_netlink_message *m, unsigned shor
         assert_return(!m->sealed, -EPERM);
         assert_return(data, -EINVAL);
 
-        r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_STRING);
+        r = message_attribute_has_type(m, &size, attr_type, NETLINK_TYPE_STRING);
         if (r < 0)
                 return r;
 
@@ -277,7 +276,7 @@ _public_ int sd_netlink_message_append_strv(sd_netlink_message *m, unsigned shor
                 } else
                         length = strlen(*p);
 
-                r = add_rtattr(m, type, *p, length + 1);
+                r = add_rtattr(m, attr_type, *p, length + 1);
                 if (r < 0)
                         return r;
         }
@@ -285,167 +284,167 @@ _public_ int sd_netlink_message_append_strv(sd_netlink_message *m, unsigned shor
         return 0;
 }
 
-_public_ int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type) {
+_public_ int sd_netlink_message_append_flag(sd_netlink_message *m, uint16_t attr_type) {
         size_t size;
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_FLAG);
+        r = message_attribute_has_type(m, &size, attr_type, NETLINK_TYPE_FLAG);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, NULL, 0);
+        r = add_rtattr(m, attr_type, NULL, 0);
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data) {
+_public_ int sd_netlink_message_append_u8(sd_netlink_message *m, uint16_t attr_type, uint8_t data) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_U8);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, &data, sizeof(uint8_t));
+        r = add_rtattr(m, attr_type, &data, sizeof(uint8_t));
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data) {
+_public_ int sd_netlink_message_append_u16(sd_netlink_message *m, uint16_t attr_type, uint16_t data) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_U16);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, &data, sizeof(uint16_t));
+        r = add_rtattr(m, attr_type, &data, sizeof(uint16_t));
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, uint32_t data) {
+_public_ int sd_netlink_message_append_u32(sd_netlink_message *m, uint16_t attr_type, uint32_t data) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_U32);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, &data, sizeof(uint32_t));
+        r = add_rtattr(m, attr_type, &data, sizeof(uint32_t));
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_u64(sd_netlink_message *m, unsigned short type, uint64_t data) {
+_public_ int sd_netlink_message_append_u64(sd_netlink_message *m, uint16_t attr_type, uint64_t data) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U64);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_U64);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, &data, sizeof(uint64_t));
+        r = add_rtattr(m, attr_type, &data, sizeof(uint64_t));
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_s8(sd_netlink_message *m, unsigned short type, int8_t data) {
+_public_ int sd_netlink_message_append_s8(sd_netlink_message *m, uint16_t attr_type, int8_t data) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_S8);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_S8);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, &data, sizeof(int8_t));
+        r = add_rtattr(m, attr_type, &data, sizeof(int8_t));
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_s16(sd_netlink_message *m, unsigned short type, int16_t data) {
+_public_ int sd_netlink_message_append_s16(sd_netlink_message *m, uint16_t attr_type, int16_t data) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_S16);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_S16);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, &data, sizeof(int16_t));
+        r = add_rtattr(m, attr_type, &data, sizeof(int16_t));
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_s32(sd_netlink_message *m, unsigned short type, int32_t data) {
+_public_ int sd_netlink_message_append_s32(sd_netlink_message *m, uint16_t attr_type, int32_t data) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_S32);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_S32);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, &data, sizeof(int32_t));
+        r = add_rtattr(m, attr_type, &data, sizeof(int32_t));
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_s64(sd_netlink_message *m, unsigned short type, int64_t data) {
+_public_ int sd_netlink_message_append_s64(sd_netlink_message *m, uint16_t attr_type, int64_t data) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_S64);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_S64);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, &data, sizeof(int64_t));
+        r = add_rtattr(m, attr_type, &data, sizeof(int64_t));
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len) {
+_public_ int sd_netlink_message_append_data(sd_netlink_message *m, uint16_t attr_type, const void *data, size_t len) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
 
-        r = add_rtattr(m, type, data, len);
+        r = add_rtattr(m, attr_type, data, len);
         if (r < 0)
                 return r;
 
@@ -454,8 +453,8 @@ _public_ int sd_netlink_message_append_data(sd_netlink_message *m, unsigned shor
 
 _public_ int sd_netlink_message_append_container_data(
                 sd_netlink_message *m,
-                unsigned short container_type,
-                unsigned short type,
+                uint16_t container_type,
+                uint16_t attr_type,
                 const void *data,
                 size_t len) {
 
@@ -468,14 +467,14 @@ _public_ int sd_netlink_message_append_container_data(
         if (r < 0)
                 return r;
 
-        r = sd_netlink_message_append_data(m, type, data, len);
+        r = sd_netlink_message_append_data(m, attr_type, data, len);
         if (r < 0)
                 return r;
 
         return sd_netlink_message_close_container(m);
 }
 
-int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data) {
+int netlink_message_append_in_addr_union(sd_netlink_message *m, uint16_t attr_type, int family, const union in_addr_union *data) {
         int r;
 
         assert_return(m, -EINVAL);
@@ -483,26 +482,26 @@ int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short t
         assert_return(data, -EINVAL);
         assert_return(IN_SET(family, AF_INET, AF_INET6), -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_IN_ADDR);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, data, FAMILY_ADDRESS_SIZE(family));
+        r = add_rtattr(m, attr_type, data, FAMILY_ADDRESS_SIZE(family));
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data) {
-        return netlink_message_append_in_addr_union(m, type, AF_INET, (const union in_addr_union *) data);
+_public_ int sd_netlink_message_append_in_addr(sd_netlink_message *m, uint16_t attr_type, const struct in_addr *data) {
+        return netlink_message_append_in_addr_union(m, attr_type, AF_INET, (const union in_addr_union *) data);
 }
 
-_public_ int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data) {
-        return netlink_message_append_in_addr_union(m, type, AF_INET6, (const union in_addr_union *) data);
+_public_ int sd_netlink_message_append_in6_addr(sd_netlink_message *m, uint16_t attr_type, const struct in6_addr *data) {
+        return netlink_message_append_in_addr_union(m, attr_type, AF_INET6, (const union in_addr_union *) data);
 }
 
-int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data) {
+int netlink_message_append_sockaddr_union(sd_netlink_message *m, uint16_t attr_type, const union sockaddr_union *data) {
         int r;
 
         assert_return(m, -EINVAL);
@@ -510,44 +509,44 @@ int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short
         assert_return(data, -EINVAL);
         assert_return(IN_SET(data->sa.sa_family, AF_INET, AF_INET6), -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_SOCKADDR);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_SOCKADDR);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, data, data->sa.sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
+        r = add_rtattr(m, attr_type, data, data->sa.sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_sockaddr_in(sd_netlink_message *m, unsigned short type, const struct sockaddr_in *data) {
-        return netlink_message_append_sockaddr_union(m, type, (const union sockaddr_union *) data);
+_public_ int sd_netlink_message_append_sockaddr_in(sd_netlink_message *m, uint16_t attr_type, const struct sockaddr_in *data) {
+        return netlink_message_append_sockaddr_union(m, attr_type, (const union sockaddr_union *) data);
 }
 
-_public_ int sd_netlink_message_append_sockaddr_in6(sd_netlink_message *m, unsigned short type, const struct sockaddr_in6 *data) {
-        return netlink_message_append_sockaddr_union(m, type, (const union sockaddr_union *) data);
+_public_ int sd_netlink_message_append_sockaddr_in6(sd_netlink_message *m, uint16_t attr_type, const struct sockaddr_in6 *data) {
+        return netlink_message_append_sockaddr_union(m, attr_type, (const union sockaddr_union *) data);
 }
 
-_public_ int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data) {
+_public_ int sd_netlink_message_append_ether_addr(sd_netlink_message *m, uint16_t attr_type, const struct ether_addr *data) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
         assert_return(data, -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_ETHER_ADDR);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, data, ETH_ALEN);
+        r = add_rtattr(m, attr_type, data, ETH_ALEN);
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-int netlink_message_append_hw_addr(sd_netlink_message *m, unsigned short type, const struct hw_addr_data *data) {
+int netlink_message_append_hw_addr(sd_netlink_message *m, uint16_t attr_type, const struct hw_addr_data *data) {
         int r;
 
         assert_return(m, -EINVAL);
@@ -555,36 +554,36 @@ int netlink_message_append_hw_addr(sd_netlink_message *m, unsigned short type, c
         assert_return(data, -EINVAL);
         assert_return(data->length > 0, -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_ETHER_ADDR);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, data->bytes, data->length);
+        r = add_rtattr(m, attr_type, data->bytes, data->length);
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
+_public_ int sd_netlink_message_append_cache_info(sd_netlink_message *m, uint16_t attr_type, const struct ifa_cacheinfo *info) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
         assert_return(info, -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_CACHE_INFO);
         if (r < 0)
                 return r;
 
-        r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
+        r = add_rtattr(m, attr_type, info, sizeof(struct ifa_cacheinfo));
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type) {
+_public_ int sd_netlink_message_open_container(sd_netlink_message *m, uint16_t attr_type) {
         size_t size;
         int r;
 
@@ -593,12 +592,12 @@ _public_ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned s
         /* m->containers[m->n_containers + 1] is accessed both in read and write. Prevent access out of bound */
         assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
 
-        r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_NESTED);
+        r = message_attribute_has_type(m, &size, attr_type, NETLINK_TYPE_NESTED);
         if (r < 0) {
-                const NLTypeSystemUnion *type_system_union;
+                const NLAPolicySetUnion *policy_set_union;
                 int family;
 
-                r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_UNION);
+                r = message_attribute_has_type(m, &size, attr_type, NETLINK_TYPE_NESTED_UNION_BY_FAMILY);
                 if (r < 0)
                         return r;
 
@@ -606,25 +605,25 @@ _public_ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned s
                 if (r < 0)
                         return r;
 
-                type_system_union = type_system_get_type_system_union(
-                                m->containers[m->n_containers].type_system,
-                                type);
-                if (!type_system_union)
+                policy_set_union = policy_set_get_policy_set_union(
+                                m->containers[m->n_containers].policy_set,
+                                attr_type);
+                if (!policy_set_union)
                         return -EOPNOTSUPP;
 
-                m->containers[m->n_containers + 1].type_system =
-                        type_system_union_get_type_system_by_protocol(
-                                type_system_union,
+                m->containers[m->n_containers + 1].policy_set =
+                        policy_set_union_get_policy_set_by_family(
+                                policy_set_union,
                                 family);
         } else
-                m->containers[m->n_containers + 1].type_system =
-                        type_system_get_type_system(
-                                m->containers[m->n_containers].type_system,
-                                type);
-        if (!m->containers[m->n_containers + 1].type_system)
+                m->containers[m->n_containers + 1].policy_set =
+                        policy_set_get_policy_set(
+                                m->containers[m->n_containers].policy_set,
+                                attr_type);
+        if (!m->containers[m->n_containers + 1].policy_set)
                 return -EOPNOTSUPP;
 
-        r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
+        r = add_rtattr(m, attr_type | NLA_F_NESTED, NULL, size);
         if (r < 0)
                 return r;
 
@@ -633,33 +632,37 @@ _public_ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned s
         return 0;
 }
 
-_public_ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned short type, const char *key) {
-        const NLTypeSystemUnion *type_system_union;
+_public_ int sd_netlink_message_open_container_union(sd_netlink_message *m, uint16_t attr_type, const char *key) {
+        const NLAPolicySetUnion *policy_set_union;
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
         assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
 
-        type_system_union = type_system_get_type_system_union(
-                        m->containers[m->n_containers].type_system,
-                        type);
-        if (!type_system_union)
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_NESTED_UNION_BY_STRING);
+        if (r < 0)
+                return r;
+
+        policy_set_union = policy_set_get_policy_set_union(
+                        m->containers[m->n_containers].policy_set,
+                        attr_type);
+        if (!policy_set_union)
                 return -EOPNOTSUPP;
 
-        m->containers[m->n_containers + 1].type_system =
-                type_system_union_get_type_system_by_string(
-                        type_system_union,
+        m->containers[m->n_containers + 1].policy_set =
+                policy_set_union_get_policy_set_by_string(
+                        policy_set_union,
                         key);
-        if (!m->containers[m->n_containers + 1].type_system)
+        if (!m->containers[m->n_containers + 1].policy_set)
                 return -EOPNOTSUPP;
 
-        r = sd_netlink_message_append_string(m, type_system_union_get_match_attribute(type_system_union), key);
+        r = sd_netlink_message_append_string(m, policy_set_union_get_match_attribute(policy_set_union), key);
         if (r < 0)
                 return r;
 
         /* do we ever need non-null size */
-        r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0);
+        r = add_rtattr(m, attr_type | NLA_F_NESTED, NULL, 0);
         if (r < 0)
                 return r;
 
@@ -673,27 +676,27 @@ _public_ int sd_netlink_message_close_container(sd_netlink_message *m) {
         assert_return(!m->sealed, -EPERM);
         assert_return(m->n_containers > 0, -EINVAL);
 
-        m->containers[m->n_containers].type_system = NULL;
+        m->containers[m->n_containers].policy_set = NULL;
         m->containers[m->n_containers].offset = 0;
         m->n_containers--;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type) {
+_public_ int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t attr_type) {
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(!m->sealed, -EPERM);
         assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
 
-        r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0);
+        r = add_rtattr(m, attr_type | NLA_F_NESTED, NULL, 0);
         if (r < 0)
                 return r;
 
         m->containers[m->n_containers].offset = r;
         m->n_containers++;
-        m->containers[m->n_containers].type_system = m->containers[m->n_containers - 1].type_system;
+        m->containers[m->n_containers].policy_set = m->containers[m->n_containers - 1].policy_set;
 
         return 0;
 }
@@ -713,14 +716,14 @@ _public_ int sd_netlink_message_cancel_array(sd_netlink_message *m) {
         m->hdr->nlmsg_len -= rta_len;
 
         m->n_containers--;
-        m->containers[m->n_containers].type_system = NULL;
+        m->containers[m->n_containers].policy_set = NULL;
 
         return 0;
 }
 
 static int netlink_message_read_internal(
                 sd_netlink_message *m,
-                unsigned short type,
+                uint16_t attr_type,
                 void **ret_data,
                 bool *ret_net_byteorder) {
 
@@ -735,10 +738,10 @@ static int netlink_message_read_internal(
         if (!m->containers[m->n_containers].attributes)
                 return -ENODATA;
 
-        if (type > m->containers[m->n_containers].max_attribute)
+        if (attr_type > m->containers[m->n_containers].max_attribute)
                 return -ENODATA;
 
-        attribute = &m->containers[m->n_containers].attributes[type];
+        attribute = &m->containers[m->n_containers].attributes[attr_type];
 
         if (attribute->offset == 0)
                 return -ENODATA;
@@ -754,13 +757,13 @@ static int netlink_message_read_internal(
         return RTA_PAYLOAD(rta);
 }
 
-_public_ int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t size, void *data) {
+_public_ int sd_netlink_message_read(sd_netlink_message *m, uint16_t attr_type, size_t size, void *data) {
         void *attr_data;
         int r;
 
         assert_return(m, -EINVAL);
 
-        r = netlink_message_read_internal(m, type, &attr_data, NULL);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, NULL);
         if (r < 0)
                 return r;
 
@@ -773,13 +776,13 @@ _public_ int sd_netlink_message_read(sd_netlink_message *m, unsigned short type,
         return r;
 }
 
-_public_ int sd_netlink_message_read_data(sd_netlink_message *m, unsigned short type, size_t *ret_size, void **ret_data) {
+_public_ int sd_netlink_message_read_data(sd_netlink_message *m, uint16_t attr_type, size_t *ret_size, void **ret_data) {
         void *attr_data;
         int r;
 
         assert_return(m, -EINVAL);
 
-        r = netlink_message_read_internal(m, type, &attr_data, NULL);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, NULL);
         if (r < 0)
                 return r;
 
@@ -799,13 +802,13 @@ _public_ int sd_netlink_message_read_data(sd_netlink_message *m, unsigned short
         return r;
 }
 
-_public_ int sd_netlink_message_read_data_suffix0(sd_netlink_message *m, unsigned short type, size_t *ret_size, void **ret_data) {
+_public_ int sd_netlink_message_read_data_suffix0(sd_netlink_message *m, uint16_t attr_type, size_t *ret_size, void **ret_data) {
         void *attr_data;
         int r;
 
         assert_return(m, -EINVAL);
 
-        r = netlink_message_read_internal(m, type, &attr_data, NULL);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, NULL);
         if (r < 0)
                 return r;
 
@@ -825,17 +828,17 @@ _public_ int sd_netlink_message_read_data_suffix0(sd_netlink_message *m, unsigne
         return r;
 }
 
-_public_ int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data) {
+_public_ int sd_netlink_message_read_string_strdup(sd_netlink_message *m, uint16_t attr_type, char **data) {
         void *attr_data;
         int r;
 
         assert_return(m, -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_STRING);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_STRING);
         if (r < 0)
                 return r;
 
-        r = netlink_message_read_internal(m, type, &attr_data, NULL);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, NULL);
         if (r < 0)
                 return r;
 
@@ -852,17 +855,17 @@ _public_ int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsign
         return 0;
 }
 
-_public_ int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data) {
+_public_ int sd_netlink_message_read_string(sd_netlink_message *m, uint16_t attr_type, const char **data) {
         void *attr_data;
         int r;
 
         assert_return(m, -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_STRING);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_STRING);
         if (r < 0)
                 return r;
 
-        r = netlink_message_read_internal(m, type, &attr_data, NULL);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, NULL);
         if (r < 0)
                 return r;
 
@@ -875,17 +878,17 @@ _public_ int sd_netlink_message_read_string(sd_netlink_message *m, unsigned shor
         return 0;
 }
 
-_public_ int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data) {
+_public_ int sd_netlink_message_read_u8(sd_netlink_message *m, uint16_t attr_type, uint8_t *data) {
         void *attr_data;
         int r;
 
         assert_return(m, -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_U8);
         if (r < 0)
                 return r;
 
-        r = netlink_message_read_internal(m, type, &attr_data, NULL);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, NULL);
         if (r < 0)
                 return r;
 
@@ -898,18 +901,18 @@ _public_ int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short ty
         return 0;
 }
 
-_public_ int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data) {
+_public_ int sd_netlink_message_read_u16(sd_netlink_message *m, uint16_t attr_type, uint16_t *data) {
         void *attr_data;
         bool net_byteorder;
         int r;
 
         assert_return(m, -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_U16);
         if (r < 0)
                 return r;
 
-        r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, &net_byteorder);
         if (r < 0)
                 return r;
 
@@ -926,18 +929,18 @@ _public_ int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short t
         return 0;
 }
 
-_public_ int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data) {
+_public_ int sd_netlink_message_read_u32(sd_netlink_message *m, uint16_t attr_type, uint32_t *data) {
         void *attr_data;
         bool net_byteorder;
         int r;
 
         assert_return(m, -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_U32);
         if (r < 0)
                 return r;
 
-        r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, &net_byteorder);
         if (r < 0)
                 return r;
 
@@ -954,17 +957,17 @@ _public_ int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short t
         return 0;
 }
 
-_public_ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short type, struct ether_addr *data) {
+_public_ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, uint16_t attr_type, struct ether_addr *data) {
         void *attr_data;
         int r;
 
         assert_return(m, -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_ETHER_ADDR);
         if (r < 0)
                 return r;
 
-        r = netlink_message_read_internal(m, type, &attr_data, NULL);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, NULL);
         if (r < 0)
                 return r;
 
@@ -977,17 +980,17 @@ _public_ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned
         return 0;
 }
 
-int netlink_message_read_hw_addr(sd_netlink_message *m, unsigned short type, struct hw_addr_data *data) {
+int netlink_message_read_hw_addr(sd_netlink_message *m, uint16_t attr_type, struct hw_addr_data *data) {
         void *attr_data;
         int r;
 
         assert_return(m, -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_ETHER_ADDR);
         if (r < 0)
                 return r;
 
-        r = netlink_message_read_internal(m, type, &attr_data, NULL);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, NULL);
         if (r < 0)
                 return r;
 
@@ -1002,17 +1005,17 @@ int netlink_message_read_hw_addr(sd_netlink_message *m, unsigned short type, str
         return 0;
 }
 
-_public_ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info) {
+_public_ int sd_netlink_message_read_cache_info(sd_netlink_message *m, uint16_t attr_type, struct ifa_cacheinfo *info) {
         void *attr_data;
         int r;
 
         assert_return(m, -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_CACHE_INFO);
         if (r < 0)
                 return r;
 
-        r = netlink_message_read_internal(m, type, &attr_data, NULL);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, NULL);
         if (r < 0)
                 return r;
 
@@ -1025,18 +1028,18 @@ _public_ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned
         return 0;
 }
 
-int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short type, int family, union in_addr_union *data) {
+int netlink_message_read_in_addr_union(sd_netlink_message *m, uint16_t attr_type, int family, union in_addr_union *data) {
         void *attr_data;
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(IN_SET(family, AF_INET, AF_INET6), -EINVAL);
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_IN_ADDR);
         if (r < 0)
                 return r;
 
-        r = netlink_message_read_internal(m, type, &attr_data, NULL);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, NULL);
         if (r < 0)
                 return r;
 
@@ -1049,29 +1052,29 @@ int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short typ
         return 0;
 }
 
-_public_ int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) {
+_public_ int sd_netlink_message_read_in_addr(sd_netlink_message *m, uint16_t attr_type, struct in_addr *data) {
         union in_addr_union u;
         int r;
 
-        r = netlink_message_read_in_addr_union(m, type, AF_INET, &u);
+        r = netlink_message_read_in_addr_union(m, attr_type, AF_INET, &u);
         if (r >= 0 && data)
                 *data = u.in;
 
         return r;
 }
 
-_public_ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) {
+_public_ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, uint16_t attr_type, struct in6_addr *data) {
         union in_addr_union u;
         int r;
 
-        r = netlink_message_read_in_addr_union(m, type, AF_INET6, &u);
+        r = netlink_message_read_in_addr_union(m, attr_type, AF_INET6, &u);
         if (r >= 0 && data)
                 *data = u.in6;
 
         return r;
 }
 
-_public_ int sd_netlink_message_has_flag(sd_netlink_message *m, unsigned short type) {
+_public_ int sd_netlink_message_has_flag(sd_netlink_message *m, uint16_t attr_type) {
         void *attr_data;
         int r;
 
@@ -1079,11 +1082,11 @@ _public_ int sd_netlink_message_has_flag(sd_netlink_message *m, unsigned short t
 
         /* This returns 1 when the flag is set, 0 when not set, negative errno on error. */
 
-        r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_FLAG);
+        r = message_attribute_has_type(m, NULL, attr_type, NETLINK_TYPE_FLAG);
         if (r < 0)
                 return r;
 
-        r = netlink_message_read_internal(m, type, &attr_data, NULL);
+        r = netlink_message_read_internal(m, attr_type, &attr_data, NULL);
         if (r == -ENODATA)
                 return 0;
         if (r < 0)
@@ -1092,10 +1095,10 @@ _public_ int sd_netlink_message_has_flag(sd_netlink_message *m, unsigned short t
         return 1;
 }
 
-_public_ int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret) {
+_public_ int sd_netlink_message_read_strv(sd_netlink_message *m, uint16_t container_type, uint16_t attr_type, char ***ret) {
         _cleanup_strv_free_ char **s = NULL;
-        const NLTypeSystem *type_system;
-        const NLType *nl_type;
+        const NLAPolicySet *policy_set;
+        const NLAPolicy *policy;
         struct rtattr *rta;
         void *container;
         size_t rt_len;
@@ -1104,26 +1107,26 @@ _public_ int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short
         assert_return(m, -EINVAL);
         assert_return(m->n_containers < NETLINK_CONTAINER_DEPTH, -EINVAL);
 
-        nl_type = type_system_get_type(
-                        m->containers[m->n_containers].type_system,
+        policy = policy_set_get_policy(
+                        m->containers[m->n_containers].policy_set,
                         container_type);
-        if (!nl_type)
+        if (!policy)
                 return -EOPNOTSUPP;
 
-        if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
+        if (policy_get_type(policy) != NETLINK_TYPE_NESTED)
                 return -EINVAL;
 
-        type_system = type_system_get_type_system(
-                        m->containers[m->n_containers].type_system,
+        policy_set = policy_set_get_policy_set(
+                        m->containers[m->n_containers].policy_set,
                         container_type);
-        if (!type_system)
+        if (!policy_set)
                 return -EOPNOTSUPP;
 
-        nl_type = type_system_get_type(type_system, type_id);
-        if (!nl_type)
+        policy = policy_set_get_policy(policy_set, attr_type);
+        if (!policy)
                 return -EOPNOTSUPP;
 
-        if (type_get_type(nl_type) != NETLINK_TYPE_STRING)
+        if (policy_get_type(policy) != NETLINK_TYPE_STRING)
                 return -EINVAL;
 
         r = netlink_message_read_internal(m, container_type, &container, NULL);
@@ -1138,10 +1141,10 @@ _public_ int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short
          * introduce an unsigned short variable as a workaround. */
         unsigned short len = rt_len;
         for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
-                unsigned short type;
+                uint16_t type;
 
                 type = RTA_TYPE(rta);
-                if (type != type_id)
+                if (type != attr_type)
                         continue;
 
                 r = strv_extend(&s, RTA_DATA(rta));
@@ -1189,81 +1192,73 @@ static int netlink_container_parse(
         return 0;
 }
 
-_public_ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type_id) {
-        const NLType *nl_type;
-        const NLTypeSystem *type_system;
+_public_ int sd_netlink_message_enter_container(sd_netlink_message *m, uint16_t attr_type) {
+        const NLAPolicy *policy;
+        const NLAPolicySet *policy_set;
         void *container;
-        uint16_t type;
         size_t size;
         int r;
 
         assert_return(m, -EINVAL);
         assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -EINVAL);
 
-        nl_type = type_system_get_type(
-                        m->containers[m->n_containers].type_system,
-                        type_id);
-        if (!nl_type)
+        policy = policy_set_get_policy(
+                        m->containers[m->n_containers].policy_set,
+                        attr_type);
+        if (!policy)
                 return -EOPNOTSUPP;
 
-        type = type_get_type(nl_type);
+        switch (policy_get_type(policy)) {
+        case NETLINK_TYPE_NESTED:
+                policy_set = policy_set_get_policy_set(
+                                m->containers[m->n_containers].policy_set,
+                                attr_type);
+                break;
+
+        case NETLINK_TYPE_NESTED_UNION_BY_STRING: {
+                const NLAPolicySetUnion *policy_set_union;
+                const char *key;
 
-        if (type == NETLINK_TYPE_NESTED) {
-                type_system = type_system_get_type_system(
-                                m->containers[m->n_containers].type_system,
-                                type_id);
-                if (!type_system)
+                policy_set_union = policy_get_policy_set_union(policy);
+                if (!policy_set_union)
                         return -EOPNOTSUPP;
-        } else if (type == NETLINK_TYPE_UNION) {
-                const NLTypeSystemUnion *type_system_union;
 
-                type_system_union = type_system_get_type_system_union(
-                                 m->containers[m->n_containers].type_system,
-                                 type_id);
-                if (!type_system_union)
+                r = sd_netlink_message_read_string(
+                                m,
+                                policy_set_union_get_match_attribute(policy_set_union),
+                                &key);
+                if (r < 0)
+                        return r;
+
+                policy_set = policy_set_union_get_policy_set_by_string(
+                                policy_set_union,
+                                key);
+                break;
+        }
+        case NETLINK_TYPE_NESTED_UNION_BY_FAMILY: {
+                const NLAPolicySetUnion *policy_set_union;
+                int family;
+
+                policy_set_union = policy_get_policy_set_union(policy);
+                if (!policy_set_union)
                         return -EOPNOTSUPP;
 
-                switch (type_system_union_get_match_type(type_system_union)) {
-                case NL_MATCH_SIBLING: {
-                        const char *key;
-
-                        r = sd_netlink_message_read_string(
-                                        m,
-                                        type_system_union_get_match_attribute(type_system_union),
-                                        &key);
-                        if (r < 0)
-                                return r;
-
-                        type_system = type_system_union_get_type_system_by_string(
-                                        type_system_union,
-                                        key);
-                        if (!type_system)
-                                return -EOPNOTSUPP;
-
-                        break;
-                }
-                case NL_MATCH_PROTOCOL: {
-                        int family;
-
-                        r = sd_rtnl_message_get_family(m, &family);
-                        if (r < 0)
-                                return r;
-
-                        type_system = type_system_union_get_type_system_by_protocol(
-                                        type_system_union,
-                                        family);
-                        if (!type_system)
-                                return -EOPNOTSUPP;
-
-                        break;
-                }
-                default:
-                        assert_not_reached();
-                }
-        } else
-                return -EINVAL;
+                r = sd_rtnl_message_get_family(m, &family);
+                if (r < 0)
+                        return r;
+
+                policy_set = policy_set_union_get_policy_set_by_family(
+                                policy_set_union,
+                                family);
+                break;
+        }
+        default:
+                assert_not_reached();
+        }
+        if (!policy_set)
+                return -EOPNOTSUPP;
 
-        r = netlink_message_read_internal(m, type_id, &container, NULL);
+        r = netlink_message_read_internal(m, attr_type, &container, NULL);
         if (r < 0)
                 return r;
 
@@ -1279,12 +1274,12 @@ _public_ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned
                 return r;
         }
 
-        m->containers[m->n_containers].type_system = type_system;
+        m->containers[m->n_containers].policy_set = policy_set;
 
         return 0;
 }
 
-_public_ int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id) {
+_public_ int sd_netlink_message_enter_array(sd_netlink_message *m, uint16_t attr_type) {
         void *container;
         size_t size;
         int r;
@@ -1292,7 +1287,7 @@ _public_ int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned shor
         assert_return(m, -EINVAL);
         assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -EINVAL);
 
-        r = netlink_message_read_internal(m, type_id, &container, NULL);
+        r = netlink_message_read_internal(m, attr_type, &container, NULL);
         if (r < 0)
                 return r;
 
@@ -1308,7 +1303,7 @@ _public_ int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned shor
                 return r;
         }
 
-        m->containers[m->n_containers].type_system = m->containers[m->n_containers - 1].type_system;
+        m->containers[m->n_containers].policy_set = m->containers[m->n_containers - 1].policy_set;
 
         return 0;
 }
@@ -1320,7 +1315,7 @@ _public_ int sd_netlink_message_exit_container(sd_netlink_message *m) {
 
         m->containers[m->n_containers].attributes = mfree(m->containers[m->n_containers].attributes);
         m->containers[m->n_containers].max_attribute = 0;
-        m->containers[m->n_containers].type_system = NULL;
+        m->containers[m->n_containers].policy_set = NULL;
 
         m->n_containers--;
 
@@ -1399,8 +1394,8 @@ _public_ int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *nl) {
 
         assert(m->hdr);
 
-        r = type_system_root_get_type_system_and_header_size(nl, m->hdr->nlmsg_type,
-                                                             &m->containers[0].type_system, &size);
+        r = netlink_get_policy_set_and_header_size(nl, m->hdr->nlmsg_type,
+                                                   &m->containers[0].policy_set, &size);
         if (r < 0)
                 return r;
 
index e834f31122b9ded2772e7fb0df01168aa53f2143..605e80916c7b4c41d05240d481b6ba2b7a9bfb7b 100644 (file)
@@ -308,7 +308,7 @@ int socket_read_message(sd_netlink *nl) {
                 }
 
                 /* check that we support this message type */
-                r = type_system_root_get_type_system_and_header_size(nl, new_msg->nlmsg_type, NULL, &size);
+                r = netlink_get_policy_set_and_header_size(nl, new_msg->nlmsg_type, NULL, &size);
                 if (r < 0) {
                         if (r == -EOPNOTSUPP)
                                 log_debug("sd-netlink: ignored message with unknown type: %i",
index 15becad30df96596401429b74548ca2da5ff45ad..9d6d978b45995783c7e81cfa6832782e6b36b78b 100644 (file)
 #include "netlink-types-internal.h"
 
 /***************** genl ctrl type systems *****************/
-static const NLType genl_ctrl_mcast_group_types[] = {
-        [CTRL_ATTR_MCAST_GRP_NAME]  = { .type = NETLINK_TYPE_STRING },
-        [CTRL_ATTR_MCAST_GRP_ID]    = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy genl_ctrl_mcast_group_policies[] = {
+        [CTRL_ATTR_MCAST_GRP_NAME]  = BUILD_POLICY(STRING),
+        [CTRL_ATTR_MCAST_GRP_ID]    = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(genl_ctrl_mcast_group);
+DEFINE_POLICY_SET(genl_ctrl_mcast_group);
 
-static const NLType genl_ctrl_ops_types[] = {
-        [CTRL_ATTR_OP_ID]           = { .type = NETLINK_TYPE_U32 },
-        [CTRL_ATTR_OP_FLAGS]        = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy genl_ctrl_ops_policies[] = {
+        [CTRL_ATTR_OP_ID]           = BUILD_POLICY(U32),
+        [CTRL_ATTR_OP_FLAGS]        = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(genl_ctrl_ops);
+DEFINE_POLICY_SET(genl_ctrl_ops);
 
-static const NLType genl_ctrl_types[] = {
-        [CTRL_ATTR_FAMILY_ID]    = { .type = NETLINK_TYPE_U16 },
-        [CTRL_ATTR_FAMILY_NAME]  = { .type = NETLINK_TYPE_STRING },
-        [CTRL_ATTR_VERSION]      = { .type = NETLINK_TYPE_U32 },
-        [CTRL_ATTR_HDRSIZE]      = { .type = NETLINK_TYPE_U32 },
-        [CTRL_ATTR_MAXATTR]      = { .type = NETLINK_TYPE_U32 },
-        [CTRL_ATTR_OPS]          = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_ctrl_ops_type_system },
-        [CTRL_ATTR_MCAST_GROUPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_ctrl_mcast_group_type_system },
+static const NLAPolicy genl_ctrl_policies[] = {
+        [CTRL_ATTR_FAMILY_ID]    = BUILD_POLICY(U16),
+        [CTRL_ATTR_FAMILY_NAME]  = BUILD_POLICY(STRING),
+        [CTRL_ATTR_VERSION]      = BUILD_POLICY(U32),
+        [CTRL_ATTR_HDRSIZE]      = BUILD_POLICY(U32),
+        [CTRL_ATTR_MAXATTR]      = BUILD_POLICY(U32),
+        [CTRL_ATTR_OPS]          = BUILD_POLICY_NESTED(genl_ctrl_ops),
+        [CTRL_ATTR_MCAST_GROUPS] = BUILD_POLICY_NESTED(genl_ctrl_mcast_group),
         /*
         [CTRL_ATTR_POLICY]       = { .type = NETLINK_TYPE_NESTED, },
         [CTRL_ATTR_OP_POLICY]    = { .type = NETLINK_TYPE_NESTED, }
         */
-        [CTRL_ATTR_OP]           = { .type = NETLINK_TYPE_U32 },
+        [CTRL_ATTR_OP]           = BUILD_POLICY(U32),
 };
 
 /***************** genl batadv type systems *****************/
-static const NLType genl_batadv_types[] = {
-        [BATADV_ATTR_VERSION]                       = { .type = NETLINK_TYPE_STRING },
-        [BATADV_ATTR_ALGO_NAME]                     = { .type = NETLINK_TYPE_STRING },
-        [BATADV_ATTR_MESH_IFINDEX]                  = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_MESH_IFNAME]                   = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ },
-        [BATADV_ATTR_MESH_ADDRESS]                  = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [BATADV_ATTR_HARD_IFINDEX]                  = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_HARD_IFNAME]                   = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ },
-        [BATADV_ATTR_HARD_ADDRESS]                  = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [BATADV_ATTR_ORIG_ADDRESS]                  = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [BATADV_ATTR_TPMETER_RESULT]                = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_TPMETER_TEST_TIME]             = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_TPMETER_BYTES]                 = { .type = NETLINK_TYPE_U64 },
-        [BATADV_ATTR_TPMETER_COOKIE]                = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_PAD]                           = { .type = NETLINK_TYPE_UNSPEC },
-        [BATADV_ATTR_ACTIVE]                        = { .type = NETLINK_TYPE_FLAG },
-        [BATADV_ATTR_TT_ADDRESS]                    = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [BATADV_ATTR_TT_TTVN]                       = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_TT_LAST_TTVN]                  = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_TT_CRC32]                      = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_TT_VID]                        = { .type = NETLINK_TYPE_U16 },
-        [BATADV_ATTR_TT_FLAGS]                      = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_FLAG_BEST]                     = { .type = NETLINK_TYPE_FLAG },
-        [BATADV_ATTR_LAST_SEEN_MSECS]               = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_NEIGH_ADDRESS]                 = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [BATADV_ATTR_TQ]                            = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_THROUGHPUT]                    = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_BANDWIDTH_UP]                  = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_BANDWIDTH_DOWN]                = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_ROUTER]                        = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [BATADV_ATTR_BLA_OWN]                       = { .type = NETLINK_TYPE_FLAG },
-        [BATADV_ATTR_BLA_ADDRESS]                   = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [BATADV_ATTR_BLA_VID]                       = { .type = NETLINK_TYPE_U16 },
-        [BATADV_ATTR_BLA_BACKBONE]                  = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [BATADV_ATTR_BLA_CRC]                       = { .type = NETLINK_TYPE_U16 },
-        [BATADV_ATTR_DAT_CACHE_IP4ADDRESS]          = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_DAT_CACHE_HWADDRESS]           = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [BATADV_ATTR_DAT_CACHE_VID]                 = { .type = NETLINK_TYPE_U16 },
-        [BATADV_ATTR_MCAST_FLAGS]                   = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_MCAST_FLAGS_PRIV]              = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_VLANID]                        = { .type = NETLINK_TYPE_U16 },
-        [BATADV_ATTR_AGGREGATED_OGMS_ENABLED]       = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_AP_ISOLATION_ENABLED]          = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_ISOLATION_MARK]                = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_ISOLATION_MASK]                = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_BONDING_ENABLED]               = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED] = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED] = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_FRAGMENTATION_ENABLED]         = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_GW_BANDWIDTH_DOWN]             = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_GW_BANDWIDTH_UP]               = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_GW_MODE]                       = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_GW_SEL_CLASS]                  = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_HOP_PENALTY]                   = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_LOG_LEVEL]                     = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]  = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_MULTICAST_FANOUT]              = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_NETWORK_CODING_ENABLED]        = { .type = NETLINK_TYPE_U8 },
-        [BATADV_ATTR_ORIG_INTERVAL]                 = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_ELP_INTERVAL]                  = { .type = NETLINK_TYPE_U32 },
-        [BATADV_ATTR_THROUGHPUT_OVERRIDE]           = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy genl_batadv_policies[] = {
+        [BATADV_ATTR_VERSION]                       = BUILD_POLICY(STRING),
+        [BATADV_ATTR_ALGO_NAME]                     = BUILD_POLICY(STRING),
+        [BATADV_ATTR_MESH_IFINDEX]                  = BUILD_POLICY(U32),
+        [BATADV_ATTR_MESH_IFNAME]                   = BUILD_POLICY_WITH_SIZE(STRING, IFNAMSIZ),
+        [BATADV_ATTR_MESH_ADDRESS]                  = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [BATADV_ATTR_HARD_IFINDEX]                  = BUILD_POLICY(U32),
+        [BATADV_ATTR_HARD_IFNAME]                   = BUILD_POLICY_WITH_SIZE(STRING, IFNAMSIZ),
+        [BATADV_ATTR_HARD_ADDRESS]                  = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [BATADV_ATTR_ORIG_ADDRESS]                  = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [BATADV_ATTR_TPMETER_RESULT]                = BUILD_POLICY(U8),
+        [BATADV_ATTR_TPMETER_TEST_TIME]             = BUILD_POLICY(U32),
+        [BATADV_ATTR_TPMETER_BYTES]                 = BUILD_POLICY(U64),
+        [BATADV_ATTR_TPMETER_COOKIE]                = BUILD_POLICY(U32),
+        [BATADV_ATTR_PAD]                           = BUILD_POLICY(UNSPEC),
+        [BATADV_ATTR_ACTIVE]                        = BUILD_POLICY(FLAG),
+        [BATADV_ATTR_TT_ADDRESS]                    = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [BATADV_ATTR_TT_TTVN]                       = BUILD_POLICY(U8),
+        [BATADV_ATTR_TT_LAST_TTVN]                  = BUILD_POLICY(U8),
+        [BATADV_ATTR_TT_CRC32]                      = BUILD_POLICY(U32),
+        [BATADV_ATTR_TT_VID]                        = BUILD_POLICY(U16),
+        [BATADV_ATTR_TT_FLAGS]                      = BUILD_POLICY(U32),
+        [BATADV_ATTR_FLAG_BEST]                     = BUILD_POLICY(FLAG),
+        [BATADV_ATTR_LAST_SEEN_MSECS]               = BUILD_POLICY(U32),
+        [BATADV_ATTR_NEIGH_ADDRESS]                 = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [BATADV_ATTR_TQ]                            = BUILD_POLICY(U8),
+        [BATADV_ATTR_THROUGHPUT]                    = BUILD_POLICY(U32),
+        [BATADV_ATTR_BANDWIDTH_UP]                  = BUILD_POLICY(U32),
+        [BATADV_ATTR_BANDWIDTH_DOWN]                = BUILD_POLICY(U32),
+        [BATADV_ATTR_ROUTER]                        = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [BATADV_ATTR_BLA_OWN]                       = BUILD_POLICY(FLAG),
+        [BATADV_ATTR_BLA_ADDRESS]                   = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [BATADV_ATTR_BLA_VID]                       = BUILD_POLICY(U16),
+        [BATADV_ATTR_BLA_BACKBONE]                  = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [BATADV_ATTR_BLA_CRC]                       = BUILD_POLICY(U16),
+        [BATADV_ATTR_DAT_CACHE_IP4ADDRESS]          = BUILD_POLICY(U32),
+        [BATADV_ATTR_DAT_CACHE_HWADDRESS]           = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [BATADV_ATTR_DAT_CACHE_VID]                 = BUILD_POLICY(U16),
+        [BATADV_ATTR_MCAST_FLAGS]                   = BUILD_POLICY(U32),
+        [BATADV_ATTR_MCAST_FLAGS_PRIV]              = BUILD_POLICY(U32),
+        [BATADV_ATTR_VLANID]                        = BUILD_POLICY(U16),
+        [BATADV_ATTR_AGGREGATED_OGMS_ENABLED]       = BUILD_POLICY(U8),
+        [BATADV_ATTR_AP_ISOLATION_ENABLED]          = BUILD_POLICY(U8),
+        [BATADV_ATTR_ISOLATION_MARK]                = BUILD_POLICY(U32),
+        [BATADV_ATTR_ISOLATION_MASK]                = BUILD_POLICY(U32),
+        [BATADV_ATTR_BONDING_ENABLED]               = BUILD_POLICY(U8),
+        [BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED] = BUILD_POLICY(U8),
+        [BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED] = BUILD_POLICY(U8),
+        [BATADV_ATTR_FRAGMENTATION_ENABLED]         = BUILD_POLICY(U8),
+        [BATADV_ATTR_GW_BANDWIDTH_DOWN]             = BUILD_POLICY(U32),
+        [BATADV_ATTR_GW_BANDWIDTH_UP]               = BUILD_POLICY(U32),
+        [BATADV_ATTR_GW_MODE]                       = BUILD_POLICY(U8),
+        [BATADV_ATTR_GW_SEL_CLASS]                  = BUILD_POLICY(U32),
+        [BATADV_ATTR_HOP_PENALTY]                   = BUILD_POLICY(U8),
+        [BATADV_ATTR_LOG_LEVEL]                     = BUILD_POLICY(U32),
+        [BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]  = BUILD_POLICY(U8),
+        [BATADV_ATTR_MULTICAST_FANOUT]              = BUILD_POLICY(U32),
+        [BATADV_ATTR_NETWORK_CODING_ENABLED]        = BUILD_POLICY(U8),
+        [BATADV_ATTR_ORIG_INTERVAL]                 = BUILD_POLICY(U32),
+        [BATADV_ATTR_ELP_INTERVAL]                  = BUILD_POLICY(U32),
+        [BATADV_ATTR_THROUGHPUT_OVERRIDE]           = BUILD_POLICY(U32),
 };
 
 /***************** genl fou type systems *****************/
-static const NLType genl_fou_types[] = {
-        [FOU_ATTR_PORT]              = { .type = NETLINK_TYPE_U16 },
-        [FOU_ATTR_AF]                = { .type = NETLINK_TYPE_U8 },
-        [FOU_ATTR_IPPROTO]           = { .type = NETLINK_TYPE_U8 },
-        [FOU_ATTR_TYPE]              = { .type = NETLINK_TYPE_U8 },
-        [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
-        [FOU_ATTR_LOCAL_V4]          = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in_addr) },
-        [FOU_ATTR_PEER_V4]           = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in_addr) },
-        [FOU_ATTR_LOCAL_V6]          = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
-        [FOU_ATTR_PEER_V6]           = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
-        [FOU_ATTR_PEER_PORT]         = { .type = NETLINK_TYPE_U16 },
-        [FOU_ATTR_IFINDEX]           = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy genl_fou_policies[] = {
+        [FOU_ATTR_PORT]              = BUILD_POLICY(U16),
+        [FOU_ATTR_AF]                = BUILD_POLICY(U8),
+        [FOU_ATTR_IPPROTO]           = BUILD_POLICY(U8),
+        [FOU_ATTR_TYPE]              = BUILD_POLICY(U8),
+        [FOU_ATTR_REMCSUM_NOPARTIAL] = BUILD_POLICY(FLAG),
+        [FOU_ATTR_LOCAL_V4]          = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in_addr)),
+        [FOU_ATTR_PEER_V4]           = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in_addr)),
+        [FOU_ATTR_LOCAL_V6]          = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)),
+        [FOU_ATTR_PEER_V6]           = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)),
+        [FOU_ATTR_PEER_PORT]         = BUILD_POLICY(U16),
+        [FOU_ATTR_IFINDEX]           = BUILD_POLICY(U32),
 };
 
 /***************** genl l2tp type systems *****************/
-static const NLType genl_l2tp_types[] = {
-        [L2TP_ATTR_PW_TYPE]           = { .type = NETLINK_TYPE_U16 },
-        [L2TP_ATTR_ENCAP_TYPE]        = { .type = NETLINK_TYPE_U16 },
-        [L2TP_ATTR_OFFSET]            = { .type = NETLINK_TYPE_U16 },
-        [L2TP_ATTR_DATA_SEQ]          = { .type = NETLINK_TYPE_U16 },
-        [L2TP_ATTR_L2SPEC_TYPE]       = { .type = NETLINK_TYPE_U8 },
-        [L2TP_ATTR_L2SPEC_LEN]        = { .type = NETLINK_TYPE_U8 },
-        [L2TP_ATTR_PROTO_VERSION]     = { .type = NETLINK_TYPE_U8 },
-        [L2TP_ATTR_IFNAME]            = { .type = NETLINK_TYPE_STRING },
-        [L2TP_ATTR_CONN_ID]           = { .type = NETLINK_TYPE_U32 },
-        [L2TP_ATTR_PEER_CONN_ID]      = { .type = NETLINK_TYPE_U32 },
-        [L2TP_ATTR_SESSION_ID]        = { .type = NETLINK_TYPE_U32 },
-        [L2TP_ATTR_PEER_SESSION_ID]   = { .type = NETLINK_TYPE_U32 },
-        [L2TP_ATTR_UDP_CSUM]          = { .type = NETLINK_TYPE_U8 },
-        [L2TP_ATTR_VLAN_ID]           = { .type = NETLINK_TYPE_U16 },
-        [L2TP_ATTR_RECV_SEQ]          = { .type = NETLINK_TYPE_U8 },
-        [L2TP_ATTR_SEND_SEQ]          = { .type = NETLINK_TYPE_U8 },
-        [L2TP_ATTR_LNS_MODE]          = { .type = NETLINK_TYPE_U8 },
-        [L2TP_ATTR_USING_IPSEC]       = { .type = NETLINK_TYPE_U8 },
-        [L2TP_ATTR_FD]                = { .type = NETLINK_TYPE_U32 },
-        [L2TP_ATTR_IP_SADDR]          = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in_addr) },
-        [L2TP_ATTR_IP_DADDR]          = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in_addr) },
-        [L2TP_ATTR_UDP_SPORT]         = { .type = NETLINK_TYPE_U16 },
-        [L2TP_ATTR_UDP_DPORT]         = { .type = NETLINK_TYPE_U16 },
-        [L2TP_ATTR_IP6_SADDR]         = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
-        [L2TP_ATTR_IP6_DADDR]         = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
-        [L2TP_ATTR_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_FLAG },
-        [L2TP_ATTR_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_FLAG },
+static const NLAPolicy genl_l2tp_policies[] = {
+        [L2TP_ATTR_PW_TYPE]           = BUILD_POLICY(U16),
+        [L2TP_ATTR_ENCAP_TYPE]        = BUILD_POLICY(U16),
+        [L2TP_ATTR_OFFSET]            = BUILD_POLICY(U16),
+        [L2TP_ATTR_DATA_SEQ]          = BUILD_POLICY(U16),
+        [L2TP_ATTR_L2SPEC_TYPE]       = BUILD_POLICY(U8),
+        [L2TP_ATTR_L2SPEC_LEN]        = BUILD_POLICY(U8),
+        [L2TP_ATTR_PROTO_VERSION]     = BUILD_POLICY(U8),
+        [L2TP_ATTR_IFNAME]            = BUILD_POLICY(STRING),
+        [L2TP_ATTR_CONN_ID]           = BUILD_POLICY(U32),
+        [L2TP_ATTR_PEER_CONN_ID]      = BUILD_POLICY(U32),
+        [L2TP_ATTR_SESSION_ID]        = BUILD_POLICY(U32),
+        [L2TP_ATTR_PEER_SESSION_ID]   = BUILD_POLICY(U32),
+        [L2TP_ATTR_UDP_CSUM]          = BUILD_POLICY(U8),
+        [L2TP_ATTR_VLAN_ID]           = BUILD_POLICY(U16),
+        [L2TP_ATTR_RECV_SEQ]          = BUILD_POLICY(U8),
+        [L2TP_ATTR_SEND_SEQ]          = BUILD_POLICY(U8),
+        [L2TP_ATTR_LNS_MODE]          = BUILD_POLICY(U8),
+        [L2TP_ATTR_USING_IPSEC]       = BUILD_POLICY(U8),
+        [L2TP_ATTR_FD]                = BUILD_POLICY(U32),
+        [L2TP_ATTR_IP_SADDR]          = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in_addr)),
+        [L2TP_ATTR_IP_DADDR]          = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in_addr)),
+        [L2TP_ATTR_UDP_SPORT]         = BUILD_POLICY(U16),
+        [L2TP_ATTR_UDP_DPORT]         = BUILD_POLICY(U16),
+        [L2TP_ATTR_IP6_SADDR]         = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)),
+        [L2TP_ATTR_IP6_DADDR]         = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)),
+        [L2TP_ATTR_UDP_ZERO_CSUM6_TX] = BUILD_POLICY(FLAG),
+        [L2TP_ATTR_UDP_ZERO_CSUM6_RX] = BUILD_POLICY(FLAG),
 };
 
 /***************** genl macsec type systems *****************/
-static const NLType genl_macsec_rxsc_types[] = {
-        [MACSEC_RXSC_ATTR_SCI] = { .type = NETLINK_TYPE_U64 },
+static const NLAPolicy genl_macsec_rxsc_policies[] = {
+        [MACSEC_RXSC_ATTR_SCI] = BUILD_POLICY(U64),
 };
 
-DEFINE_TYPE_SYSTEM(genl_macsec_rxsc);
+DEFINE_POLICY_SET(genl_macsec_rxsc);
 
-static const NLType genl_macsec_sa_types[] = {
-        [MACSEC_SA_ATTR_AN]     = { .type = NETLINK_TYPE_U8 },
-        [MACSEC_SA_ATTR_ACTIVE] = { .type = NETLINK_TYPE_U8 },
-        [MACSEC_SA_ATTR_PN]     = { .type = NETLINK_TYPE_U32 },
-        [MACSEC_SA_ATTR_KEYID]  = { .type = NETLINK_TYPE_BINARY, .size = MACSEC_KEYID_LEN },
-        [MACSEC_SA_ATTR_KEY]    = { .type = NETLINK_TYPE_BINARY, .size = MACSEC_MAX_KEY_LEN },
+static const NLAPolicy genl_macsec_sa_policies[] = {
+        [MACSEC_SA_ATTR_AN]     = BUILD_POLICY(U8),
+        [MACSEC_SA_ATTR_ACTIVE] = BUILD_POLICY(U8),
+        [MACSEC_SA_ATTR_PN]     = BUILD_POLICY(U32),
+        [MACSEC_SA_ATTR_KEYID]  = BUILD_POLICY_WITH_SIZE(BINARY, MACSEC_KEYID_LEN),
+        [MACSEC_SA_ATTR_KEY]    = BUILD_POLICY_WITH_SIZE(BINARY, MACSEC_MAX_KEY_LEN),
 };
 
-DEFINE_TYPE_SYSTEM(genl_macsec_sa);
+DEFINE_POLICY_SET(genl_macsec_sa);
 
-static const NLType genl_macsec_types[] = {
-        [MACSEC_ATTR_IFINDEX]     = { .type = NETLINK_TYPE_U32 },
-        [MACSEC_ATTR_RXSC_CONFIG] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_rxsc_type_system },
-        [MACSEC_ATTR_SA_CONFIG]   = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_sa_type_system },
+static const NLAPolicy genl_macsec_policies[] = {
+        [MACSEC_ATTR_IFINDEX]     = BUILD_POLICY(U32),
+        [MACSEC_ATTR_RXSC_CONFIG] = BUILD_POLICY_NESTED(genl_macsec_rxsc),
+        [MACSEC_ATTR_SA_CONFIG]   = BUILD_POLICY_NESTED(genl_macsec_sa),
 };
 
 /***************** genl nl80211 type systems *****************/
-static const NLType genl_nl80211_types[] = {
-        [NL80211_ATTR_WIPHY]       = { .type = NETLINK_TYPE_U32 },
-        [NL80211_ATTR_WIPHY_NAME]  = { .type = NETLINK_TYPE_STRING },
-        [NL80211_ATTR_IFINDEX]     = { .type = NETLINK_TYPE_U32 },
-        [NL80211_ATTR_IFNAME]      = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ-1 },
-        [NL80211_ATTR_IFTYPE]      = { .type = NETLINK_TYPE_U32 },
-        [NL80211_ATTR_MAC]         = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [NL80211_ATTR_SSID]        = { .type = NETLINK_TYPE_BINARY, .size = IEEE80211_MAX_SSID_LEN },
-        [NL80211_ATTR_STATUS_CODE] = { .type = NETLINK_TYPE_U16 },
-        [NL80211_ATTR_4ADDR]       = { .type = NETLINK_TYPE_U8 },
+static const NLAPolicy genl_nl80211_policies[] = {
+        [NL80211_ATTR_WIPHY]       = BUILD_POLICY(U32),
+        [NL80211_ATTR_WIPHY_NAME]  = BUILD_POLICY(STRING),
+        [NL80211_ATTR_IFINDEX]     = BUILD_POLICY(U32),
+        [NL80211_ATTR_IFNAME]      = BUILD_POLICY_WITH_SIZE(STRING, IFNAMSIZ-1),
+        [NL80211_ATTR_IFTYPE]      = BUILD_POLICY(U32),
+        [NL80211_ATTR_MAC]         = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [NL80211_ATTR_SSID]        = BUILD_POLICY_WITH_SIZE(BINARY, IEEE80211_MAX_SSID_LEN),
+        [NL80211_ATTR_STATUS_CODE] = BUILD_POLICY(U16),
+        [NL80211_ATTR_4ADDR]       = BUILD_POLICY(U8),
 };
 
 /***************** genl wireguard type systems *****************/
-static const NLType genl_wireguard_allowedip_types[] = {
-        [WGALLOWEDIP_A_FAMILY]    = { .type = NETLINK_TYPE_U16 },
-        [WGALLOWEDIP_A_IPADDR]    = { .type = NETLINK_TYPE_IN_ADDR },
-        [WGALLOWEDIP_A_CIDR_MASK] = { .type = NETLINK_TYPE_U8 },
+static const NLAPolicy genl_wireguard_allowedip_policies[] = {
+        [WGALLOWEDIP_A_FAMILY]    = BUILD_POLICY(U16),
+        [WGALLOWEDIP_A_IPADDR]    = BUILD_POLICY(IN_ADDR),
+        [WGALLOWEDIP_A_CIDR_MASK] = BUILD_POLICY(U8),
 };
 
-DEFINE_TYPE_SYSTEM(genl_wireguard_allowedip);
+DEFINE_POLICY_SET(genl_wireguard_allowedip);
 
-static const NLType genl_wireguard_peer_types[] = {
-        [WGPEER_A_PUBLIC_KEY]                    = { .type = NETLINK_TYPE_BINARY, .size = WG_KEY_LEN },
-        [WGPEER_A_FLAGS]                         = { .type = NETLINK_TYPE_U32 },
-        [WGPEER_A_PRESHARED_KEY]                 = { .type = NETLINK_TYPE_BINARY, .size = WG_KEY_LEN },
-        [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NETLINK_TYPE_U16 },
-        [WGPEER_A_ENDPOINT]                      = { .type = NETLINK_TYPE_SOCKADDR },
-        [WGPEER_A_ALLOWEDIPS]                    = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_allowedip_type_system },
+static const NLAPolicy genl_wireguard_peer_policies[] = {
+        [WGPEER_A_PUBLIC_KEY]                    = BUILD_POLICY_WITH_SIZE(BINARY, WG_KEY_LEN),
+        [WGPEER_A_FLAGS]                         = BUILD_POLICY(U32),
+        [WGPEER_A_PRESHARED_KEY]                 = BUILD_POLICY_WITH_SIZE(BINARY, WG_KEY_LEN),
+        [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = BUILD_POLICY(U16),
+        [WGPEER_A_ENDPOINT]                      = BUILD_POLICY(SOCKADDR),
+        [WGPEER_A_ALLOWEDIPS]                    = BUILD_POLICY_NESTED(genl_wireguard_allowedip),
 };
 
-DEFINE_TYPE_SYSTEM(genl_wireguard_peer);
+DEFINE_POLICY_SET(genl_wireguard_peer);
 
-static const NLType genl_wireguard_types[] = {
-        [WGDEVICE_A_IFINDEX]     = { .type = NETLINK_TYPE_U32 },
-        [WGDEVICE_A_IFNAME]      = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ-1 },
-        [WGDEVICE_A_FLAGS]       = { .type = NETLINK_TYPE_U32 },
-        [WGDEVICE_A_PRIVATE_KEY] = { .type = NETLINK_TYPE_BINARY, .size = WG_KEY_LEN },
-        [WGDEVICE_A_LISTEN_PORT] = { .type = NETLINK_TYPE_U16 },
-        [WGDEVICE_A_FWMARK]      = { .type = NETLINK_TYPE_U32 },
-        [WGDEVICE_A_PEERS]       = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_peer_type_system },
+static const NLAPolicy genl_wireguard_policies[] = {
+        [WGDEVICE_A_IFINDEX]     = BUILD_POLICY(U32),
+        [WGDEVICE_A_IFNAME]      = BUILD_POLICY_WITH_SIZE(STRING, IFNAMSIZ-1),
+        [WGDEVICE_A_FLAGS]       = BUILD_POLICY(U32),
+        [WGDEVICE_A_PRIVATE_KEY] = BUILD_POLICY_WITH_SIZE(BINARY, WG_KEY_LEN),
+        [WGDEVICE_A_LISTEN_PORT] = BUILD_POLICY(U16),
+        [WGDEVICE_A_FWMARK]      = BUILD_POLICY(U32),
+        [WGDEVICE_A_PEERS]       = BUILD_POLICY_NESTED(genl_wireguard_peer),
 };
 
 /***************** genl families *****************/
-static const NLTypeSystemUnionElement genl_type_systems[] = {
-        { .name = CTRL_GENL_NAME,    .type_system = TYPE_SYSTEM_FROM_TYPE(genl_ctrl),      },
-        { .name = BATADV_NL_NAME,    .type_system = TYPE_SYSTEM_FROM_TYPE(genl_batadv),    },
-        { .name = FOU_GENL_NAME,     .type_system = TYPE_SYSTEM_FROM_TYPE(genl_fou),       },
-        { .name = L2TP_GENL_NAME,    .type_system = TYPE_SYSTEM_FROM_TYPE(genl_l2tp),      },
-        { .name = MACSEC_GENL_NAME,  .type_system = TYPE_SYSTEM_FROM_TYPE(genl_macsec),    },
-        { .name = NL80211_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_nl80211),   },
-        { .name = WG_GENL_NAME,      .type_system = TYPE_SYSTEM_FROM_TYPE(genl_wireguard), },
+static const NLAPolicySetUnionElement genl_policy_set_union_elements[] = {
+        BUILD_UNION_ELEMENT_BY_STRING(CTRL_GENL_NAME,    genl_ctrl),
+        BUILD_UNION_ELEMENT_BY_STRING(BATADV_NL_NAME,    genl_batadv),
+        BUILD_UNION_ELEMENT_BY_STRING(FOU_GENL_NAME,     genl_fou),
+        BUILD_UNION_ELEMENT_BY_STRING(L2TP_GENL_NAME,    genl_l2tp),
+        BUILD_UNION_ELEMENT_BY_STRING(MACSEC_GENL_NAME,  genl_macsec),
+        BUILD_UNION_ELEMENT_BY_STRING(NL80211_GENL_NAME, genl_nl80211),
+        BUILD_UNION_ELEMENT_BY_STRING(WG_GENL_NAME,      genl_wireguard),
 };
 
 /* This is the root type system union, so match_attribute is not necessary. */
-DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(genl, 0);
+DEFINE_POLICY_SET_UNION(genl, 0);
 
-const NLTypeSystem *genl_get_type_system_by_name(const char *name) {
-        return type_system_union_get_type_system_by_string(&genl_type_system_union, name);
+const NLAPolicySet *genl_get_policy_set_by_name(const char *name) {
+        return policy_set_union_get_policy_set_by_string(&genl_policy_set_union, name);
 }
index 16da6aad0e6776d50f7548598c4ddc212db7302d..1412514f9ba77362e17d021dd417ef72ec929e7a 100644 (file)
@@ -4,46 +4,63 @@
 #include "macro.h"
 #include "netlink-types.h"
 
-struct NLType {
-        uint16_t type;
+/* C.f. see 'struct nla_policy' at include/net/netlink.h. */
+struct NLAPolicy {
+        NLAType type;
         size_t size;
-        const NLTypeSystem *type_system;
-        const NLTypeSystemUnion *type_system_union;
+        union {
+                const NLAPolicySet *policy_set;
+                const NLAPolicySetUnion *policy_set_union;
+        };
 };
 
-struct NLTypeSystem {
+struct NLAPolicySet {
         uint16_t count;
-        const NLType *types;
+        const NLAPolicy *policies;
 };
 
-typedef struct NLTypeSystemUnionElement {
+typedef struct NLAPolicySetUnionElement {
         union {
-                int protocol;
-                const char *name;
+                int family;          /* used by NETLINK_TYPE_NESTED_UNION_BY_FAMILY */
+                const char *string;  /* used by NETLINK_TYPE_NESTED_UNION_BY_STRING */
         };
-        NLTypeSystem type_system;
-} NLTypeSystemUnionElement;
+        NLAPolicySet policy_set;
+} NLAPolicySetUnionElement;
 
-struct NLTypeSystemUnion {
+struct NLAPolicySetUnion {
         size_t count;
-        const NLTypeSystemUnionElement *elements;
-        NLMatchType match_type;
-        uint16_t match_attribute;
+        const NLAPolicySetUnionElement *elements;
+        uint16_t match_attribute; /* used by NETLINK_TYPE_NESTED_UNION_BY_STRING */
 };
 
-#define TYPE_SYSTEM_FROM_TYPE(name)                                     \
-        { .count = ELEMENTSOF(name##_types), .types = name##_types }
-#define DEFINE_TYPE_SYSTEM(name)                                        \
-        static const NLTypeSystem name##_type_system = TYPE_SYSTEM_FROM_TYPE(name)
+#define BUILD_POLICY_WITH_SIZE(t, n)            \
+        { .type = NETLINK_TYPE_##t, .size = n }
+#define BUILD_POLICY(t)                         \
+        BUILD_POLICY_WITH_SIZE(t, 0)
+#define BUILD_POLICY_NESTED_WITH_SIZE(name, n)                          \
+        { .type = NETLINK_TYPE_NESTED, .size = n, .policy_set = &name##_policy_set }
+#define BUILD_POLICY_NESTED(name)               \
+        BUILD_POLICY_NESTED_WITH_SIZE(name, 0)
+#define _BUILD_POLICY_NESTED_UNION(name, by)                            \
+        { .type = NETLINK_TYPE_NESTED_UNION_BY_##by, .policy_set_union = &name##_policy_set_union }
+#define BUILD_POLICY_NESTED_UNION_BY_STRING(name)       \
+        _BUILD_POLICY_NESTED_UNION(name, STRING)
+#define BUILD_POLICY_NESTED_UNION_BY_FAMILY(name)       \
+        _BUILD_POLICY_NESTED_UNION(name, FAMILY)
+
+#define _BUILD_POLICY_SET(name)                                         \
+        { .count = ELEMENTSOF(name##_policies), .policies = name##_policies }
+#define DEFINE_POLICY_SET(name)                                         \
+        static const NLAPolicySet name##_policy_set = _BUILD_POLICY_SET(name)
+
+# define BUILD_UNION_ELEMENT_BY_STRING(s, name)                 \
+        { .string = s, .policy_set = _BUILD_POLICY_SET(name) }
+# define BUILD_UNION_ELEMENT_BY_FAMILY(f, name)                 \
+        { .family = f, .policy_set = _BUILD_POLICY_SET(name) }
 
-#define _DEFINE_TYPE_SYSTEM_UNION(name, type, attr)                     \
-        static const NLTypeSystemUnion name##_type_system_union = {     \
-                .count = ELEMENTSOF(name##_type_systems),               \
-                .elements = name##_type_systems,                        \
-                .match_type = type,                                     \
+#define DEFINE_POLICY_SET_UNION(name, attr)                             \
+        static const NLAPolicySetUnion name##_policy_set_union = {      \
+                .count = ELEMENTSOF(name##_policy_set_union_elements),  \
+                .elements = name##_policy_set_union_elements,           \
                 .match_attribute = attr,                                \
         }
-#define DEFINE_TYPE_SYSTEM_UNION_MATCH_PROTOCOL(name)           \
-        _DEFINE_TYPE_SYSTEM_UNION(name, NL_MATCH_PROTOCOL, 0)
-#define DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(name, attr)      \
-        _DEFINE_TYPE_SYSTEM_UNION(name, NL_MATCH_SIBLING, attr)
index 1ba134a976a6dbd156feae8f22ac290cbfd9b283..8ef4d45d42680859dadc816682307a3d8bc602c9 100644 (file)
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#include <netinet/in.h>
-#include <sys/socket.h>
 #include <linux/if.h>
 #include <linux/netfilter/nf_tables.h>
 #include <linux/netfilter/nfnetlink.h>
 
 #include "netlink-types-internal.h"
-#include "string-table.h"
 
-static const NLType nfnl_nft_table_types[] = {
-        [NFTA_TABLE_NAME]  = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
-        [NFTA_TABLE_FLAGS] = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy nfnl_nft_table_policies[] = {
+        [NFTA_TABLE_NAME]  = BUILD_POLICY_WITH_SIZE(STRING, NFT_TABLE_MAXNAMELEN - 1),
+        [NFTA_TABLE_FLAGS] = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_nft_table);
+DEFINE_POLICY_SET(nfnl_nft_table);
 
-static const NLType nfnl_nft_chain_hook_types[] = {
-        [NFTA_HOOK_HOOKNUM]  = { .type = NETLINK_TYPE_U32 },
-        [NFTA_HOOK_PRIORITY] = { .type = NETLINK_TYPE_U32 },
-        [NFTA_HOOK_DEV]      = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
+static const NLAPolicy nfnl_nft_chain_hook_policies[] = {
+        [NFTA_HOOK_HOOKNUM]  = BUILD_POLICY(U32),
+        [NFTA_HOOK_PRIORITY] = BUILD_POLICY(U32),
+        [NFTA_HOOK_DEV]      = BUILD_POLICY_WITH_SIZE(STRING, IFNAMSIZ - 1),
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_nft_chain_hook);
+DEFINE_POLICY_SET(nfnl_nft_chain_hook);
 
-static const NLType nfnl_nft_chain_types[] = {
-        [NFTA_CHAIN_TABLE] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
-        [NFTA_CHAIN_NAME]  = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
-        [NFTA_CHAIN_HOOK]  = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_chain_hook_type_system },
-        [NFTA_CHAIN_TYPE]  = { .type = NETLINK_TYPE_STRING, .size = 16 },
-        [NFTA_CHAIN_FLAGS] = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy nfnl_nft_chain_policies[] = {
+        [NFTA_CHAIN_TABLE] = BUILD_POLICY_WITH_SIZE(STRING, NFT_TABLE_MAXNAMELEN - 1),
+        [NFTA_CHAIN_NAME]  = BUILD_POLICY_WITH_SIZE(STRING, NFT_TABLE_MAXNAMELEN - 1),
+        [NFTA_CHAIN_HOOK]  = BUILD_POLICY_NESTED(nfnl_nft_chain_hook),
+        [NFTA_CHAIN_TYPE]  = BUILD_POLICY_WITH_SIZE(STRING, 16),
+        [NFTA_CHAIN_FLAGS] = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_nft_chain);
+DEFINE_POLICY_SET(nfnl_nft_chain);
 
-static const NLType nfnl_nft_expr_meta_types[] = {
-        [NFTA_META_DREG] = { .type = NETLINK_TYPE_U32 },
-        [NFTA_META_KEY]  = { .type = NETLINK_TYPE_U32 },
-        [NFTA_META_SREG] = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy nfnl_nft_expr_meta_policies[] = {
+        [NFTA_META_DREG] = BUILD_POLICY(U32),
+        [NFTA_META_KEY]  = BUILD_POLICY(U32),
+        [NFTA_META_SREG] = BUILD_POLICY(U32),
 };
 
-static const NLType nfnl_nft_expr_payload_types[] = {
-        [NFTA_PAYLOAD_DREG]   = { .type = NETLINK_TYPE_U32 },
-        [NFTA_PAYLOAD_BASE]   = { .type = NETLINK_TYPE_U32 },
-        [NFTA_PAYLOAD_OFFSET] = { .type = NETLINK_TYPE_U32 },
-        [NFTA_PAYLOAD_LEN]    = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy nfnl_nft_expr_payload_policies[] = {
+        [NFTA_PAYLOAD_DREG]   = BUILD_POLICY(U32),
+        [NFTA_PAYLOAD_BASE]   = BUILD_POLICY(U32),
+        [NFTA_PAYLOAD_OFFSET] = BUILD_POLICY(U32),
+        [NFTA_PAYLOAD_LEN]    = BUILD_POLICY(U32),
 };
 
-static const NLType nfnl_nft_expr_nat_types[] = {
-        [NFTA_NAT_TYPE]          = { .type = NETLINK_TYPE_U32 },
-        [NFTA_NAT_FAMILY]        = { .type = NETLINK_TYPE_U32 },
-        [NFTA_NAT_REG_ADDR_MIN]  = { .type = NETLINK_TYPE_U32 },
-        [NFTA_NAT_REG_ADDR_MAX]  = { .type = NETLINK_TYPE_U32 },
-        [NFTA_NAT_REG_PROTO_MIN] = { .type = NETLINK_TYPE_U32 },
-        [NFTA_NAT_REG_PROTO_MAX] = { .type = NETLINK_TYPE_U32 },
-        [NFTA_NAT_FLAGS]         = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy nfnl_nft_expr_nat_policies[] = {
+        [NFTA_NAT_TYPE]          = BUILD_POLICY(U32),
+        [NFTA_NAT_FAMILY]        = BUILD_POLICY(U32),
+        [NFTA_NAT_REG_ADDR_MIN]  = BUILD_POLICY(U32),
+        [NFTA_NAT_REG_ADDR_MAX]  = BUILD_POLICY(U32),
+        [NFTA_NAT_REG_PROTO_MIN] = BUILD_POLICY(U32),
+        [NFTA_NAT_REG_PROTO_MAX] = BUILD_POLICY(U32),
+        [NFTA_NAT_FLAGS]         = BUILD_POLICY(U32),
 };
 
-static const NLType nfnl_nft_data_types[] = {
+static const NLAPolicy nfnl_nft_data_policies[] = {
         [NFTA_DATA_VALUE] = { .type = NETLINK_TYPE_BINARY },
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_nft_data);
+DEFINE_POLICY_SET(nfnl_nft_data);
 
-static const NLType nfnl_nft_expr_bitwise_types[] = {
-        [NFTA_BITWISE_SREG] = { .type = NETLINK_TYPE_U32 },
-        [NFTA_BITWISE_DREG] = { .type = NETLINK_TYPE_U32 },
-        [NFTA_BITWISE_LEN]  = { .type = NETLINK_TYPE_U32 },
-        [NFTA_BITWISE_MASK] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
-        [NFTA_BITWISE_XOR]  = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
+static const NLAPolicy nfnl_nft_expr_bitwise_policies[] = {
+        [NFTA_BITWISE_SREG] = BUILD_POLICY(U32),
+        [NFTA_BITWISE_DREG] = BUILD_POLICY(U32),
+        [NFTA_BITWISE_LEN]  = BUILD_POLICY(U32),
+        [NFTA_BITWISE_MASK] = BUILD_POLICY_NESTED(nfnl_nft_data),
+        [NFTA_BITWISE_XOR]  = BUILD_POLICY_NESTED(nfnl_nft_data),
 };
 
-static const NLType nfnl_nft_expr_cmp_types[] = {
-        [NFTA_CMP_SREG] = { .type = NETLINK_TYPE_U32 },
-        [NFTA_CMP_OP]   = { .type = NETLINK_TYPE_U32 },
-        [NFTA_CMP_DATA] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
+static const NLAPolicy nfnl_nft_expr_cmp_policies[] = {
+        [NFTA_CMP_SREG] = BUILD_POLICY(U32),
+        [NFTA_CMP_OP]   = BUILD_POLICY(U32),
+        [NFTA_CMP_DATA] = BUILD_POLICY_NESTED(nfnl_nft_data),
 };
 
-static const NLType nfnl_nft_expr_fib_types[] = {
-        [NFTA_FIB_DREG]   = { .type = NETLINK_TYPE_U32 },
-        [NFTA_FIB_RESULT] = { .type = NETLINK_TYPE_U32 },
-        [NFTA_FIB_FLAGS]  = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy nfnl_nft_expr_fib_policies[] = {
+        [NFTA_FIB_DREG]   = BUILD_POLICY(U32),
+        [NFTA_FIB_RESULT] = BUILD_POLICY(U32),
+        [NFTA_FIB_FLAGS]  = BUILD_POLICY(U32),
 };
 
-static const NLType nfnl_nft_expr_lookup_types[] = {
+static const NLAPolicy nfnl_nft_expr_lookup_policies[] = {
         [NFTA_LOOKUP_SET]   = { .type = NETLINK_TYPE_STRING },
-        [NFTA_LOOKUP_SREG]  = { .type = NETLINK_TYPE_U32 },
-        [NFTA_LOOKUP_DREG]  = { .type = NETLINK_TYPE_U32 },
-        [NFTA_LOOKUP_FLAGS] = { .type = NETLINK_TYPE_U32 },
+        [NFTA_LOOKUP_SREG]  = BUILD_POLICY(U32),
+        [NFTA_LOOKUP_DREG]  = BUILD_POLICY(U32),
+        [NFTA_LOOKUP_FLAGS] = BUILD_POLICY(U32),
 };
 
-static const NLType nfnl_nft_expr_masq_types[] = {
-        [NFTA_MASQ_FLAGS]         = { .type = NETLINK_TYPE_U32 },
-        [NFTA_MASQ_REG_PROTO_MIN] = { .type = NETLINK_TYPE_U32 },
-        [NFTA_MASQ_REG_PROTO_MAX] = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy nfnl_nft_expr_masq_policies[] = {
+        [NFTA_MASQ_FLAGS]         = BUILD_POLICY(U32),
+        [NFTA_MASQ_REG_PROTO_MIN] = BUILD_POLICY(U32),
+        [NFTA_MASQ_REG_PROTO_MAX] = BUILD_POLICY(U32),
 };
 
-static const NLTypeSystemUnionElement nfnl_expr_data_type_systems[] = {
-        { .name = "bitwise", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_bitwise), },
-        { .name = "cmp",     .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_cmp),     },
-        { .name = "fib",     .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_fib),     },
-        { .name = "lookup",  .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_lookup),  },
-        { .name = "masq",    .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_masq),    },
-        { .name = "meta",    .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_meta),    },
-        { .name = "nat",     .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_nat),     },
-        { .name = "payload", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_payload), },
+static const NLAPolicySetUnionElement nfnl_expr_data_policy_set_union_elements[] = {
+        BUILD_UNION_ELEMENT_BY_STRING("bitwise", nfnl_nft_expr_bitwise),
+        BUILD_UNION_ELEMENT_BY_STRING("cmp",     nfnl_nft_expr_cmp),
+        BUILD_UNION_ELEMENT_BY_STRING("fib",     nfnl_nft_expr_fib),
+        BUILD_UNION_ELEMENT_BY_STRING("lookup",  nfnl_nft_expr_lookup),
+        BUILD_UNION_ELEMENT_BY_STRING("masq",    nfnl_nft_expr_masq),
+        BUILD_UNION_ELEMENT_BY_STRING("meta",    nfnl_nft_expr_meta),
+        BUILD_UNION_ELEMENT_BY_STRING("nat",     nfnl_nft_expr_nat),
+        BUILD_UNION_ELEMENT_BY_STRING("payload", nfnl_nft_expr_payload),
 };
 
-DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(nfnl_expr_data, NFTA_EXPR_NAME);
+DEFINE_POLICY_SET_UNION(nfnl_expr_data, NFTA_EXPR_NAME);
 
-static const NLType nfnl_nft_rule_expr_types[] = {
-        [NFTA_EXPR_NAME] = { .type = NETLINK_TYPE_STRING, .size = 16 },
-        [NFTA_EXPR_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &nfnl_expr_data_type_system_union },
+static const NLAPolicy nfnl_nft_rule_expr_policies[] = {
+        [NFTA_EXPR_NAME] = BUILD_POLICY_WITH_SIZE(STRING, 16),
+        [NFTA_EXPR_DATA] = BUILD_POLICY_NESTED_UNION_BY_STRING(nfnl_expr_data),
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_nft_rule_expr);
+DEFINE_POLICY_SET(nfnl_nft_rule_expr);
 
-static const NLType nfnl_nft_rule_types[] = {
-        [NFTA_RULE_TABLE]       = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
-        [NFTA_RULE_CHAIN]       = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
-        [NFTA_RULE_EXPRESSIONS] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_rule_expr_type_system }
+static const NLAPolicy nfnl_nft_rule_policies[] = {
+        [NFTA_RULE_TABLE]       = BUILD_POLICY_WITH_SIZE(STRING, NFT_TABLE_MAXNAMELEN - 1),
+        [NFTA_RULE_CHAIN]       = BUILD_POLICY_WITH_SIZE(STRING, NFT_TABLE_MAXNAMELEN - 1),
+        [NFTA_RULE_EXPRESSIONS] = BUILD_POLICY_NESTED(nfnl_nft_rule_expr),
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_nft_rule);
+DEFINE_POLICY_SET(nfnl_nft_rule);
 
-static const NLType nfnl_nft_set_types[] = {
-        [NFTA_SET_TABLE]      = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
-        [NFTA_SET_NAME]       = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
-        [NFTA_SET_FLAGS]      = { .type = NETLINK_TYPE_U32 },
-        [NFTA_SET_KEY_TYPE]   = { .type = NETLINK_TYPE_U32 },
-        [NFTA_SET_KEY_LEN]    = { .type = NETLINK_TYPE_U32 },
-        [NFTA_SET_DATA_TYPE]  = { .type = NETLINK_TYPE_U32 },
-        [NFTA_SET_DATA_LEN]   = { .type = NETLINK_TYPE_U32 },
-        [NFTA_SET_POLICY]     = { .type = NETLINK_TYPE_U32 },
-        [NFTA_SET_ID]         = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy nfnl_nft_set_policies[] = {
+        [NFTA_SET_TABLE]      = BUILD_POLICY_WITH_SIZE(STRING, NFT_TABLE_MAXNAMELEN - 1),
+        [NFTA_SET_NAME]       = BUILD_POLICY_WITH_SIZE(STRING, NFT_TABLE_MAXNAMELEN - 1),
+        [NFTA_SET_FLAGS]      = BUILD_POLICY(U32),
+        [NFTA_SET_KEY_TYPE]   = BUILD_POLICY(U32),
+        [NFTA_SET_KEY_LEN]    = BUILD_POLICY(U32),
+        [NFTA_SET_DATA_TYPE]  = BUILD_POLICY(U32),
+        [NFTA_SET_DATA_LEN]   = BUILD_POLICY(U32),
+        [NFTA_SET_POLICY]     = BUILD_POLICY(U32),
+        [NFTA_SET_ID]         = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_nft_set);
+DEFINE_POLICY_SET(nfnl_nft_set);
 
-static const NLType nfnl_nft_setelem_types[] = {
-        [NFTA_SET_ELEM_KEY]   = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
-        [NFTA_SET_ELEM_DATA]  = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
-        [NFTA_SET_ELEM_FLAGS] = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy nfnl_nft_setelem_policies[] = {
+        [NFTA_SET_ELEM_KEY]   = BUILD_POLICY_NESTED(nfnl_nft_data),
+        [NFTA_SET_ELEM_DATA]  = BUILD_POLICY_NESTED(nfnl_nft_data),
+        [NFTA_SET_ELEM_FLAGS] = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_nft_setelem);
+DEFINE_POLICY_SET(nfnl_nft_setelem);
 
-static const NLType nfnl_nft_setelem_list_types[] = {
-        [NFTA_SET_ELEM_LIST_TABLE]    = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
-        [NFTA_SET_ELEM_LIST_SET]      = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
-        [NFTA_SET_ELEM_LIST_ELEMENTS] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_type_system },
+static const NLAPolicy nfnl_nft_setelem_list_policies[] = {
+        [NFTA_SET_ELEM_LIST_TABLE]    = BUILD_POLICY_WITH_SIZE(STRING, NFT_TABLE_MAXNAMELEN - 1),
+        [NFTA_SET_ELEM_LIST_SET]      = BUILD_POLICY_WITH_SIZE(STRING, NFT_TABLE_MAXNAMELEN - 1),
+        [NFTA_SET_ELEM_LIST_ELEMENTS] = BUILD_POLICY_NESTED(nfnl_nft_setelem),
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_nft_setelem_list);
+DEFINE_POLICY_SET(nfnl_nft_setelem_list);
 
-static const NLType nfnl_subsys_nft_types [] = {
-        [NFT_MSG_DELTABLE]   = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_table_type_system,        .size = sizeof(struct nfgenmsg) },
-        [NFT_MSG_NEWTABLE]   = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_table_type_system,        .size = sizeof(struct nfgenmsg) },
-        [NFT_MSG_NEWCHAIN]   = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_chain_type_system,        .size = sizeof(struct nfgenmsg) },
-        [NFT_MSG_NEWRULE]    = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_rule_type_system,         .size = sizeof(struct nfgenmsg) },
-        [NFT_MSG_NEWSET]     = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_set_type_system,          .size = sizeof(struct nfgenmsg) },
-        [NFT_MSG_NEWSETELEM] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_list_type_system, .size = sizeof(struct nfgenmsg) },
-        [NFT_MSG_DELSETELEM] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_list_type_system, .size = sizeof(struct nfgenmsg) },
+static const NLAPolicy nfnl_subsys_nft_policies[] = {
+        [NFT_MSG_DELTABLE]   = BUILD_POLICY_NESTED_WITH_SIZE(nfnl_nft_table,        sizeof(struct nfgenmsg)),
+        [NFT_MSG_NEWTABLE]   = BUILD_POLICY_NESTED_WITH_SIZE(nfnl_nft_table,        sizeof(struct nfgenmsg)),
+        [NFT_MSG_NEWCHAIN]   = BUILD_POLICY_NESTED_WITH_SIZE(nfnl_nft_chain,        sizeof(struct nfgenmsg)),
+        [NFT_MSG_NEWRULE]    = BUILD_POLICY_NESTED_WITH_SIZE(nfnl_nft_rule,         sizeof(struct nfgenmsg)),
+        [NFT_MSG_NEWSET]     = BUILD_POLICY_NESTED_WITH_SIZE(nfnl_nft_set,          sizeof(struct nfgenmsg)),
+        [NFT_MSG_NEWSETELEM] = BUILD_POLICY_NESTED_WITH_SIZE(nfnl_nft_setelem_list, sizeof(struct nfgenmsg)),
+        [NFT_MSG_DELSETELEM] = BUILD_POLICY_NESTED_WITH_SIZE(nfnl_nft_setelem_list, sizeof(struct nfgenmsg)),
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_subsys_nft);
+DEFINE_POLICY_SET(nfnl_subsys_nft);
 
-static const NLType nfnl_msg_batch_types [] = {
-        [NFNL_BATCH_GENID] = { .type = NETLINK_TYPE_U32 }
+static const NLAPolicy nfnl_msg_batch_policies[] = {
+        [NFNL_BATCH_GENID] = BUILD_POLICY(U32)
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_msg_batch);
+DEFINE_POLICY_SET(nfnl_msg_batch);
 
-static const NLType nfnl_subsys_none_types[] = {
-        [NFNL_MSG_BATCH_BEGIN] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_msg_batch_type_system, .size = sizeof(struct nfgenmsg) },
-        [NFNL_MSG_BATCH_END]   = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_msg_batch_type_system, .size = sizeof(struct nfgenmsg) },
+static const NLAPolicy nfnl_subsys_none_policies[] = {
+        [NFNL_MSG_BATCH_BEGIN] = BUILD_POLICY_NESTED_WITH_SIZE(nfnl_msg_batch, sizeof(struct nfgenmsg)),
+        [NFNL_MSG_BATCH_END]   = BUILD_POLICY_NESTED_WITH_SIZE(nfnl_msg_batch, sizeof(struct nfgenmsg)),
 };
 
-DEFINE_TYPE_SYSTEM(nfnl_subsys_none);
+DEFINE_POLICY_SET(nfnl_subsys_none);
 
-static const NLType nfnl_types[] = {
-        [NFNL_SUBSYS_NONE]     = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_subsys_none_type_system },
-        [NFNL_SUBSYS_NFTABLES] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_subsys_nft_type_system },
+static const NLAPolicy nfnl_policies[] = {
+        [NFNL_SUBSYS_NONE]     = BUILD_POLICY_NESTED(nfnl_subsys_none),
+        [NFNL_SUBSYS_NFTABLES] = BUILD_POLICY_NESTED(nfnl_subsys_nft),
 };
 
-DEFINE_TYPE_SYSTEM(nfnl);
+DEFINE_POLICY_SET(nfnl);
 
-const NLType *nfnl_get_type(uint16_t nlmsg_type) {
-        const NLTypeSystem *subsys;
+const NLAPolicy *nfnl_get_policy(uint16_t nlmsg_type) {
+        const NLAPolicySet *subsys;
 
-        subsys = type_system_get_type_system(&nfnl_type_system, nlmsg_type >> 8);
+        subsys = policy_set_get_policy_set(&nfnl_policy_set, NFNL_SUBSYS_ID(nlmsg_type));
         if (!subsys)
                 return NULL;
 
-        return type_system_get_type(subsys, nlmsg_type & ((1U << 8) - 1));
+        return policy_set_get_policy(subsys, NFNL_MSG_TYPE(nlmsg_type));
 }
index c98be6da54bc5f2aad691b36c4c121bdcd65a248..be6f7cf791766e2474144964fbea0c65861aa656 100644 (file)
 #include <linux/veth.h>
 #include <linux/wireguard.h>
 
-#include "sd-netlink.h"
-
 #include "missing_network.h"
 #include "netlink-types-internal.h"
-#include "string-table.h"
 
 enum {
         BOND_ARP_TARGETS_0,
@@ -53,1180 +50,1179 @@ enum {
 
 assert_cc(_BOND_ARP_TARGETS_MAX == BOND_MAX_ARP_TARGETS);
 
-static const NLTypeSystem rtnl_link_type_system;
-
-static const NLType rtnl_link_info_data_bareudp_types[] = {
-        [IFLA_BAREUDP_PORT]            = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BAREUDP_ETHERTYPE]       = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BAREUDP_SRCPORT_MIN]     = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BAREUDP_MULTIPROTO_MODE] = { .type = NETLINK_TYPE_FLAG },
-};
-
-static const NLType rtnl_link_info_data_batadv_types[] = {
-        [IFLA_BATADV_ALGO_NAME] = { .type = NETLINK_TYPE_STRING, .size = 20 },
-};
-
-static const NLType rtnl_bond_arp_ip_target_types[] = {
-        [BOND_ARP_TARGETS_0]        = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_1]        = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_2]        = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_3]        = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_4]        = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_5]        = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_6]        = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_7]        = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_8]        = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_9]        = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_10]       = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_11]       = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_12]       = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_13]       = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_14]       = { .type = NETLINK_TYPE_U32 },
-        [BOND_ARP_TARGETS_15]       = { .type = NETLINK_TYPE_U32 },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_bond_arp_ip_target);
-
-static const NLType rtnl_bond_ad_info_types[] = {
-        [IFLA_BOND_AD_INFO_AGGREGATOR]  = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BOND_AD_INFO_NUM_PORTS]   = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BOND_AD_INFO_ACTOR_KEY]   = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BOND_AD_INFO_PARTNER_KEY] = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BOND_AD_INFO_PARTNER_MAC] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_bond_ad_info);
-
-static const NLType rtnl_link_info_data_bond_types[] = {
-        [IFLA_BOND_MODE]                = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BOND_ACTIVE_SLAVE]        = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_MIIMON]              = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_UPDELAY]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_DOWNDELAY]           = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_USE_CARRIER]         = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BOND_ARP_INTERVAL]        = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_ARP_IP_TARGET]       = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bond_arp_ip_target_type_system },
-        [IFLA_BOND_ARP_VALIDATE]        = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_ARP_ALL_TARGETS]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_PRIMARY]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_PRIMARY_RESELECT]    = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BOND_FAIL_OVER_MAC]       = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BOND_XMIT_HASH_POLICY]    = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BOND_RESEND_IGMP]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_NUM_PEER_NOTIF]      = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BOND_ALL_SLAVES_ACTIVE]   = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BOND_MIN_LINKS]           = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_LP_INTERVAL]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_PACKETS_PER_SLAVE]   = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BOND_AD_LACP_RATE]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BOND_AD_SELECT]           = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BOND_AD_INFO]             = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bond_ad_info_type_system },
-        [IFLA_BOND_AD_ACTOR_SYS_PRIO]   = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BOND_AD_USER_PORT_KEY]    = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BOND_AD_ACTOR_SYSTEM]     = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [IFLA_BOND_TLB_DYNAMIC_LB]      = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BOND_PEER_NOTIF_DELAY]    = { .type = NETLINK_TYPE_U32 },
-};
-
-static const NLType rtnl_link_info_data_bridge_types[] = {
-        [IFLA_BR_FORWARD_DELAY]              = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BR_HELLO_TIME]                 = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BR_MAX_AGE]                    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BR_AGEING_TIME]                = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BR_STP_STATE]                  = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BR_PRIORITY]                   = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BR_VLAN_FILTERING]             = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_VLAN_PROTOCOL]              = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BR_GROUP_FWD_MASK]             = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BR_ROOT_ID]                    = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_bridge_id) },
-        [IFLA_BR_BRIDGE_ID]                  = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_bridge_id) },
-        [IFLA_BR_ROOT_PORT]                  = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BR_ROOT_PATH_COST]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BR_TOPOLOGY_CHANGE]            = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_TOPOLOGY_CHANGE_DETECTED]   = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_HELLO_TIMER]                = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BR_TCN_TIMER]                  = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BR_TOPOLOGY_CHANGE_TIMER]      = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BR_GC_TIMER]                   = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BR_GROUP_ADDR]                 = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [IFLA_BR_FDB_FLUSH]                  = { .type = NETLINK_TYPE_FLAG },
-        [IFLA_BR_MCAST_ROUTER]               = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_MCAST_SNOOPING]             = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_MCAST_QUERY_USE_IFADDR]     = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_MCAST_QUERIER]              = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_MCAST_HASH_ELASTICITY]      = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BR_MCAST_HASH_MAX]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BR_MCAST_LAST_MEMBER_CNT]      = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BR_MCAST_STARTUP_QUERY_CNT]    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BR_MCAST_LAST_MEMBER_INTVL]    = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BR_MCAST_MEMBERSHIP_INTVL]     = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BR_MCAST_QUERIER_INTVL]        = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BR_MCAST_QUERY_INTVL]          = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BR_MCAST_STARTUP_QUERY_INTVL]  = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BR_NF_CALL_IPTABLES]           = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_NF_CALL_IP6TABLES]          = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_NF_CALL_ARPTABLES]          = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_VLAN_DEFAULT_PVID]          = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BR_VLAN_STATS_ENABLED]         = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_MCAST_STATS_ENABLED]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_MCAST_IGMP_VERSION]         = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_MCAST_MLD_VERSION]          = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_VLAN_STATS_PER_PORT]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BR_MULTI_BOOLOPT]              = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct br_boolopt_multi) },
-};
-
-static const NLType rtnl_link_info_data_can_types[] = {
-        [IFLA_CAN_BITTIMING]            = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct can_bittiming) },
-        [IFLA_CAN_BITTIMING_CONST]      = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct can_bittiming_const) },
-        [IFLA_CAN_CLOCK]                = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct can_clock) },
-        [IFLA_CAN_STATE]                = { .type = NETLINK_TYPE_U32 },
-        [IFLA_CAN_CTRLMODE]             = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct can_ctrlmode) },
-        [IFLA_CAN_RESTART_MS]           = { .type = NETLINK_TYPE_U32 },
-        [IFLA_CAN_RESTART]              = { .type = NETLINK_TYPE_U32 },
-        [IFLA_CAN_BERR_COUNTER]         = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct can_berr_counter) },
-        [IFLA_CAN_DATA_BITTIMING]       = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct can_bittiming) },
-        [IFLA_CAN_DATA_BITTIMING_CONST] = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct can_bittiming_const) },
-        [IFLA_CAN_TERMINATION]          = { .type = NETLINK_TYPE_U16 },
-        [IFLA_CAN_TERMINATION_CONST]    = { .type = NETLINK_TYPE_BINARY }, /* size = termination_const_cnt * sizeof(u16) */
-        [IFLA_CAN_BITRATE_CONST]        = { .type = NETLINK_TYPE_BINARY }, /* size = bitrate_const_cnt * sizeof(u32) */
-        [IFLA_CAN_DATA_BITRATE_CONST]   = { .type = NETLINK_TYPE_BINARY }, /* size = data_bitrate_const_cnt * sizeof(u32) */
-        [IFLA_CAN_BITRATE_MAX]          = { .type = NETLINK_TYPE_U32 },
-};
-
-static const NLType rtnl_link_info_data_geneve_types[] = {
-        [IFLA_GENEVE_ID]                = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GENEVE_REMOTE]            = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in_addr) },
-        [IFLA_GENEVE_TTL]               = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GENEVE_TOS]               = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GENEVE_PORT]              = { .type = NETLINK_TYPE_U16 },
-        [IFLA_GENEVE_COLLECT_METADATA]  = { .type = NETLINK_TYPE_FLAG },
-        [IFLA_GENEVE_REMOTE6]           = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
-        [IFLA_GENEVE_UDP_CSUM]          = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GENEVE_LABEL]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GENEVE_TTL_INHERIT]       = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GENEVE_DF]                = { .type = NETLINK_TYPE_U8 },
-};
-
-static const NLType rtnl_link_info_data_gre_types[] = {
-        [IFLA_GRE_LINK]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GRE_IFLAGS]           = { .type = NETLINK_TYPE_U16 },
-        [IFLA_GRE_OFLAGS]           = { .type = NETLINK_TYPE_U16 },
-        [IFLA_GRE_IKEY]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GRE_OKEY]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GRE_LOCAL]            = { .type = NETLINK_TYPE_IN_ADDR },
-        [IFLA_GRE_REMOTE]           = { .type = NETLINK_TYPE_IN_ADDR },
-        [IFLA_GRE_TTL]              = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GRE_TOS]              = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GRE_PMTUDISC]         = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GRE_ENCAP_LIMIT]      = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GRE_FLOWINFO]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GRE_FLAGS]            = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GRE_ENCAP_TYPE]       = { .type = NETLINK_TYPE_U16 },
-        [IFLA_GRE_ENCAP_FLAGS]      = { .type = NETLINK_TYPE_U16 },
-        [IFLA_GRE_ENCAP_SPORT]      = { .type = NETLINK_TYPE_U16 },
-        [IFLA_GRE_ENCAP_DPORT]      = { .type = NETLINK_TYPE_U16 },
-        [IFLA_GRE_COLLECT_METADATA] = { .type = NETLINK_TYPE_FLAG },
-        [IFLA_GRE_IGNORE_DF]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GRE_FWMARK]           = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GRE_ERSPAN_INDEX]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GRE_ERSPAN_VER]       = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GRE_ERSPAN_DIR]       = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GRE_ERSPAN_HWID]      = { .type = NETLINK_TYPE_U16 },
-};
-
-static const NLType rtnl_link_info_data_ipoib_types[] = {
-        [IFLA_IPOIB_PKEY]           = { .type = NETLINK_TYPE_U16 },
-        [IFLA_IPOIB_MODE]           = { .type = NETLINK_TYPE_U16 },
-        [IFLA_IPOIB_UMCAST]         = { .type = NETLINK_TYPE_U16 },
+static const NLAPolicySet rtnl_link_policy_set;
+
+static const NLAPolicy rtnl_link_info_data_bareudp_policies[] = {
+        [IFLA_BAREUDP_PORT]            = BUILD_POLICY(U16),
+        [IFLA_BAREUDP_ETHERTYPE]       = BUILD_POLICY(U16),
+        [IFLA_BAREUDP_SRCPORT_MIN]     = BUILD_POLICY(U16),
+        [IFLA_BAREUDP_MULTIPROTO_MODE] = BUILD_POLICY(FLAG),
+};
+
+static const NLAPolicy rtnl_link_info_data_batadv_policies[] = {
+        [IFLA_BATADV_ALGO_NAME] = BUILD_POLICY_WITH_SIZE(STRING, 20),
+};
+
+static const NLAPolicy rtnl_bond_arp_ip_target_policies[] = {
+        [BOND_ARP_TARGETS_0]        = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_1]        = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_2]        = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_3]        = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_4]        = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_5]        = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_6]        = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_7]        = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_8]        = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_9]        = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_10]       = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_11]       = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_12]       = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_13]       = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_14]       = BUILD_POLICY(U32),
+        [BOND_ARP_TARGETS_15]       = BUILD_POLICY(U32),
+};
+
+DEFINE_POLICY_SET(rtnl_bond_arp_ip_target);
+
+static const NLAPolicy rtnl_bond_ad_info_policies[] = {
+        [IFLA_BOND_AD_INFO_AGGREGATOR]  = BUILD_POLICY(U16),
+        [IFLA_BOND_AD_INFO_NUM_PORTS]   = BUILD_POLICY(U16),
+        [IFLA_BOND_AD_INFO_ACTOR_KEY]   = BUILD_POLICY(U16),
+        [IFLA_BOND_AD_INFO_PARTNER_KEY] = BUILD_POLICY(U16),
+        [IFLA_BOND_AD_INFO_PARTNER_MAC] = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+};
+
+DEFINE_POLICY_SET(rtnl_bond_ad_info);
+
+static const NLAPolicy rtnl_link_info_data_bond_policies[] = {
+        [IFLA_BOND_MODE]                = BUILD_POLICY(U8),
+        [IFLA_BOND_ACTIVE_SLAVE]        = BUILD_POLICY(U32),
+        [IFLA_BOND_MIIMON]              = BUILD_POLICY(U32),
+        [IFLA_BOND_UPDELAY]             = BUILD_POLICY(U32),
+        [IFLA_BOND_DOWNDELAY]           = BUILD_POLICY(U32),
+        [IFLA_BOND_USE_CARRIER]         = BUILD_POLICY(U8),
+        [IFLA_BOND_ARP_INTERVAL]        = BUILD_POLICY(U32),
+        [IFLA_BOND_ARP_IP_TARGET]       = BUILD_POLICY_NESTED(rtnl_bond_arp_ip_target),
+        [IFLA_BOND_ARP_VALIDATE]        = BUILD_POLICY(U32),
+        [IFLA_BOND_ARP_ALL_TARGETS]     = BUILD_POLICY(U32),
+        [IFLA_BOND_PRIMARY]             = BUILD_POLICY(U32),
+        [IFLA_BOND_PRIMARY_RESELECT]    = BUILD_POLICY(U8),
+        [IFLA_BOND_FAIL_OVER_MAC]       = BUILD_POLICY(U8),
+        [IFLA_BOND_XMIT_HASH_POLICY]    = BUILD_POLICY(U8),
+        [IFLA_BOND_RESEND_IGMP]         = BUILD_POLICY(U32),
+        [IFLA_BOND_NUM_PEER_NOTIF]      = BUILD_POLICY(U8),
+        [IFLA_BOND_ALL_SLAVES_ACTIVE]   = BUILD_POLICY(U8),
+        [IFLA_BOND_MIN_LINKS]           = BUILD_POLICY(U32),
+        [IFLA_BOND_LP_INTERVAL]         = BUILD_POLICY(U32),
+        [IFLA_BOND_PACKETS_PER_SLAVE]   = BUILD_POLICY(U32),
+        [IFLA_BOND_AD_LACP_RATE]        = BUILD_POLICY(U8),
+        [IFLA_BOND_AD_SELECT]           = BUILD_POLICY(U8),
+        [IFLA_BOND_AD_INFO]             = BUILD_POLICY_NESTED(rtnl_bond_ad_info),
+        [IFLA_BOND_AD_ACTOR_SYS_PRIO]   = BUILD_POLICY(U16),
+        [IFLA_BOND_AD_USER_PORT_KEY]    = BUILD_POLICY(U16),
+        [IFLA_BOND_AD_ACTOR_SYSTEM]     = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [IFLA_BOND_TLB_DYNAMIC_LB]      = BUILD_POLICY(U8),
+        [IFLA_BOND_PEER_NOTIF_DELAY]    = BUILD_POLICY(U32),
+};
+
+static const NLAPolicy rtnl_link_info_data_bridge_policies[] = {
+        [IFLA_BR_FORWARD_DELAY]              = BUILD_POLICY(U32),
+        [IFLA_BR_HELLO_TIME]                 = BUILD_POLICY(U32),
+        [IFLA_BR_MAX_AGE]                    = BUILD_POLICY(U32),
+        [IFLA_BR_AGEING_TIME]                = BUILD_POLICY(U32),
+        [IFLA_BR_STP_STATE]                  = BUILD_POLICY(U32),
+        [IFLA_BR_PRIORITY]                   = BUILD_POLICY(U16),
+        [IFLA_BR_VLAN_FILTERING]             = BUILD_POLICY(U8),
+        [IFLA_BR_VLAN_PROTOCOL]              = BUILD_POLICY(U16),
+        [IFLA_BR_GROUP_FWD_MASK]             = BUILD_POLICY(U16),
+        [IFLA_BR_ROOT_ID]                    = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_bridge_id)),
+        [IFLA_BR_BRIDGE_ID]                  = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_bridge_id)),
+        [IFLA_BR_ROOT_PORT]                  = BUILD_POLICY(U16),
+        [IFLA_BR_ROOT_PATH_COST]             = BUILD_POLICY(U32),
+        [IFLA_BR_TOPOLOGY_CHANGE]            = BUILD_POLICY(U8),
+        [IFLA_BR_TOPOLOGY_CHANGE_DETECTED]   = BUILD_POLICY(U8),
+        [IFLA_BR_HELLO_TIMER]                = BUILD_POLICY(U64),
+        [IFLA_BR_TCN_TIMER]                  = BUILD_POLICY(U64),
+        [IFLA_BR_TOPOLOGY_CHANGE_TIMER]      = BUILD_POLICY(U64),
+        [IFLA_BR_GC_TIMER]                   = BUILD_POLICY(U64),
+        [IFLA_BR_GROUP_ADDR]                 = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [IFLA_BR_FDB_FLUSH]                  = BUILD_POLICY(FLAG),
+        [IFLA_BR_MCAST_ROUTER]               = BUILD_POLICY(U8),
+        [IFLA_BR_MCAST_SNOOPING]             = BUILD_POLICY(U8),
+        [IFLA_BR_MCAST_QUERY_USE_IFADDR]     = BUILD_POLICY(U8),
+        [IFLA_BR_MCAST_QUERIER]              = BUILD_POLICY(U8),
+        [IFLA_BR_MCAST_HASH_ELASTICITY]      = BUILD_POLICY(U32),
+        [IFLA_BR_MCAST_HASH_MAX]             = BUILD_POLICY(U32),
+        [IFLA_BR_MCAST_LAST_MEMBER_CNT]      = BUILD_POLICY(U32),
+        [IFLA_BR_MCAST_STARTUP_QUERY_CNT]    = BUILD_POLICY(U32),
+        [IFLA_BR_MCAST_LAST_MEMBER_INTVL]    = BUILD_POLICY(U64),
+        [IFLA_BR_MCAST_MEMBERSHIP_INTVL]     = BUILD_POLICY(U64),
+        [IFLA_BR_MCAST_QUERIER_INTVL]        = BUILD_POLICY(U64),
+        [IFLA_BR_MCAST_QUERY_INTVL]          = BUILD_POLICY(U64),
+        [IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = BUILD_POLICY(U64),
+        [IFLA_BR_MCAST_STARTUP_QUERY_INTVL]  = BUILD_POLICY(U64),
+        [IFLA_BR_NF_CALL_IPTABLES]           = BUILD_POLICY(U8),
+        [IFLA_BR_NF_CALL_IP6TABLES]          = BUILD_POLICY(U8),
+        [IFLA_BR_NF_CALL_ARPTABLES]          = BUILD_POLICY(U8),
+        [IFLA_BR_VLAN_DEFAULT_PVID]          = BUILD_POLICY(U16),
+        [IFLA_BR_VLAN_STATS_ENABLED]         = BUILD_POLICY(U8),
+        [IFLA_BR_MCAST_STATS_ENABLED]        = BUILD_POLICY(U8),
+        [IFLA_BR_MCAST_IGMP_VERSION]         = BUILD_POLICY(U8),
+        [IFLA_BR_MCAST_MLD_VERSION]          = BUILD_POLICY(U8),
+        [IFLA_BR_VLAN_STATS_PER_PORT]        = BUILD_POLICY(U8),
+        [IFLA_BR_MULTI_BOOLOPT]              = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct br_boolopt_multi)),
+};
+
+static const NLAPolicy rtnl_link_info_data_can_policies[] = {
+        [IFLA_CAN_BITTIMING]            = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct can_bittiming)),
+        [IFLA_CAN_BITTIMING_CONST]      = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct can_bittiming_const)),
+        [IFLA_CAN_CLOCK]                = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct can_clock)),
+        [IFLA_CAN_STATE]                = BUILD_POLICY(U32),
+        [IFLA_CAN_CTRLMODE]             = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct can_ctrlmode)),
+        [IFLA_CAN_RESTART_MS]           = BUILD_POLICY(U32),
+        [IFLA_CAN_RESTART]              = BUILD_POLICY(U32),
+        [IFLA_CAN_BERR_COUNTER]         = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct can_berr_counter)),
+        [IFLA_CAN_DATA_BITTIMING]       = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct can_bittiming)),
+        [IFLA_CAN_DATA_BITTIMING_CONST] = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct can_bittiming_const)),
+        [IFLA_CAN_TERMINATION]          = BUILD_POLICY(U16),
+        [IFLA_CAN_TERMINATION_CONST]    = BUILD_POLICY(BINARY), /* size = termination_const_cnt * sizeof(u16) */
+        [IFLA_CAN_BITRATE_CONST]        = BUILD_POLICY(BINARY), /* size = bitrate_const_cnt * sizeof(u32) */
+        [IFLA_CAN_DATA_BITRATE_CONST]   = BUILD_POLICY(BINARY), /* size = data_bitrate_const_cnt * sizeof(u32) */
+        [IFLA_CAN_BITRATE_MAX]          = BUILD_POLICY(U32),
+};
+
+static const NLAPolicy rtnl_link_info_data_geneve_policies[] = {
+        [IFLA_GENEVE_ID]                = BUILD_POLICY(U32),
+        [IFLA_GENEVE_REMOTE]            = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in_addr)),
+        [IFLA_GENEVE_TTL]               = BUILD_POLICY(U8),
+        [IFLA_GENEVE_TOS]               = BUILD_POLICY(U8),
+        [IFLA_GENEVE_PORT]              = BUILD_POLICY(U16),
+        [IFLA_GENEVE_COLLECT_METADATA]  = BUILD_POLICY(FLAG),
+        [IFLA_GENEVE_REMOTE6]           = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)),
+        [IFLA_GENEVE_UDP_CSUM]          = BUILD_POLICY(U8),
+        [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = BUILD_POLICY(U8),
+        [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = BUILD_POLICY(U8),
+        [IFLA_GENEVE_LABEL]             = BUILD_POLICY(U32),
+        [IFLA_GENEVE_TTL_INHERIT]       = BUILD_POLICY(U8),
+        [IFLA_GENEVE_DF]                = BUILD_POLICY(U8),
+};
+
+static const NLAPolicy rtnl_link_info_data_gre_policies[] = {
+        [IFLA_GRE_LINK]             = BUILD_POLICY(U32),
+        [IFLA_GRE_IFLAGS]           = BUILD_POLICY(U16),
+        [IFLA_GRE_OFLAGS]           = BUILD_POLICY(U16),
+        [IFLA_GRE_IKEY]             = BUILD_POLICY(U32),
+        [IFLA_GRE_OKEY]             = BUILD_POLICY(U32),
+        [IFLA_GRE_LOCAL]            = BUILD_POLICY(IN_ADDR),
+        [IFLA_GRE_REMOTE]           = BUILD_POLICY(IN_ADDR),
+        [IFLA_GRE_TTL]              = BUILD_POLICY(U8),
+        [IFLA_GRE_TOS]              = BUILD_POLICY(U8),
+        [IFLA_GRE_PMTUDISC]         = BUILD_POLICY(U8),
+        [IFLA_GRE_ENCAP_LIMIT]      = BUILD_POLICY(U8),
+        [IFLA_GRE_FLOWINFO]         = BUILD_POLICY(U32),
+        [IFLA_GRE_FLAGS]            = BUILD_POLICY(U32),
+        [IFLA_GRE_ENCAP_TYPE]       = BUILD_POLICY(U16),
+        [IFLA_GRE_ENCAP_FLAGS]      = BUILD_POLICY(U16),
+        [IFLA_GRE_ENCAP_SPORT]      = BUILD_POLICY(U16),
+        [IFLA_GRE_ENCAP_DPORT]      = BUILD_POLICY(U16),
+        [IFLA_GRE_COLLECT_METADATA] = BUILD_POLICY(FLAG),
+        [IFLA_GRE_IGNORE_DF]        = BUILD_POLICY(U8),
+        [IFLA_GRE_FWMARK]           = BUILD_POLICY(U32),
+        [IFLA_GRE_ERSPAN_INDEX]     = BUILD_POLICY(U32),
+        [IFLA_GRE_ERSPAN_VER]       = BUILD_POLICY(U8),
+        [IFLA_GRE_ERSPAN_DIR]       = BUILD_POLICY(U8),
+        [IFLA_GRE_ERSPAN_HWID]      = BUILD_POLICY(U16),
+};
+
+static const NLAPolicy rtnl_link_info_data_ipoib_policies[] = {
+        [IFLA_IPOIB_PKEY]           = BUILD_POLICY(U16),
+        [IFLA_IPOIB_MODE]           = BUILD_POLICY(U16),
+        [IFLA_IPOIB_UMCAST]         = BUILD_POLICY(U16),
 };
 
 /* IFLA_IPTUN_ attributes are used in ipv4/ipip.c, ipv6/ip6_tunnel.c, and ipv6/sit.c. And unfortunately,
  * IFLA_IPTUN_FLAGS is used with different types, ugh... */
-#define DEFINE_IPTUN_TYPES(name, flags_type)                                            \
-        static const NLType rtnl_link_info_data_##name##_types[] = {                    \
-                [IFLA_IPTUN_LINK]                = { .type = NETLINK_TYPE_U32 },        \
-                [IFLA_IPTUN_LOCAL]               = { .type = NETLINK_TYPE_IN_ADDR },    \
-                [IFLA_IPTUN_REMOTE]              = { .type = NETLINK_TYPE_IN_ADDR },    \
-                [IFLA_IPTUN_TTL]                 = { .type = NETLINK_TYPE_U8 },         \
-                [IFLA_IPTUN_TOS]                 = { .type = NETLINK_TYPE_U8 },         \
-                [IFLA_IPTUN_ENCAP_LIMIT]         = { .type = NETLINK_TYPE_U8 },         \
-                [IFLA_IPTUN_FLOWINFO]            = { .type = NETLINK_TYPE_U32 },        \
-                [IFLA_IPTUN_FLAGS]               = { .type = flags_type },              \
-                [IFLA_IPTUN_PROTO]               = { .type = NETLINK_TYPE_U8 },         \
-                [IFLA_IPTUN_PMTUDISC]            = { .type = NETLINK_TYPE_U8 },         \
-                [IFLA_IPTUN_6RD_PREFIX]          = { .type = NETLINK_TYPE_IN_ADDR,      \
-                                                     .size = sizeof(struct in6_addr) }, \
-                [IFLA_IPTUN_6RD_RELAY_PREFIX]    = { .type = NETLINK_TYPE_U32 },        \
-                [IFLA_IPTUN_6RD_PREFIXLEN]       = { .type = NETLINK_TYPE_U16 },        \
-                [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NETLINK_TYPE_U16 },        \
-                [IFLA_IPTUN_ENCAP_TYPE]          = { .type = NETLINK_TYPE_U16 },        \
-                [IFLA_IPTUN_ENCAP_FLAGS]         = { .type = NETLINK_TYPE_U16 },        \
-                [IFLA_IPTUN_ENCAP_SPORT]         = { .type = NETLINK_TYPE_U16 },        \
-                [IFLA_IPTUN_ENCAP_DPORT]         = { .type = NETLINK_TYPE_U16 },        \
-                [IFLA_IPTUN_COLLECT_METADATA]    = { .type = NETLINK_TYPE_FLAG },       \
-                [IFLA_IPTUN_FWMARK]              = { .type = NETLINK_TYPE_U32 },        \
+#define DEFINE_IPTUN_TYPES(name, flags_type)                            \
+        static const NLAPolicy rtnl_link_info_data_##name##_policies[] = {    \
+                [IFLA_IPTUN_LINK]                = BUILD_POLICY(U32),   \
+                [IFLA_IPTUN_LOCAL]               = BUILD_POLICY(IN_ADDR), \
+                [IFLA_IPTUN_REMOTE]              = BUILD_POLICY(IN_ADDR), \
+                [IFLA_IPTUN_TTL]                 = BUILD_POLICY(U8),    \
+                [IFLA_IPTUN_TOS]                 = BUILD_POLICY(U8),    \
+                [IFLA_IPTUN_ENCAP_LIMIT]         = BUILD_POLICY(U8),    \
+                [IFLA_IPTUN_FLOWINFO]            = BUILD_POLICY(U32),   \
+                [IFLA_IPTUN_FLAGS]               = BUILD_POLICY(flags_type), \
+                [IFLA_IPTUN_PROTO]               = BUILD_POLICY(U8),    \
+                [IFLA_IPTUN_PMTUDISC]            = BUILD_POLICY(U8),    \
+                [IFLA_IPTUN_6RD_PREFIX]          = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)), \
+                [IFLA_IPTUN_6RD_RELAY_PREFIX]    = BUILD_POLICY(U32),   \
+                [IFLA_IPTUN_6RD_PREFIXLEN]       = BUILD_POLICY(U16),   \
+                [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = BUILD_POLICY(U16),   \
+                [IFLA_IPTUN_ENCAP_TYPE]          = BUILD_POLICY(U16),   \
+                [IFLA_IPTUN_ENCAP_FLAGS]         = BUILD_POLICY(U16),   \
+                [IFLA_IPTUN_ENCAP_SPORT]         = BUILD_POLICY(U16),   \
+                [IFLA_IPTUN_ENCAP_DPORT]         = BUILD_POLICY(U16),   \
+                [IFLA_IPTUN_COLLECT_METADATA]    = BUILD_POLICY(FLAG),  \
+                [IFLA_IPTUN_FWMARK]              = BUILD_POLICY(U32),   \
         }
 
-DEFINE_IPTUN_TYPES(iptun, NETLINK_TYPE_U32); /* for ipip and ip6tnl */
-DEFINE_IPTUN_TYPES(sit, NETLINK_TYPE_U16); /* for sit */
+DEFINE_IPTUN_TYPES(iptun, U32); /* for ipip and ip6tnl */
+DEFINE_IPTUN_TYPES(sit, U16); /* for sit */
 
-static const NLType rtnl_link_info_data_ipvlan_types[] = {
-        [IFLA_IPVLAN_MODE]  = { .type = NETLINK_TYPE_U16 },
-        [IFLA_IPVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
-};
-
-static const NLType rtnl_link_info_data_macsec_types[] = {
-        [IFLA_MACSEC_SCI]            = { .type = NETLINK_TYPE_U64 },
-        [IFLA_MACSEC_PORT]           = { .type = NETLINK_TYPE_U16 },
-        [IFLA_MACSEC_ICV_LEN]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_MACSEC_CIPHER_SUITE]   = { .type = NETLINK_TYPE_U64 },
-        [IFLA_MACSEC_WINDOW]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_MACSEC_ENCODING_SA]    = { .type = NETLINK_TYPE_U8 },
-        [IFLA_MACSEC_ENCRYPT]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_MACSEC_PROTECT]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_MACSEC_INC_SCI]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_MACSEC_ES]             = { .type = NETLINK_TYPE_U8 },
-        [IFLA_MACSEC_SCB]            = { .type = NETLINK_TYPE_U8 },
-        [IFLA_MACSEC_REPLAY_PROTECT] = { .type = NETLINK_TYPE_U8 },
-        [IFLA_MACSEC_VALIDATION]     = { .type = NETLINK_TYPE_U8 },
-        [IFLA_MACSEC_OFFLOAD]        = { .type = NETLINK_TYPE_U8 },
-};
-
-static const NLType rtnl_macvlan_macaddr_types[] = {
-        [IFLA_MACVLAN_MACADDR] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_macvlan_macaddr);
-
-static const NLType rtnl_link_info_data_macvlan_types[] = {
-        [IFLA_MACVLAN_MODE]              = { .type = NETLINK_TYPE_U32 },
-        [IFLA_MACVLAN_FLAGS]             = { .type = NETLINK_TYPE_U16 },
-        [IFLA_MACVLAN_MACADDR_MODE]      = { .type = NETLINK_TYPE_U32 },
-        [IFLA_MACVLAN_MACADDR_DATA]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_macvlan_macaddr_type_system },
-        [IFLA_MACVLAN_MACADDR_COUNT]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_MACVLAN_BC_QUEUE_LEN]      = { .type = NETLINK_TYPE_U32 },
-        [IFLA_MACVLAN_BC_QUEUE_LEN_USED] = { .type = NETLINK_TYPE_U32 },
-};
-
-static const NLType rtnl_link_info_data_tun_types[] = {
-        [IFLA_TUN_OWNER]               = { .type = NETLINK_TYPE_U32 },
-        [IFLA_TUN_GROUP]               = { .type = NETLINK_TYPE_U32 },
-        [IFLA_TUN_TYPE]                = { .type = NETLINK_TYPE_U8 },
-        [IFLA_TUN_PI]                  = { .type = NETLINK_TYPE_U8 },
-        [IFLA_TUN_VNET_HDR]            = { .type = NETLINK_TYPE_U8 },
-        [IFLA_TUN_PERSIST]             = { .type = NETLINK_TYPE_U8 },
-        [IFLA_TUN_MULTI_QUEUE]         = { .type = NETLINK_TYPE_U8 },
-        [IFLA_TUN_NUM_QUEUES]          = { .type = NETLINK_TYPE_U32 },
-        [IFLA_TUN_NUM_DISABLED_QUEUES] = { .type = NETLINK_TYPE_U32 },
-};
-
-static const NLType rtnl_link_info_data_veth_types[] = {
-        [VETH_INFO_PEER]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
-};
-
-static const NLType rtnl_vlan_qos_map_types[] = {
-        [IFLA_VLAN_QOS_MAPPING]        = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vlan_qos_mapping) },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_vlan_qos_map);
-
-static const NLType rtnl_link_info_data_vlan_types[] = {
-        [IFLA_VLAN_ID]          = { .type = NETLINK_TYPE_U16 },
-        [IFLA_VLAN_FLAGS]       = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vlan_flags) },
-        [IFLA_VLAN_EGRESS_QOS]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vlan_qos_map_type_system },
-        [IFLA_VLAN_INGRESS_QOS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vlan_qos_map_type_system },
-        [IFLA_VLAN_PROTOCOL]    = { .type = NETLINK_TYPE_U16 },
-};
-
-static const NLType rtnl_link_info_data_vrf_types[] = {
-        [IFLA_VRF_TABLE]                 = { .type = NETLINK_TYPE_U32 },
-};
-
-static const NLType rtnl_link_info_data_vti_types[] = {
-        [IFLA_VTI_LINK]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_VTI_IKEY]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_VTI_OKEY]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_VTI_LOCAL]        = { .type = NETLINK_TYPE_IN_ADDR },
-        [IFLA_VTI_REMOTE]       = { .type = NETLINK_TYPE_IN_ADDR },
-        [IFLA_VTI_FWMARK]       = { .type = NETLINK_TYPE_U32 },
-};
-
-static const NLType rtnl_link_info_data_vxcan_types[] = {
-        [VXCAN_INFO_PEER]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
-};
-
-static const NLType rtnl_link_info_data_vxlan_types[] = {
-        [IFLA_VXLAN_ID]                = { .type = NETLINK_TYPE_U32 },
-        [IFLA_VXLAN_GROUP]             = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in_addr) },
-        [IFLA_VXLAN_LINK]              = { .type = NETLINK_TYPE_U32 },
-        [IFLA_VXLAN_LOCAL]             = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in_addr) },
-        [IFLA_VXLAN_TTL]               = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_TOS]               = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_LEARNING]          = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_AGEING]            = { .type = NETLINK_TYPE_U32 },
-        [IFLA_VXLAN_LIMIT]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_VXLAN_PORT_RANGE]        = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vxlan_port_range) },
-        [IFLA_VXLAN_PROXY]             = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_RSC]               = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_L2MISS]            = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_L3MISS]            = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_PORT]              = { .type = NETLINK_TYPE_U16 },
-        [IFLA_VXLAN_GROUP6]            = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
-        [IFLA_VXLAN_LOCAL6]            = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
-        [IFLA_VXLAN_UDP_CSUM]          = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_REMCSUM_TX]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_REMCSUM_RX]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_GBP]               = { .type = NETLINK_TYPE_FLAG },
-        [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
-        [IFLA_VXLAN_COLLECT_METADATA]  = { .type = NETLINK_TYPE_U8 },
-        [IFLA_VXLAN_LABEL]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_VXLAN_GPE]               = { .type = NETLINK_TYPE_FLAG },
-        [IFLA_VXLAN_TTL_INHERIT]       = { .type = NETLINK_TYPE_FLAG },
-        [IFLA_VXLAN_DF]                = { .type = NETLINK_TYPE_U8 },
-};
-
-static const NLType rtnl_link_info_data_xfrm_types[] = {
-        [IFLA_XFRM_LINK]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_XFRM_IF_ID]        = { .type = NETLINK_TYPE_U32 }
+static const NLAPolicy rtnl_link_info_data_ipvlan_policies[] = {
+        [IFLA_IPVLAN_MODE]  = BUILD_POLICY(U16),
+        [IFLA_IPVLAN_FLAGS] = BUILD_POLICY(U16),
+};
+
+static const NLAPolicy rtnl_link_info_data_macsec_policies[] = {
+        [IFLA_MACSEC_SCI]            = BUILD_POLICY(U64),
+        [IFLA_MACSEC_PORT]           = BUILD_POLICY(U16),
+        [IFLA_MACSEC_ICV_LEN]        = BUILD_POLICY(U8),
+        [IFLA_MACSEC_CIPHER_SUITE]   = BUILD_POLICY(U64),
+        [IFLA_MACSEC_WINDOW]         = BUILD_POLICY(U32),
+        [IFLA_MACSEC_ENCODING_SA]    = BUILD_POLICY(U8),
+        [IFLA_MACSEC_ENCRYPT]        = BUILD_POLICY(U8),
+        [IFLA_MACSEC_PROTECT]        = BUILD_POLICY(U8),
+        [IFLA_MACSEC_INC_SCI]        = BUILD_POLICY(U8),
+        [IFLA_MACSEC_ES]             = BUILD_POLICY(U8),
+        [IFLA_MACSEC_SCB]            = BUILD_POLICY(U8),
+        [IFLA_MACSEC_REPLAY_PROTECT] = BUILD_POLICY(U8),
+        [IFLA_MACSEC_VALIDATION]     = BUILD_POLICY(U8),
+        [IFLA_MACSEC_OFFLOAD]        = BUILD_POLICY(U8),
+};
+
+static const NLAPolicy rtnl_macvlan_macaddr_policies[] = {
+        [IFLA_MACVLAN_MACADDR] = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+};
+
+DEFINE_POLICY_SET(rtnl_macvlan_macaddr);
+
+static const NLAPolicy rtnl_link_info_data_macvlan_policies[] = {
+        [IFLA_MACVLAN_MODE]              = BUILD_POLICY(U32),
+        [IFLA_MACVLAN_FLAGS]             = BUILD_POLICY(U16),
+        [IFLA_MACVLAN_MACADDR_MODE]      = BUILD_POLICY(U32),
+        [IFLA_MACVLAN_MACADDR_DATA]      = BUILD_POLICY_NESTED(rtnl_macvlan_macaddr),
+        [IFLA_MACVLAN_MACADDR_COUNT]     = BUILD_POLICY(U32),
+        [IFLA_MACVLAN_BC_QUEUE_LEN]      = BUILD_POLICY(U32),
+        [IFLA_MACVLAN_BC_QUEUE_LEN_USED] = BUILD_POLICY(U32),
+};
+
+static const NLAPolicy rtnl_link_info_data_tun_policies[] = {
+        [IFLA_TUN_OWNER]               = BUILD_POLICY(U32),
+        [IFLA_TUN_GROUP]               = BUILD_POLICY(U32),
+        [IFLA_TUN_TYPE]                = BUILD_POLICY(U8),
+        [IFLA_TUN_PI]                  = BUILD_POLICY(U8),
+        [IFLA_TUN_VNET_HDR]            = BUILD_POLICY(U8),
+        [IFLA_TUN_PERSIST]             = BUILD_POLICY(U8),
+        [IFLA_TUN_MULTI_QUEUE]         = BUILD_POLICY(U8),
+        [IFLA_TUN_NUM_QUEUES]          = BUILD_POLICY(U32),
+        [IFLA_TUN_NUM_DISABLED_QUEUES] = BUILD_POLICY(U32),
+};
+
+static const NLAPolicy rtnl_link_info_data_veth_policies[] = {
+        [VETH_INFO_PEER]  = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_link, sizeof(struct ifinfomsg)),
+};
+
+static const NLAPolicy rtnl_vlan_qos_map_policies[] = {
+        [IFLA_VLAN_QOS_MAPPING]        = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vlan_qos_mapping)),
+};
+
+DEFINE_POLICY_SET(rtnl_vlan_qos_map);
+
+static const NLAPolicy rtnl_link_info_data_vlan_policies[] = {
+        [IFLA_VLAN_ID]          = BUILD_POLICY(U16),
+        [IFLA_VLAN_FLAGS]       = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vlan_flags)),
+        [IFLA_VLAN_EGRESS_QOS]  = BUILD_POLICY_NESTED(rtnl_vlan_qos_map),
+        [IFLA_VLAN_INGRESS_QOS] = BUILD_POLICY_NESTED(rtnl_vlan_qos_map),
+        [IFLA_VLAN_PROTOCOL]    = BUILD_POLICY(U16),
+};
+
+static const NLAPolicy rtnl_link_info_data_vrf_policies[] = {
+        [IFLA_VRF_TABLE]                 = BUILD_POLICY(U32),
+};
+
+static const NLAPolicy rtnl_link_info_data_vti_policies[] = {
+        [IFLA_VTI_LINK]         = BUILD_POLICY(U32),
+        [IFLA_VTI_IKEY]         = BUILD_POLICY(U32),
+        [IFLA_VTI_OKEY]         = BUILD_POLICY(U32),
+        [IFLA_VTI_LOCAL]        = BUILD_POLICY(IN_ADDR),
+        [IFLA_VTI_REMOTE]       = BUILD_POLICY(IN_ADDR),
+        [IFLA_VTI_FWMARK]       = BUILD_POLICY(U32),
+};
+
+static const NLAPolicy rtnl_link_info_data_vxcan_policies[] = {
+        [VXCAN_INFO_PEER]  = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_link, sizeof(struct ifinfomsg)),
+};
+
+static const NLAPolicy rtnl_link_info_data_vxlan_policies[] = {
+        [IFLA_VXLAN_ID]                = BUILD_POLICY(U32),
+        [IFLA_VXLAN_GROUP]             = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in_addr)),
+        [IFLA_VXLAN_LINK]              = BUILD_POLICY(U32),
+        [IFLA_VXLAN_LOCAL]             = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in_addr)),
+        [IFLA_VXLAN_TTL]               = BUILD_POLICY(U8),
+        [IFLA_VXLAN_TOS]               = BUILD_POLICY(U8),
+        [IFLA_VXLAN_LEARNING]          = BUILD_POLICY(U8),
+        [IFLA_VXLAN_AGEING]            = BUILD_POLICY(U32),
+        [IFLA_VXLAN_LIMIT]             = BUILD_POLICY(U32),
+        [IFLA_VXLAN_PORT_RANGE]        = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vxlan_port_range)),
+        [IFLA_VXLAN_PROXY]             = BUILD_POLICY(U8),
+        [IFLA_VXLAN_RSC]               = BUILD_POLICY(U8),
+        [IFLA_VXLAN_L2MISS]            = BUILD_POLICY(U8),
+        [IFLA_VXLAN_L3MISS]            = BUILD_POLICY(U8),
+        [IFLA_VXLAN_PORT]              = BUILD_POLICY(U16),
+        [IFLA_VXLAN_GROUP6]            = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)),
+        [IFLA_VXLAN_LOCAL6]            = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)),
+        [IFLA_VXLAN_UDP_CSUM]          = BUILD_POLICY(U8),
+        [IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = BUILD_POLICY(U8),
+        [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = BUILD_POLICY(U8),
+        [IFLA_VXLAN_REMCSUM_TX]        = BUILD_POLICY(U8),
+        [IFLA_VXLAN_REMCSUM_RX]        = BUILD_POLICY(U8),
+        [IFLA_VXLAN_GBP]               = BUILD_POLICY(FLAG),
+        [IFLA_VXLAN_REMCSUM_NOPARTIAL] = BUILD_POLICY(FLAG),
+        [IFLA_VXLAN_COLLECT_METADATA]  = BUILD_POLICY(U8),
+        [IFLA_VXLAN_LABEL]             = BUILD_POLICY(U32),
+        [IFLA_VXLAN_GPE]               = BUILD_POLICY(FLAG),
+        [IFLA_VXLAN_TTL_INHERIT]       = BUILD_POLICY(FLAG),
+        [IFLA_VXLAN_DF]                = BUILD_POLICY(U8),
+};
+
+static const NLAPolicy rtnl_link_info_data_xfrm_policies[] = {
+        [IFLA_XFRM_LINK]         = BUILD_POLICY(U32),
+        [IFLA_XFRM_IF_ID]        = BUILD_POLICY(U32)
 };
-
-static const NLTypeSystemUnionElement rtnl_link_info_data_type_systems[] = {
-        { .name = "bareudp",   .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_bareudp), },
-        { .name = "batadv",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_batadv),  },
-        { .name = "bond",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_bond),    },
-        { .name = "bridge",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_bridge),  },
+
+static const NLAPolicySetUnionElement rtnl_link_info_data_policy_set_union_elements[] = {
+        BUILD_UNION_ELEMENT_BY_STRING("bareudp",   rtnl_link_info_data_bareudp),
+        BUILD_UNION_ELEMENT_BY_STRING("batadv",    rtnl_link_info_data_batadv),
+        BUILD_UNION_ELEMENT_BY_STRING("bond",      rtnl_link_info_data_bond),
+        BUILD_UNION_ELEMENT_BY_STRING("bridge",    rtnl_link_info_data_bridge),
 /*
-        { .name = "caif",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_caif),    },
+        BUILD_UNION_ELEMENT_BY_STRING("caif",      rtnl_link_info_data_caif),
 */
-        { .name = "can",       .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_can),     },
-        { .name = "erspan",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_gre),     },
-        { .name = "geneve",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_geneve),  },
-        { .name = "gre",       .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_gre),     },
-        { .name = "gretap",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_gre),     },
+        BUILD_UNION_ELEMENT_BY_STRING("can",       rtnl_link_info_data_can),
+        BUILD_UNION_ELEMENT_BY_STRING("erspan",    rtnl_link_info_data_gre),
+        BUILD_UNION_ELEMENT_BY_STRING("geneve",    rtnl_link_info_data_geneve),
+        BUILD_UNION_ELEMENT_BY_STRING("gre",       rtnl_link_info_data_gre),
+        BUILD_UNION_ELEMENT_BY_STRING("gretap",    rtnl_link_info_data_gre),
 /*
-        { .name = "gtp",       .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_gtp),     },
-        { .name = "hsr",       .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_hsr),     },
+        BUILD_UNION_ELEMENT_BY_STRING("gtp",       rtnl_link_info_data_gtp),
+        BUILD_UNION_ELEMENT_BY_STRING("hsr",       rtnl_link_info_data_hsr),
 */
-        { .name = "ip6erspan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_gre),     },
-        { .name = "ip6gre",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_gre),     },
-        { .name = "ip6gretap", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_gre),     },
-        { .name = "ip6tnl",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_iptun),   },
-        { .name = "ipoib",     .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipoib),   },
-        { .name = "ipip",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_iptun),   },
-        { .name = "ipvlan",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipvlan),  },
-        { .name = "ipvtap",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipvlan),  },
-        { .name = "macsec",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_macsec),  },
-        { .name = "macvlan",   .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_macvlan), },
-        { .name = "macvtap",   .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_macvlan), },
+        BUILD_UNION_ELEMENT_BY_STRING("ip6erspan", rtnl_link_info_data_gre),
+        BUILD_UNION_ELEMENT_BY_STRING("ip6gre",    rtnl_link_info_data_gre),
+        BUILD_UNION_ELEMENT_BY_STRING("ip6gretap", rtnl_link_info_data_gre),
+        BUILD_UNION_ELEMENT_BY_STRING("ip6tnl",    rtnl_link_info_data_iptun),
+        BUILD_UNION_ELEMENT_BY_STRING("ipoib",     rtnl_link_info_data_ipoib),
+        BUILD_UNION_ELEMENT_BY_STRING("ipip",      rtnl_link_info_data_iptun),
+        BUILD_UNION_ELEMENT_BY_STRING("ipvlan",    rtnl_link_info_data_ipvlan),
+        BUILD_UNION_ELEMENT_BY_STRING("ipvtap",    rtnl_link_info_data_ipvlan),
+        BUILD_UNION_ELEMENT_BY_STRING("macsec",    rtnl_link_info_data_macsec),
+        BUILD_UNION_ELEMENT_BY_STRING("macvlan",   rtnl_link_info_data_macvlan),
+        BUILD_UNION_ELEMENT_BY_STRING("macvtap",   rtnl_link_info_data_macvlan),
 /*
-        { .name = "ppp",       .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ppp),     },
-        { .name = "rmnet",     .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_rmnet),   },
+        BUILD_UNION_ELEMENT_BY_STRING("ppp",       rtnl_link_info_data_ppp),
+        BUILD_UNION_ELEMENT_BY_STRING("rmnet",     rtnl_link_info_data_rmnet),
 */
-        { .name = "sit",       .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_sit),     },
-        { .name = "tun",       .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_tun),     },
-        { .name = "veth",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_veth),    },
-        { .name = "vlan",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vlan),    },
-        { .name = "vrf",       .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vrf),     },
-        { .name = "vti",       .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vti),     },
-        { .name = "vti6",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vti),     },
-        { .name = "vxcan",     .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vxcan),   },
-        { .name = "vxlan",     .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vxlan),   },
+        BUILD_UNION_ELEMENT_BY_STRING("sit",       rtnl_link_info_data_sit),
+        BUILD_UNION_ELEMENT_BY_STRING("tun",       rtnl_link_info_data_tun),
+        BUILD_UNION_ELEMENT_BY_STRING("veth",      rtnl_link_info_data_veth),
+        BUILD_UNION_ELEMENT_BY_STRING("vlan",      rtnl_link_info_data_vlan),
+        BUILD_UNION_ELEMENT_BY_STRING("vrf",       rtnl_link_info_data_vrf),
+        BUILD_UNION_ELEMENT_BY_STRING("vti",       rtnl_link_info_data_vti),
+        BUILD_UNION_ELEMENT_BY_STRING("vti6",      rtnl_link_info_data_vti),
+        BUILD_UNION_ELEMENT_BY_STRING("vxcan",     rtnl_link_info_data_vxcan),
+        BUILD_UNION_ELEMENT_BY_STRING("vxlan",     rtnl_link_info_data_vxlan),
 /*
-        { .name = "wwan",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_wwan),    },
+        BUILD_UNION_ELEMENT_BY_STRING("wwan",      rtnl_link_info_data_wwan),
 */
-        { .name = "xfrm",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_xfrm),    },
-};
-
-DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(rtnl_link_info_data, IFLA_INFO_KIND);
-
-static const struct NLType rtnl_bridge_port_types[] = {
-        [IFLA_BRPORT_STATE]                 = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_COST]                  = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRPORT_PRIORITY]              = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRPORT_MODE]                  = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_GUARD]                 = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_PROTECT]               = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_FAST_LEAVE]            = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_LEARNING]              = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_UNICAST_FLOOD]         = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_PROXYARP]              = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_LEARNING_SYNC]         = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_PROXYARP_WIFI]         = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_ROOT_ID]               = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_BRIDGE_ID]             = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_DESIGNATED_PORT]       = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRPORT_DESIGNATED_COST]       = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRPORT_ID]                    = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRPORT_NO]                    = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRPORT_TOPOLOGY_CHANGE_ACK]   = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_CONFIG_PENDING]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_MESSAGE_AGE_TIMER]     = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BRPORT_FORWARD_DELAY_TIMER]   = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BRPORT_HOLD_TIMER]            = { .type = NETLINK_TYPE_U64 },
-        [IFLA_BRPORT_FLUSH]                 = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_MULTICAST_ROUTER]      = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_PAD]                   = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_MCAST_FLOOD]           = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_MCAST_TO_UCAST]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_VLAN_TUNNEL]           = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_BCAST_FLOOD]           = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_GROUP_FWD_MASK]        = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRPORT_NEIGH_SUPPRESS]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_ISOLATED]              = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_BACKUP_PORT]           = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRPORT_MRP_RING_OPEN]         = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_MRP_IN_OPEN]           = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT] = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRPORT_MCAST_EHT_HOSTS_CNT]   = { .type = NETLINK_TYPE_U32 },
-};
-
-static const NLTypeSystemUnionElement rtnl_link_info_slave_data_type_systems[] = {
-        { .name = "bridge",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_bridge_port), },
-};
-
-DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(rtnl_link_info_slave_data, IFLA_INFO_SLAVE_KIND);
-
-static const NLType rtnl_link_info_types[] = {
-        [IFLA_INFO_KIND]        = { .type = NETLINK_TYPE_STRING },
-        [IFLA_INFO_DATA]        = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_link_info_data_type_system_union },
+        BUILD_UNION_ELEMENT_BY_STRING("xfrm",      rtnl_link_info_data_xfrm),
+};
+
+DEFINE_POLICY_SET_UNION(rtnl_link_info_data, IFLA_INFO_KIND);
+
+static const struct NLAPolicy rtnl_bridge_port_policies[] = {
+        [IFLA_BRPORT_STATE]                 = BUILD_POLICY(U8),
+        [IFLA_BRPORT_COST]                  = BUILD_POLICY(U32),
+        [IFLA_BRPORT_PRIORITY]              = BUILD_POLICY(U16),
+        [IFLA_BRPORT_MODE]                  = BUILD_POLICY(U8),
+        [IFLA_BRPORT_GUARD]                 = BUILD_POLICY(U8),
+        [IFLA_BRPORT_PROTECT]               = BUILD_POLICY(U8),
+        [IFLA_BRPORT_FAST_LEAVE]            = BUILD_POLICY(U8),
+        [IFLA_BRPORT_LEARNING]              = BUILD_POLICY(U8),
+        [IFLA_BRPORT_UNICAST_FLOOD]         = BUILD_POLICY(U8),
+        [IFLA_BRPORT_PROXYARP]              = BUILD_POLICY(U8),
+        [IFLA_BRPORT_LEARNING_SYNC]         = BUILD_POLICY(U8),
+        [IFLA_BRPORT_PROXYARP_WIFI]         = BUILD_POLICY(U8),
+        [IFLA_BRPORT_ROOT_ID]               = BUILD_POLICY(U8),
+        [IFLA_BRPORT_BRIDGE_ID]             = BUILD_POLICY(U8),
+        [IFLA_BRPORT_DESIGNATED_PORT]       = BUILD_POLICY(U16),
+        [IFLA_BRPORT_DESIGNATED_COST]       = BUILD_POLICY(U16),
+        [IFLA_BRPORT_ID]                    = BUILD_POLICY(U16),
+        [IFLA_BRPORT_NO]                    = BUILD_POLICY(U16),
+        [IFLA_BRPORT_TOPOLOGY_CHANGE_ACK]   = BUILD_POLICY(U8),
+        [IFLA_BRPORT_CONFIG_PENDING]        = BUILD_POLICY(U8),
+        [IFLA_BRPORT_MESSAGE_AGE_TIMER]     = BUILD_POLICY(U64),
+        [IFLA_BRPORT_FORWARD_DELAY_TIMER]   = BUILD_POLICY(U64),
+        [IFLA_BRPORT_HOLD_TIMER]            = BUILD_POLICY(U64),
+        [IFLA_BRPORT_FLUSH]                 = BUILD_POLICY(U8),
+        [IFLA_BRPORT_MULTICAST_ROUTER]      = BUILD_POLICY(U8),
+        [IFLA_BRPORT_PAD]                   = BUILD_POLICY(U8),
+        [IFLA_BRPORT_MCAST_FLOOD]           = BUILD_POLICY(U8),
+        [IFLA_BRPORT_MCAST_TO_UCAST]        = BUILD_POLICY(U8),
+        [IFLA_BRPORT_VLAN_TUNNEL]           = BUILD_POLICY(U8),
+        [IFLA_BRPORT_BCAST_FLOOD]           = BUILD_POLICY(U8),
+        [IFLA_BRPORT_GROUP_FWD_MASK]        = BUILD_POLICY(U16),
+        [IFLA_BRPORT_NEIGH_SUPPRESS]        = BUILD_POLICY(U8),
+        [IFLA_BRPORT_ISOLATED]              = BUILD_POLICY(U8),
+        [IFLA_BRPORT_BACKUP_PORT]           = BUILD_POLICY(U32),
+        [IFLA_BRPORT_MRP_RING_OPEN]         = BUILD_POLICY(U8),
+        [IFLA_BRPORT_MRP_IN_OPEN]           = BUILD_POLICY(U8),
+        [IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT] = BUILD_POLICY(U32),
+        [IFLA_BRPORT_MCAST_EHT_HOSTS_CNT]   = BUILD_POLICY(U32),
+};
+
+static const NLAPolicySetUnionElement rtnl_link_info_slave_data_policy_set_union_elements[] = {
+        BUILD_UNION_ELEMENT_BY_STRING("bridge",    rtnl_bridge_port),
+};
+
+DEFINE_POLICY_SET_UNION(rtnl_link_info_slave_data, IFLA_INFO_SLAVE_KIND);
+
+static const NLAPolicy rtnl_link_info_policies[] = {
+        [IFLA_INFO_KIND]        = BUILD_POLICY(STRING),
+        [IFLA_INFO_DATA]        = BUILD_POLICY_NESTED_UNION_BY_STRING(rtnl_link_info_data),
         /* TODO: Currently IFLA_INFO_XSTATS is used only when IFLA_INFO_KIND is "can". In the future,
-         * when multiple kinds of netdevs use this attribute, then convert its type to NETLINK_TYPE_UNION. */
-        [IFLA_INFO_XSTATS]      = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct can_device_stats) },
-        [IFLA_INFO_SLAVE_KIND]  = { .type = NETLINK_TYPE_STRING },
-        [IFLA_INFO_SLAVE_DATA]  = { .type = NETLINK_TYPE_NESTED, .type_system_union = &rtnl_link_info_slave_data_type_system_union },
+         * when multiple kinds of netdevs use this attribute, convert its type to NETLINK_TYPE_UNION. */
+        [IFLA_INFO_XSTATS]      = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct can_device_stats)),
+        [IFLA_INFO_SLAVE_KIND]  = BUILD_POLICY(STRING),
+        [IFLA_INFO_SLAVE_DATA]  = BUILD_POLICY_NESTED_UNION_BY_STRING(rtnl_link_info_slave_data),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_link_info);
+DEFINE_POLICY_SET(rtnl_link_info);
 
-static const struct NLType rtnl_inet_types[] = {
-        [IFLA_INET_CONF] = { .type = NETLINK_TYPE_BINARY }, /* size = IPV4_DEVCONF_MAX * 4 */
+static const struct NLAPolicy rtnl_inet_policies[] = {
+        [IFLA_INET_CONF] = BUILD_POLICY(BINARY), /* size = IPV4_DEVCONF_MAX * 4 */
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_inet);
+DEFINE_POLICY_SET(rtnl_inet);
 
-static const struct NLType rtnl_inet6_types[] = {
-        [IFLA_INET6_FLAGS]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_INET6_CONF]          = { .type = NETLINK_TYPE_BINARY }, /* size = DEVCONF_MAX * sizeof(s32) */
-        [IFLA_INET6_STATS]         = { .type = NETLINK_TYPE_BINARY }, /* size = IPSTATS_MIB_MAX * sizeof(u64) */
+static const struct NLAPolicy rtnl_inet6_policies[] = {
+        [IFLA_INET6_FLAGS]         = BUILD_POLICY(U32),
+        [IFLA_INET6_CONF]          = BUILD_POLICY(BINARY), /* size = DEVCONF_MAX * sizeof(s32) */
+        [IFLA_INET6_STATS]         = BUILD_POLICY(BINARY), /* size = IPSTATS_MIB_MAX * sizeof(u64) */
         [IFLA_INET6_MCAST]         = {}, /* unused. */
-        [IFLA_INET6_CACHEINFO]     = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_cacheinfo) },
-        [IFLA_INET6_ICMP6STATS]    = { .type = NETLINK_TYPE_BINARY }, /* size = ICMP6_MIB_MAX * sizeof(u64) */
-        [IFLA_INET6_TOKEN]         = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
-        [IFLA_INET6_ADDR_GEN_MODE] = { .type = NETLINK_TYPE_U8 },
+        [IFLA_INET6_CACHEINFO]     = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_cacheinfo)),
+        [IFLA_INET6_ICMP6STATS]    = BUILD_POLICY(BINARY), /* size = ICMP6_MIB_MAX * sizeof(u64) */
+        [IFLA_INET6_TOKEN]         = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)),
+        [IFLA_INET6_ADDR_GEN_MODE] = BUILD_POLICY(U8),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_inet6);
+DEFINE_POLICY_SET(rtnl_inet6);
 
-static const NLTypeSystemUnionElement rtnl_prot_info_type_systems[] = {
-        { .protocol = AF_BRIDGE, .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_bridge_port), },
-        { .protocol = AF_INET6,  .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_inet6), },
+static const NLAPolicySetUnionElement rtnl_prot_info_policy_set_union_elements[] = {
+        BUILD_UNION_ELEMENT_BY_FAMILY(AF_BRIDGE, rtnl_bridge_port),
+        BUILD_UNION_ELEMENT_BY_FAMILY(AF_INET6,  rtnl_inet6),
 };
 
-DEFINE_TYPE_SYSTEM_UNION_MATCH_PROTOCOL(rtnl_prot_info);
+DEFINE_POLICY_SET_UNION(rtnl_prot_info, 0);
 
-static const NLType rtnl_af_spec_unspec_types[] = {
-        [AF_INET]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_inet_type_system },
-        [AF_INET6] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_inet6_type_system },
+static const NLAPolicy rtnl_af_spec_unspec_policies[] = {
+        [AF_INET]  = BUILD_POLICY_NESTED(rtnl_inet),
+        [AF_INET6] = BUILD_POLICY_NESTED(rtnl_inet6),
 };
 
-static const NLType rtnl_bridge_vlan_tunnel_info_types[] = {
-        [IFLA_BRIDGE_VLAN_TUNNEL_ID]    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_VLAN_TUNNEL_VID]   = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRIDGE_VLAN_TUNNEL_FLAGS] = { .type = NETLINK_TYPE_U16 },
+static const NLAPolicy rtnl_bridge_vlan_tunnel_info_policies[] = {
+        [IFLA_BRIDGE_VLAN_TUNNEL_ID]    = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_VLAN_TUNNEL_VID]   = BUILD_POLICY(U16),
+        [IFLA_BRIDGE_VLAN_TUNNEL_FLAGS] = BUILD_POLICY(U16),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_vlan_tunnel_info);
+DEFINE_POLICY_SET(rtnl_bridge_vlan_tunnel_info);
 
-static const NLType rtnl_bridge_mrp_instance_types[] = {
-        [IFLA_BRIDGE_MRP_INSTANCE_RING_ID]      = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX]    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INSTANCE_PRIO]         = { .type = NETLINK_TYPE_U16 },
+static const NLAPolicy rtnl_bridge_mrp_instance_policies[] = {
+        [IFLA_BRIDGE_MRP_INSTANCE_RING_ID]      = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX]    = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]    = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INSTANCE_PRIO]         = BUILD_POLICY(U16),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_mrp_instance);
+DEFINE_POLICY_SET(rtnl_bridge_mrp_instance);
 
-static const NLType rtnl_bridge_mrp_port_state_types[] = {
-        [IFLA_BRIDGE_MRP_PORT_STATE_STATE]      = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_mrp_port_state_policies[] = {
+        [IFLA_BRIDGE_MRP_PORT_STATE_STATE]      = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_mrp_port_state);
+DEFINE_POLICY_SET(rtnl_bridge_mrp_port_state);
 
-static const NLType rtnl_bridge_mrp_port_role_types[] = {
-        [IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]        = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_mrp_port_role_policies[] = {
+        [IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]        = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_mrp_port_role);
+DEFINE_POLICY_SET(rtnl_bridge_mrp_port_role);
 
-static const NLType rtnl_bridge_mrp_ring_state_types[] = {
-        [IFLA_BRIDGE_MRP_RING_STATE_RING_ID]    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_RING_STATE_STATE]      = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_mrp_ring_state_policies[] = {
+        [IFLA_BRIDGE_MRP_RING_STATE_RING_ID]    = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_RING_STATE_STATE]      = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_mrp_ring_state);
+DEFINE_POLICY_SET(rtnl_bridge_mrp_ring_state);
 
-static const NLType rtnl_bridge_mrp_ring_role_types[] = {
-        [IFLA_BRIDGE_MRP_RING_ROLE_RING_ID]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_RING_ROLE_ROLE]        = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_mrp_ring_role_policies[] = {
+        [IFLA_BRIDGE_MRP_RING_ROLE_RING_ID]     = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_RING_ROLE_ROLE]        = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_mrp_ring_role);
+DEFINE_POLICY_SET(rtnl_bridge_mrp_ring_role);
 
-static const NLType rtnl_bridge_mrp_start_test_types[] = {
-        [IFLA_BRIDGE_MRP_START_TEST_RING_ID]    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_START_TEST_INTERVAL]   = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_START_TEST_MAX_MISS]   = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_START_TEST_PERIOD]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_START_TEST_MONITOR]    = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_mrp_start_test_policies[] = {
+        [IFLA_BRIDGE_MRP_START_TEST_RING_ID]    = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_START_TEST_INTERVAL]   = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_START_TEST_MAX_MISS]   = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_START_TEST_PERIOD]     = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_START_TEST_MONITOR]    = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_mrp_start_test);
+DEFINE_POLICY_SET(rtnl_bridge_mrp_start_test);
 
-static const NLType rtnl_bridge_mrp_info_types[] = {
-        [IFLA_BRIDGE_MRP_INFO_RING_ID]          = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_P_IFINDEX]        = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_S_IFINDEX]        = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_PRIO]             = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRIDGE_MRP_INFO_RING_STATE]       = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_RING_ROLE]        = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_TEST_INTERVAL]    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_TEST_MAX_MISS]    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_TEST_MONITOR]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_I_IFINDEX]        = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_IN_STATE]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_IN_ROLE]          = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_IN_TEST_INTERVAL] = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_INFO_IN_TEST_MAX_MISS] = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_mrp_info_policies[] = {
+        [IFLA_BRIDGE_MRP_INFO_RING_ID]          = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_P_IFINDEX]        = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_S_IFINDEX]        = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_PRIO]             = BUILD_POLICY(U16),
+        [IFLA_BRIDGE_MRP_INFO_RING_STATE]       = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_RING_ROLE]        = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_TEST_INTERVAL]    = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_TEST_MAX_MISS]    = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_TEST_MONITOR]     = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_I_IFINDEX]        = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_IN_STATE]         = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_IN_ROLE]          = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_IN_TEST_INTERVAL] = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_INFO_IN_TEST_MAX_MISS] = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_mrp_info);
+DEFINE_POLICY_SET(rtnl_bridge_mrp_info);
 
-static const NLType rtnl_bridge_mrp_in_role_types[] = {
-        [IFLA_BRIDGE_MRP_IN_ROLE_RING_ID]       = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_IN_ROLE_IN_ID]         = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRIDGE_MRP_IN_ROLE_ROLE]          = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX]     = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_mrp_in_role_policies[] = {
+        [IFLA_BRIDGE_MRP_IN_ROLE_RING_ID]       = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_IN_ROLE_IN_ID]         = BUILD_POLICY(U16),
+        [IFLA_BRIDGE_MRP_IN_ROLE_ROLE]          = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX]     = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_mrp_in_role);
+DEFINE_POLICY_SET(rtnl_bridge_mrp_in_role);
 
-static const NLType rtnl_bridge_mrp_in_state_types[] = {
-        [IFLA_BRIDGE_MRP_IN_STATE_IN_ID]        = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_IN_STATE_STATE]        = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_mrp_in_state_policies[] = {
+        [IFLA_BRIDGE_MRP_IN_STATE_IN_ID]        = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_IN_STATE_STATE]        = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_mrp_in_state);
+DEFINE_POLICY_SET(rtnl_bridge_mrp_in_state);
 
-static const NLType rtnl_bridge_mrp_start_in_test_types[] = {
-        [IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID]    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]   = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_mrp_start_in_test_policies[] = {
+        [IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID]    = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]   = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_mrp_start_in_test);
+DEFINE_POLICY_SET(rtnl_bridge_mrp_start_in_test);
 
-static const NLType rtnl_bridge_mrp_types[] = {
-        [IFLA_BRIDGE_MRP_INSTANCE]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_mrp_instance_type_system },
-        [IFLA_BRIDGE_MRP_PORT_STATE]    = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_mrp_port_state_type_system },
-        [IFLA_BRIDGE_MRP_PORT_ROLE]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_mrp_port_role_type_system },
-        [IFLA_BRIDGE_MRP_RING_STATE]    = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_mrp_ring_state_type_system },
-        [IFLA_BRIDGE_MRP_RING_ROLE]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_mrp_ring_role_type_system },
-        [IFLA_BRIDGE_MRP_START_TEST]    = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_mrp_start_test_type_system },
-        [IFLA_BRIDGE_MRP_INFO]          = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_mrp_info_type_system },
-        [IFLA_BRIDGE_MRP_IN_ROLE]       = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_mrp_in_role_type_system },
-        [IFLA_BRIDGE_MRP_IN_STATE]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_mrp_in_state_type_system },
-        [IFLA_BRIDGE_MRP_START_IN_TEST] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_mrp_start_in_test_type_system },
+static const NLAPolicy rtnl_bridge_mrp_policies[] = {
+        [IFLA_BRIDGE_MRP_INSTANCE]      = BUILD_POLICY_NESTED(rtnl_bridge_mrp_instance),
+        [IFLA_BRIDGE_MRP_PORT_STATE]    = BUILD_POLICY_NESTED(rtnl_bridge_mrp_port_state),
+        [IFLA_BRIDGE_MRP_PORT_ROLE]     = BUILD_POLICY_NESTED(rtnl_bridge_mrp_port_role),
+        [IFLA_BRIDGE_MRP_RING_STATE]    = BUILD_POLICY_NESTED(rtnl_bridge_mrp_ring_state),
+        [IFLA_BRIDGE_MRP_RING_ROLE]     = BUILD_POLICY_NESTED(rtnl_bridge_mrp_ring_role),
+        [IFLA_BRIDGE_MRP_START_TEST]    = BUILD_POLICY_NESTED(rtnl_bridge_mrp_start_test),
+        [IFLA_BRIDGE_MRP_INFO]          = BUILD_POLICY_NESTED(rtnl_bridge_mrp_info),
+        [IFLA_BRIDGE_MRP_IN_ROLE]       = BUILD_POLICY_NESTED(rtnl_bridge_mrp_in_role),
+        [IFLA_BRIDGE_MRP_IN_STATE]      = BUILD_POLICY_NESTED(rtnl_bridge_mrp_in_state),
+        [IFLA_BRIDGE_MRP_START_IN_TEST] = BUILD_POLICY_NESTED(rtnl_bridge_mrp_start_in_test),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_mrp);
+DEFINE_POLICY_SET(rtnl_bridge_mrp);
 
-static const NLType rtnl_bridge_cfm_mep_create_types[] = {
-        [IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]   = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]  = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]    = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_cfm_mep_create_policies[] = {
+        [IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE]   = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN]     = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION]  = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX]    = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_cfm_mep_create);
+DEFINE_POLICY_SET(rtnl_bridge_cfm_mep_create);
 
-static const NLType rtnl_bridge_cfm_mep_delete_types[] = {
-        [IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]   = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_cfm_mep_delete_policies[] = {
+        [IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE]   = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_cfm_mep_delete);
+DEFINE_POLICY_SET(rtnl_bridge_cfm_mep_delete);
 
-static const NLType rtnl_bridge_cfm_mep_config_types[] = {
-        [IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC] = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]       = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_cfm_mep_config_policies[] = {
+        [IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE]    = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC] = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL]     = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID]       = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_cfm_mep_config);
+DEFINE_POLICY_SET(rtnl_bridge_cfm_mep_config);
 
-static const NLType rtnl_bridge_cfm_cc_config_types[] = {
-        [IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]       = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID]     = { .type = NETLINK_TYPE_BINARY, .size = CFM_MAID_LENGTH },
+static const NLAPolicy rtnl_bridge_cfm_cc_config_policies[] = {
+        [IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE]     = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE]       = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID]     = BUILD_POLICY_WITH_SIZE(BINARY, CFM_MAID_LENGTH),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_cfm_cc_config);
+DEFINE_POLICY_SET(rtnl_bridge_cfm_cc_config);
 
-static const NLType rtnl_bridge_cfm_cc_peer_mep_types[] = {
-        [IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]  = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_PEER_MEPID]         = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_cfm_cc_peer_mep_policies[] = {
+        [IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE]  = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_PEER_MEPID]         = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_cfm_cc_peer_mep);
+DEFINE_POLICY_SET(rtnl_bridge_cfm_cc_peer_mep);
 
-static const NLType rtnl_bridge_cfm_cc_rdi_types[] = {
-        [IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]       = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_RDI_RDI]            = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_cfm_cc_rdi_policies[] = {
+        [IFLA_BRIDGE_CFM_CC_RDI_INSTANCE]       = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_RDI_RDI]            = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_cfm_cc_rdi);
+DEFINE_POLICY_SET(rtnl_bridge_cfm_cc_rdi);
 
-static const NLType rtnl_bridge_cfm_cc_ccm_tx_types[] = {
-        [IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]       = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC]           = { .type = NETLINK_TYPE_ETHER_ADDR, .size = ETH_ALEN },
-        [IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]  = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]   = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]       = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE] = { .type = NETLINK_TYPE_U8 },
+static const NLAPolicy rtnl_bridge_cfm_cc_ccm_tx_policies[] = {
+        [IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE]       = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC]           = BUILD_POLICY_WITH_SIZE(ETHER_ADDR, ETH_ALEN),
+        [IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE]  = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD]         = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV]         = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE]   = BUILD_POLICY(U8),
+        [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV]       = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE] = BUILD_POLICY(U8),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_cfm_cc_ccm_tx);
+DEFINE_POLICY_SET(rtnl_bridge_cfm_cc_ccm_tx);
 
-static const NLType rtnl_bridge_cfm_mep_status_types[] = {
-        [IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE]           = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_MEP_STATUS_OPCODE_UNEXP_SEEN]  = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_MEP_STATUS_VERSION_UNEXP_SEEN] = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_MEP_STATUS_RX_LEVEL_LOW_SEEN]  = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_cfm_mep_status_policies[] = {
+        [IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE]           = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_MEP_STATUS_OPCODE_UNEXP_SEEN]  = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_MEP_STATUS_VERSION_UNEXP_SEEN] = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_MEP_STATUS_RX_LEVEL_LOW_SEEN]  = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_cfm_mep_status);
+DEFINE_POLICY_SET(rtnl_bridge_cfm_mep_status);
 
-static const NLType rtnl_bridge_cfm_cc_peer_status_types[] = {
-        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE]       = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_CCM_DEFECT]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_RDI]            = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_PORT_TLV_VALUE] = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_IF_TLV_VALUE]   = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEEN]           = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_TLV_SEEN]       = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEQ_UNEXP_SEEN] = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_bridge_cfm_cc_peer_status_policies[] = {
+        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE]       = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID]     = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_CCM_DEFECT]     = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_RDI]            = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_PORT_TLV_VALUE] = BUILD_POLICY(U8),
+        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_IF_TLV_VALUE]   = BUILD_POLICY(U8),
+        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEEN]           = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_TLV_SEEN]       = BUILD_POLICY(U32),
+        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEQ_UNEXP_SEEN] = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_cfm_cc_peer_status);
+DEFINE_POLICY_SET(rtnl_bridge_cfm_cc_peer_status);
 
-static const NLType rtnl_bridge_cfm_types[] = {
-        [IFLA_BRIDGE_CFM_MEP_CREATE]          = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_mep_create_type_system },
-        [IFLA_BRIDGE_CFM_MEP_DELETE]          = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_mep_delete_type_system },
-        [IFLA_BRIDGE_CFM_MEP_CONFIG]          = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_mep_config_type_system },
-        [IFLA_BRIDGE_CFM_CC_CONFIG]           = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_cc_config_type_system },
-        [IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_cc_peer_mep_type_system },
-        [IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_cc_peer_mep_type_system },
-        [IFLA_BRIDGE_CFM_CC_RDI]              = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_cc_rdi_type_system },
-        [IFLA_BRIDGE_CFM_CC_CCM_TX]           = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_cc_ccm_tx_type_system },
-        [IFLA_BRIDGE_CFM_MEP_CREATE_INFO]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_mep_create_type_system },
-        [IFLA_BRIDGE_CFM_MEP_CONFIG_INFO]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_mep_config_type_system },
-        [IFLA_BRIDGE_CFM_CC_CONFIG_INFO]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_cc_config_type_system },
-        [IFLA_BRIDGE_CFM_CC_RDI_INFO]         = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_cc_rdi_type_system },
-        [IFLA_BRIDGE_CFM_CC_CCM_TX_INFO]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_cc_ccm_tx_type_system },
-        [IFLA_BRIDGE_CFM_CC_PEER_MEP_INFO]    = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_cc_peer_mep_type_system },
-        [IFLA_BRIDGE_CFM_MEP_STATUS_INFO]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_mep_status_type_system },
-        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_INFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_cc_peer_status_type_system },
+static const NLAPolicy rtnl_bridge_cfm_policies[] = {
+        [IFLA_BRIDGE_CFM_MEP_CREATE]          = BUILD_POLICY_NESTED(rtnl_bridge_cfm_mep_create),
+        [IFLA_BRIDGE_CFM_MEP_DELETE]          = BUILD_POLICY_NESTED(rtnl_bridge_cfm_mep_delete),
+        [IFLA_BRIDGE_CFM_MEP_CONFIG]          = BUILD_POLICY_NESTED(rtnl_bridge_cfm_mep_config),
+        [IFLA_BRIDGE_CFM_CC_CONFIG]           = BUILD_POLICY_NESTED(rtnl_bridge_cfm_cc_config),
+        [IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD]     = BUILD_POLICY_NESTED(rtnl_bridge_cfm_cc_peer_mep),
+        [IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE]  = BUILD_POLICY_NESTED(rtnl_bridge_cfm_cc_peer_mep),
+        [IFLA_BRIDGE_CFM_CC_RDI]              = BUILD_POLICY_NESTED(rtnl_bridge_cfm_cc_rdi),
+        [IFLA_BRIDGE_CFM_CC_CCM_TX]           = BUILD_POLICY_NESTED(rtnl_bridge_cfm_cc_ccm_tx),
+        [IFLA_BRIDGE_CFM_MEP_CREATE_INFO]     = BUILD_POLICY_NESTED(rtnl_bridge_cfm_mep_create),
+        [IFLA_BRIDGE_CFM_MEP_CONFIG_INFO]     = BUILD_POLICY_NESTED(rtnl_bridge_cfm_mep_config),
+        [IFLA_BRIDGE_CFM_CC_CONFIG_INFO]      = BUILD_POLICY_NESTED(rtnl_bridge_cfm_cc_config),
+        [IFLA_BRIDGE_CFM_CC_RDI_INFO]         = BUILD_POLICY_NESTED(rtnl_bridge_cfm_cc_rdi),
+        [IFLA_BRIDGE_CFM_CC_CCM_TX_INFO]      = BUILD_POLICY_NESTED(rtnl_bridge_cfm_cc_ccm_tx),
+        [IFLA_BRIDGE_CFM_CC_PEER_MEP_INFO]    = BUILD_POLICY_NESTED(rtnl_bridge_cfm_cc_peer_mep),
+        [IFLA_BRIDGE_CFM_MEP_STATUS_INFO]     = BUILD_POLICY_NESTED(rtnl_bridge_cfm_mep_status),
+        [IFLA_BRIDGE_CFM_CC_PEER_STATUS_INFO] = BUILD_POLICY_NESTED(rtnl_bridge_cfm_cc_peer_status),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_bridge_cfm);
+DEFINE_POLICY_SET(rtnl_bridge_cfm);
 
-static const NLType rtnl_af_spec_bridge_types[] = {
-        [IFLA_BRIDGE_FLAGS]            = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRIDGE_MODE]             = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRIDGE_VLAN_INFO]        = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct bridge_vlan_info) },
-        [IFLA_BRIDGE_VLAN_TUNNEL_INFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_vlan_tunnel_info_type_system },
-        [IFLA_BRIDGE_MRP]              = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_mrp_type_system },
-        [IFLA_BRIDGE_CFM]              = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bridge_cfm_type_system },
+static const NLAPolicy rtnl_af_spec_bridge_policies[] = {
+        [IFLA_BRIDGE_FLAGS]            = BUILD_POLICY(U16),
+        [IFLA_BRIDGE_MODE]             = BUILD_POLICY(U16),
+        [IFLA_BRIDGE_VLAN_INFO]        = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct bridge_vlan_info)),
+        [IFLA_BRIDGE_VLAN_TUNNEL_INFO] = BUILD_POLICY_NESTED(rtnl_bridge_vlan_tunnel_info),
+        [IFLA_BRIDGE_MRP]              = BUILD_POLICY_NESTED(rtnl_bridge_mrp),
+        [IFLA_BRIDGE_CFM]              = BUILD_POLICY_NESTED(rtnl_bridge_cfm),
 };
 
-static const NLTypeSystemUnionElement rtnl_af_spec_type_systems[] = {
-        { .protocol = AF_UNSPEC, .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_af_spec_unspec), },
-        { .protocol = AF_BRIDGE, .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_af_spec_bridge), },
+static const NLAPolicySetUnionElement rtnl_af_spec_policy_set_union_elements[] = {
+        BUILD_UNION_ELEMENT_BY_FAMILY(AF_UNSPEC, rtnl_af_spec_unspec),
+        BUILD_UNION_ELEMENT_BY_FAMILY(AF_BRIDGE, rtnl_af_spec_bridge),
 };
 
-DEFINE_TYPE_SYSTEM_UNION_MATCH_PROTOCOL(rtnl_af_spec);
+DEFINE_POLICY_SET_UNION(rtnl_af_spec, 0);
 
-static const NLType rtnl_prop_list_types[] = {
-        [IFLA_ALT_IFNAME]       = { .type = NETLINK_TYPE_STRING, .size = ALTIFNAMSIZ - 1 },
+static const NLAPolicy rtnl_prop_list_policies[] = {
+        [IFLA_ALT_IFNAME]       = BUILD_POLICY_WITH_SIZE(STRING, ALTIFNAMSIZ - 1),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_prop_list);
+DEFINE_POLICY_SET(rtnl_prop_list);
 
-static const NLType rtnl_vf_vlan_list_types[] = {
-        [IFLA_VF_VLAN_INFO]  = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vf_vlan_info) },
+static const NLAPolicy rtnl_vf_vlan_list_policies[] = {
+        [IFLA_VF_VLAN_INFO]  = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vf_vlan_info)),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_vf_vlan_list);
+DEFINE_POLICY_SET(rtnl_vf_vlan_list);
 
-static const NLType rtnl_vf_info_types[] = {
-        [IFLA_VF_MAC]           = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vf_mac) },
-        [IFLA_VF_VLAN]          = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vf_vlan) },
-        [IFLA_VF_VLAN_LIST]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vf_vlan_list_type_system },
-        [IFLA_VF_TX_RATE]       = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vf_tx_rate) },
-        [IFLA_VF_SPOOFCHK]      = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vf_spoofchk) },
-        [IFLA_VF_RATE]          = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vf_rate) },
-        [IFLA_VF_LINK_STATE]    = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vf_link_state) },
-        [IFLA_VF_RSS_QUERY_EN]  = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vf_rss_query_en) },
-        [IFLA_VF_TRUST]         = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vf_trust) },
-        [IFLA_VF_IB_NODE_GUID]  = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vf_guid) },
-        [IFLA_VF_IB_PORT_GUID]  = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_vf_guid) },
+static const NLAPolicy rtnl_vf_info_policies[] = {
+        [IFLA_VF_MAC]           = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vf_mac)),
+        [IFLA_VF_VLAN]          = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vf_vlan)),
+        [IFLA_VF_VLAN_LIST]     = BUILD_POLICY_NESTED(rtnl_vf_vlan_list),
+        [IFLA_VF_TX_RATE]       = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vf_tx_rate)),
+        [IFLA_VF_SPOOFCHK]      = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vf_spoofchk)),
+        [IFLA_VF_RATE]          = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vf_rate)),
+        [IFLA_VF_LINK_STATE]    = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vf_link_state)),
+        [IFLA_VF_RSS_QUERY_EN]  = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vf_rss_query_en)),
+        [IFLA_VF_TRUST]         = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vf_trust)),
+        [IFLA_VF_IB_NODE_GUID]  = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vf_guid)),
+        [IFLA_VF_IB_PORT_GUID]  = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_vf_guid)),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_vf_info);
+DEFINE_POLICY_SET(rtnl_vf_info);
 
-static const NLType rtnl_vfinfo_list_types[] = {
-        [IFLA_VF_INFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vf_info_type_system },
+static const NLAPolicy rtnl_vfinfo_list_policies[] = {
+        [IFLA_VF_INFO] = BUILD_POLICY_NESTED(rtnl_vf_info),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_vfinfo_list);
+DEFINE_POLICY_SET(rtnl_vfinfo_list);
 
-static const NLType rtnl_vf_port_types[] = {
-        [IFLA_PORT_VF]            = { .type = NETLINK_TYPE_U32 },
-        [IFLA_PORT_PROFILE]       = { .type = NETLINK_TYPE_STRING },
-        [IFLA_PORT_VSI_TYPE]      = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct ifla_port_vsi) },
-        [IFLA_PORT_INSTANCE_UUID] = { .type = NETLINK_TYPE_BINARY, .size = PORT_UUID_MAX },
-        [IFLA_PORT_HOST_UUID]     = { .type = NETLINK_TYPE_BINARY, .size = PORT_UUID_MAX },
-        [IFLA_PORT_REQUEST]       = { .type = NETLINK_TYPE_U8 },
-        [IFLA_PORT_RESPONSE]      = { .type = NETLINK_TYPE_U16 },
+static const NLAPolicy rtnl_vf_port_policies[] = {
+        [IFLA_PORT_VF]            = BUILD_POLICY(U32),
+        [IFLA_PORT_PROFILE]       = BUILD_POLICY(STRING),
+        [IFLA_PORT_VSI_TYPE]      = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct ifla_port_vsi)),
+        [IFLA_PORT_INSTANCE_UUID] = BUILD_POLICY_WITH_SIZE(BINARY, PORT_UUID_MAX),
+        [IFLA_PORT_HOST_UUID]     = BUILD_POLICY_WITH_SIZE(BINARY, PORT_UUID_MAX),
+        [IFLA_PORT_REQUEST]       = BUILD_POLICY(U8),
+        [IFLA_PORT_RESPONSE]      = BUILD_POLICY(U16),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_vf_port);
+DEFINE_POLICY_SET(rtnl_vf_port);
 
-static const NLType rtnl_vf_ports_types[] = {
-        [IFLA_VF_PORT] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vf_port_type_system },
+static const NLAPolicy rtnl_vf_ports_policies[] = {
+        [IFLA_VF_PORT] = BUILD_POLICY_NESTED(rtnl_vf_port),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_vf_ports);
+DEFINE_POLICY_SET(rtnl_vf_ports);
 
-static const NLType rtnl_xdp_types[] = {
-        [IFLA_XDP_FD]          = { .type = NETLINK_TYPE_S32 },
-        [IFLA_XDP_ATTACHED]    = { .type = NETLINK_TYPE_U8 },
-        [IFLA_XDP_FLAGS]       = { .type = NETLINK_TYPE_U32 },
-        [IFLA_XDP_PROG_ID]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_XDP_DRV_PROG_ID] = { .type = NETLINK_TYPE_U32 },
-        [IFLA_XDP_SKB_PROG_ID] = { .type = NETLINK_TYPE_U32 },
-        [IFLA_XDP_HW_PROG_ID]  = { .type = NETLINK_TYPE_U32 },
-        [IFLA_XDP_EXPECTED_FD] = { .type = NETLINK_TYPE_S32 },
+static const NLAPolicy rtnl_xdp_policies[] = {
+        [IFLA_XDP_FD]          = BUILD_POLICY(S32),
+        [IFLA_XDP_ATTACHED]    = BUILD_POLICY(U8),
+        [IFLA_XDP_FLAGS]       = BUILD_POLICY(U32),
+        [IFLA_XDP_PROG_ID]     = BUILD_POLICY(U32),
+        [IFLA_XDP_DRV_PROG_ID] = BUILD_POLICY(U32),
+        [IFLA_XDP_SKB_PROG_ID] = BUILD_POLICY(U32),
+        [IFLA_XDP_HW_PROG_ID]  = BUILD_POLICY(U32),
+        [IFLA_XDP_EXPECTED_FD] = BUILD_POLICY(S32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_xdp);
+DEFINE_POLICY_SET(rtnl_xdp);
 
-static const NLType rtnl_proto_down_reason_types[] = {
-        [IFLA_PROTO_DOWN_REASON_MASK]  = { .type = NETLINK_TYPE_U32 },
-        [IFLA_PROTO_DOWN_REASON_VALUE] = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_proto_down_reason_policies[] = {
+        [IFLA_PROTO_DOWN_REASON_MASK]  = BUILD_POLICY(U32),
+        [IFLA_PROTO_DOWN_REASON_VALUE] = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_proto_down_reason);
+DEFINE_POLICY_SET(rtnl_proto_down_reason);
 
-static const NLType rtnl_link_types[] = {
-        [IFLA_ADDRESS]             = { .type = NETLINK_TYPE_ETHER_ADDR },
-        [IFLA_BROADCAST]           = { .type = NETLINK_TYPE_ETHER_ADDR },
-        [IFLA_IFNAME]              = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
-        [IFLA_MTU]                 = { .type = NETLINK_TYPE_U32 },
-        [IFLA_LINK]                = { .type = NETLINK_TYPE_U32 },
-        [IFLA_QDISC]               = { .type = NETLINK_TYPE_STRING },
-        [IFLA_STATS]               = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct rtnl_link_stats) },
+static const NLAPolicy rtnl_link_policies[] = {
+        [IFLA_ADDRESS]             = BUILD_POLICY(ETHER_ADDR),
+        [IFLA_BROADCAST]           = BUILD_POLICY(ETHER_ADDR),
+        [IFLA_IFNAME]              = BUILD_POLICY_WITH_SIZE(STRING, IFNAMSIZ - 1),
+        [IFLA_MTU]                 = BUILD_POLICY(U32),
+        [IFLA_LINK]                = BUILD_POLICY(U32),
+        [IFLA_QDISC]               = BUILD_POLICY(STRING),
+        [IFLA_STATS]               = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct rtnl_link_stats)),
         [IFLA_COST]                = { /* Not used. */ },
         [IFLA_PRIORITY]            = { /* Not used. */ },
-        [IFLA_MASTER]              = { .type = NETLINK_TYPE_U32 },
+        [IFLA_MASTER]              = BUILD_POLICY(U32),
         [IFLA_WIRELESS]            = { /* Used only by wext. */ },
-        [IFLA_PROTINFO]            = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_prot_info_type_system_union },
-        [IFLA_TXQLEN]              = { .type = NETLINK_TYPE_U32 },
-        [IFLA_MAP]                 = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct rtnl_link_ifmap) },
-        [IFLA_WEIGHT]              = { .type = NETLINK_TYPE_U32 },
-        [IFLA_OPERSTATE]           = { .type = NETLINK_TYPE_U8 },
-        [IFLA_LINKMODE]            = { .type = NETLINK_TYPE_U8 },
-        [IFLA_LINKINFO]            = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_info_type_system },
-        [IFLA_NET_NS_PID]          = { .type = NETLINK_TYPE_U32 },
-        [IFLA_IFALIAS]             = { .type = NETLINK_TYPE_STRING, .size = IFALIASZ - 1 },
-        [IFLA_NUM_VF]              = { .type = NETLINK_TYPE_U32 },
-        [IFLA_VFINFO_LIST]         = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vfinfo_list_type_system },
-        [IFLA_STATS64]             = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct rtnl_link_stats64) },
-        [IFLA_VF_PORTS]            = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vf_ports_type_system },
-        [IFLA_PORT_SELF]           = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vf_port_type_system },
-        [IFLA_AF_SPEC]             = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_af_spec_type_system_union },
-        [IFLA_GROUP]               = { .type = NETLINK_TYPE_U32 },
-        [IFLA_NET_NS_FD]           = { .type = NETLINK_TYPE_U32 },
-        [IFLA_EXT_MASK]            = { .type = NETLINK_TYPE_U32 },
-        [IFLA_PROMISCUITY]         = { .type = NETLINK_TYPE_U32 },
-        [IFLA_NUM_TX_QUEUES]       = { .type = NETLINK_TYPE_U32 },
-        [IFLA_NUM_RX_QUEUES]       = { .type = NETLINK_TYPE_U32 },
-        [IFLA_CARRIER]             = { .type = NETLINK_TYPE_U8 },
-        [IFLA_PHYS_PORT_ID]        = { .type = NETLINK_TYPE_BINARY, .size = MAX_PHYS_ITEM_ID_LEN },
-        [IFLA_CARRIER_CHANGES]     = { .type = NETLINK_TYPE_U32 },
-        [IFLA_PHYS_SWITCH_ID]      = { .type = NETLINK_TYPE_BINARY, .size = MAX_PHYS_ITEM_ID_LEN },
-        [IFLA_LINK_NETNSID]        = { .type = NETLINK_TYPE_S32 },
-        [IFLA_PHYS_PORT_NAME]      = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
-        [IFLA_PROTO_DOWN]          = { .type = NETLINK_TYPE_U8 },
-        [IFLA_GSO_MAX_SEGS]        = { .type = NETLINK_TYPE_U32 },
-        [IFLA_GSO_MAX_SIZE]        = { .type = NETLINK_TYPE_U32 },
-        [IFLA_XDP]                 = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_xdp_type_system },
-        [IFLA_EVENT]               = { .type = NETLINK_TYPE_U32 },
-        [IFLA_NEW_NETNSID]         = { .type = NETLINK_TYPE_S32 },
-        [IFLA_TARGET_NETNSID]      = { .type = NETLINK_TYPE_S32 },
-        [IFLA_CARRIER_UP_COUNT]    = { .type = NETLINK_TYPE_U32 },
-        [IFLA_CARRIER_DOWN_COUNT]  = { .type = NETLINK_TYPE_U32 },
-        [IFLA_NEW_IFINDEX]         = { .type = NETLINK_TYPE_S32 },
-        [IFLA_MIN_MTU]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_MAX_MTU]             = { .type = NETLINK_TYPE_U32 },
-        [IFLA_PROP_LIST]           = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_prop_list_type_system },
-        [IFLA_ALT_IFNAME]          = { .type = NETLINK_TYPE_STRING, .size = ALTIFNAMSIZ - 1 },
-        [IFLA_PERM_ADDRESS]        = { .type = NETLINK_TYPE_ETHER_ADDR },
-        [IFLA_PROTO_DOWN_REASON]   = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_proto_down_reason_type_system },
-        [IFLA_PARENT_DEV_NAME]     = { .type = NETLINK_TYPE_STRING, },
-        [IFLA_PARENT_DEV_BUS_NAME] = { .type = NETLINK_TYPE_STRING, },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_link);
+        [IFLA_PROTINFO]            = BUILD_POLICY_NESTED_UNION_BY_FAMILY(rtnl_prot_info),
+        [IFLA_TXQLEN]              = BUILD_POLICY(U32),
+        [IFLA_MAP]                 = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct rtnl_link_ifmap)),
+        [IFLA_WEIGHT]              = BUILD_POLICY(U32),
+        [IFLA_OPERSTATE]           = BUILD_POLICY(U8),
+        [IFLA_LINKMODE]            = BUILD_POLICY(U8),
+        [IFLA_LINKINFO]            = BUILD_POLICY_NESTED(rtnl_link_info),
+        [IFLA_NET_NS_PID]          = BUILD_POLICY(U32),
+        [IFLA_IFALIAS]             = BUILD_POLICY_WITH_SIZE(STRING, IFALIASZ - 1),
+        [IFLA_NUM_VF]              = BUILD_POLICY(U32),
+        [IFLA_VFINFO_LIST]         = BUILD_POLICY_NESTED(rtnl_vfinfo_list),
+        [IFLA_STATS64]             = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct rtnl_link_stats64)),
+        [IFLA_VF_PORTS]            = BUILD_POLICY_NESTED(rtnl_vf_ports),
+        [IFLA_PORT_SELF]           = BUILD_POLICY_NESTED(rtnl_vf_port),
+        [IFLA_AF_SPEC]             = BUILD_POLICY_NESTED_UNION_BY_FAMILY(rtnl_af_spec),
+        [IFLA_GROUP]               = BUILD_POLICY(U32),
+        [IFLA_NET_NS_FD]           = BUILD_POLICY(U32),
+        [IFLA_EXT_MASK]            = BUILD_POLICY(U32),
+        [IFLA_PROMISCUITY]         = BUILD_POLICY(U32),
+        [IFLA_NUM_TX_QUEUES]       = BUILD_POLICY(U32),
+        [IFLA_NUM_RX_QUEUES]       = BUILD_POLICY(U32),
+        [IFLA_CARRIER]             = BUILD_POLICY(U8),
+        [IFLA_PHYS_PORT_ID]        = BUILD_POLICY_WITH_SIZE(BINARY, MAX_PHYS_ITEM_ID_LEN),
+        [IFLA_CARRIER_CHANGES]     = BUILD_POLICY(U32),
+        [IFLA_PHYS_SWITCH_ID]      = BUILD_POLICY_WITH_SIZE(BINARY, MAX_PHYS_ITEM_ID_LEN),
+        [IFLA_LINK_NETNSID]        = BUILD_POLICY(S32),
+        [IFLA_PHYS_PORT_NAME]      = BUILD_POLICY_WITH_SIZE(STRING, IFNAMSIZ - 1),
+        [IFLA_PROTO_DOWN]          = BUILD_POLICY(U8),
+        [IFLA_GSO_MAX_SEGS]        = BUILD_POLICY(U32),
+        [IFLA_GSO_MAX_SIZE]        = BUILD_POLICY(U32),
+        [IFLA_XDP]                 = BUILD_POLICY_NESTED(rtnl_xdp),
+        [IFLA_EVENT]               = BUILD_POLICY(U32),
+        [IFLA_NEW_NETNSID]         = BUILD_POLICY(S32),
+        [IFLA_TARGET_NETNSID]      = BUILD_POLICY(S32),
+        [IFLA_CARRIER_UP_COUNT]    = BUILD_POLICY(U32),
+        [IFLA_CARRIER_DOWN_COUNT]  = BUILD_POLICY(U32),
+        [IFLA_NEW_IFINDEX]         = BUILD_POLICY(S32),
+        [IFLA_MIN_MTU]             = BUILD_POLICY(U32),
+        [IFLA_MAX_MTU]             = BUILD_POLICY(U32),
+        [IFLA_PROP_LIST]           = BUILD_POLICY_NESTED(rtnl_prop_list),
+        [IFLA_ALT_IFNAME]          = BUILD_POLICY_WITH_SIZE(STRING, ALTIFNAMSIZ - 1),
+        [IFLA_PERM_ADDRESS]        = BUILD_POLICY(ETHER_ADDR),
+        [IFLA_PROTO_DOWN_REASON]   = BUILD_POLICY_NESTED(rtnl_proto_down_reason),
+        [IFLA_PARENT_DEV_NAME]     = BUILD_POLICY(STRING),
+        [IFLA_PARENT_DEV_BUS_NAME] = BUILD_POLICY(STRING),
+};
+
+DEFINE_POLICY_SET(rtnl_link);
 
 /* IFA_FLAGS was defined in kernel 3.14, but we still support older
  * kernels where IFA_MAX is lower. */
-static const NLType rtnl_address_types[] = {
-        [IFA_ADDRESS]           = { .type = NETLINK_TYPE_IN_ADDR },
-        [IFA_LOCAL]             = { .type = NETLINK_TYPE_IN_ADDR },
-        [IFA_LABEL]             = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
-        [IFA_BROADCAST]         = { .type = NETLINK_TYPE_IN_ADDR },
-        [IFA_ANYCAST]           = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
-        [IFA_CACHEINFO]         = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) },
-        [IFA_MULTICAST]         = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
-        [IFA_FLAGS]             = { .type = NETLINK_TYPE_U32 },
-        [IFA_RT_PRIORITY]       = { .type = NETLINK_TYPE_U32 },
-        [IFA_TARGET_NETNSID]    = { .type = NETLINK_TYPE_S32 },
+static const NLAPolicy rtnl_address_policies[] = {
+        [IFA_ADDRESS]           = BUILD_POLICY(IN_ADDR),
+        [IFA_LOCAL]             = BUILD_POLICY(IN_ADDR),
+        [IFA_LABEL]             = BUILD_POLICY_WITH_SIZE(STRING, IFNAMSIZ - 1),
+        [IFA_BROADCAST]         = BUILD_POLICY(IN_ADDR),
+        [IFA_ANYCAST]           = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)),
+        [IFA_CACHEINFO]         = BUILD_POLICY_WITH_SIZE(CACHE_INFO, sizeof(struct ifa_cacheinfo)),
+        [IFA_MULTICAST]         = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)),
+        [IFA_FLAGS]             = BUILD_POLICY(U32),
+        [IFA_RT_PRIORITY]       = BUILD_POLICY(U32),
+        [IFA_TARGET_NETNSID]    = BUILD_POLICY(S32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_address);
+DEFINE_POLICY_SET(rtnl_address);
 
 /* RTM_METRICS --- array of struct rtattr with types of RTAX_* */
 
-static const NLType rtnl_route_metrics_types[] = {
-        [RTAX_MTU]                = { .type = NETLINK_TYPE_U32 },
-        [RTAX_WINDOW]             = { .type = NETLINK_TYPE_U32 },
-        [RTAX_RTT]                = { .type = NETLINK_TYPE_U32 },
-        [RTAX_RTTVAR]             = { .type = NETLINK_TYPE_U32 },
-        [RTAX_SSTHRESH]           = { .type = NETLINK_TYPE_U32 },
-        [RTAX_CWND]               = { .type = NETLINK_TYPE_U32 },
-        [RTAX_ADVMSS]             = { .type = NETLINK_TYPE_U32 },
-        [RTAX_REORDERING]         = { .type = NETLINK_TYPE_U32 },
-        [RTAX_HOPLIMIT]           = { .type = NETLINK_TYPE_U32 },
-        [RTAX_INITCWND]           = { .type = NETLINK_TYPE_U32 },
-        [RTAX_FEATURES]           = { .type = NETLINK_TYPE_U32 },
-        [RTAX_RTO_MIN]            = { .type = NETLINK_TYPE_U32 },
-        [RTAX_INITRWND]           = { .type = NETLINK_TYPE_U32 },
-        [RTAX_QUICKACK]           = { .type = NETLINK_TYPE_U32 },
-        [RTAX_CC_ALGO]            = { .type = NETLINK_TYPE_U32 },
-        [RTAX_FASTOPEN_NO_COOKIE] = { .type = NETLINK_TYPE_U32 },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_route_metrics);
-
-static const NLType rtnl_route_types[] = {
-        [RTA_DST]               = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
-        [RTA_SRC]               = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
-        [RTA_IIF]               = { .type = NETLINK_TYPE_U32 },
-        [RTA_OIF]               = { .type = NETLINK_TYPE_U32 },
-        [RTA_GATEWAY]           = { .type = NETLINK_TYPE_IN_ADDR },
-        [RTA_PRIORITY]          = { .type = NETLINK_TYPE_U32 },
-        [RTA_PREFSRC]           = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
-        [RTA_METRICS]           = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_metrics_type_system },
-        [RTA_MULTIPATH]         = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct rtnexthop) },
-        [RTA_FLOW]              = { .type = NETLINK_TYPE_U32 }, /* 6? */
-        [RTA_CACHEINFO]         = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct rta_cacheinfo) },
-        [RTA_TABLE]             = { .type = NETLINK_TYPE_U32 },
-        [RTA_MARK]              = { .type = NETLINK_TYPE_U32 },
-        [RTA_MFC_STATS]         = { .type = NETLINK_TYPE_U64 },
-        [RTA_VIA]               = { /* See struct rtvia */ },
-        [RTA_NEWDST]            = { .type = NETLINK_TYPE_U32 },
-        [RTA_PREF]              = { .type = NETLINK_TYPE_U8 },
-        [RTA_ENCAP_TYPE]        = { .type = NETLINK_TYPE_U16 },
+static const NLAPolicy rtnl_route_metrics_policies[] = {
+        [RTAX_MTU]                = BUILD_POLICY(U32),
+        [RTAX_WINDOW]             = BUILD_POLICY(U32),
+        [RTAX_RTT]                = BUILD_POLICY(U32),
+        [RTAX_RTTVAR]             = BUILD_POLICY(U32),
+        [RTAX_SSTHRESH]           = BUILD_POLICY(U32),
+        [RTAX_CWND]               = BUILD_POLICY(U32),
+        [RTAX_ADVMSS]             = BUILD_POLICY(U32),
+        [RTAX_REORDERING]         = BUILD_POLICY(U32),
+        [RTAX_HOPLIMIT]           = BUILD_POLICY(U32),
+        [RTAX_INITCWND]           = BUILD_POLICY(U32),
+        [RTAX_FEATURES]           = BUILD_POLICY(U32),
+        [RTAX_RTO_MIN]            = BUILD_POLICY(U32),
+        [RTAX_INITRWND]           = BUILD_POLICY(U32),
+        [RTAX_QUICKACK]           = BUILD_POLICY(U32),
+        [RTAX_CC_ALGO]            = BUILD_POLICY(U32),
+        [RTAX_FASTOPEN_NO_COOKIE] = BUILD_POLICY(U32),
+};
+
+DEFINE_POLICY_SET(rtnl_route_metrics);
+
+static const NLAPolicy rtnl_route_policies[] = {
+        [RTA_DST]               = BUILD_POLICY(IN_ADDR),
+        [RTA_SRC]               = BUILD_POLICY(IN_ADDR),
+        [RTA_IIF]               = BUILD_POLICY(U32),
+        [RTA_OIF]               = BUILD_POLICY(U32),
+        [RTA_GATEWAY]           = BUILD_POLICY(IN_ADDR),
+        [RTA_PRIORITY]          = BUILD_POLICY(U32),
+        [RTA_PREFSRC]           = BUILD_POLICY(IN_ADDR),
+        [RTA_METRICS]           = BUILD_POLICY_NESTED(rtnl_route_metrics),
+        [RTA_MULTIPATH]         = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct rtnexthop)),
+        [RTA_FLOW]              = BUILD_POLICY(U32),
+        [RTA_CACHEINFO]         = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct rta_cacheinfo)),
+        [RTA_TABLE]             = BUILD_POLICY(U32),
+        [RTA_MARK]              = BUILD_POLICY(U32),
+        [RTA_MFC_STATS]         = BUILD_POLICY(U64),
+        [RTA_VIA]               = BUILD_POLICY(BINARY), /* See struct rtvia */
+        [RTA_NEWDST]            = BUILD_POLICY(U32),
+        [RTA_PREF]              = BUILD_POLICY(U8),
+        [RTA_ENCAP_TYPE]        = BUILD_POLICY(U16),
         [RTA_ENCAP]             = { .type = NETLINK_TYPE_NESTED }, /* Multiple type systems i.e. LWTUNNEL_ENCAP_MPLS/LWTUNNEL_ENCAP_IP/LWTUNNEL_ENCAP_ILA etc... */
-        [RTA_EXPIRES]           = { .type = NETLINK_TYPE_U32 },
-        [RTA_UID]               = { .type = NETLINK_TYPE_U32 },
-        [RTA_TTL_PROPAGATE]     = { .type = NETLINK_TYPE_U8 },
-        [RTA_IP_PROTO]          = { .type = NETLINK_TYPE_U8 },
-        [RTA_SPORT]             = { .type = NETLINK_TYPE_U16 },
-        [RTA_DPORT]             = { .type = NETLINK_TYPE_U16 },
-        [RTA_NH_ID]             = { .type = NETLINK_TYPE_U32 },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_route);
-
-static const NLType rtnl_neigh_types[] = {
-        [NDA_DST]               = { .type = NETLINK_TYPE_IN_ADDR },
-        [NDA_LLADDR]            = { .type = NETLINK_TYPE_ETHER_ADDR },
-        [NDA_CACHEINFO]         = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) },
-        [NDA_PROBES]            = { .type = NETLINK_TYPE_U32 },
-        [NDA_VLAN]              = { .type = NETLINK_TYPE_U16 },
-        [NDA_PORT]              = { .type = NETLINK_TYPE_U16 },
-        [NDA_VNI]               = { .type = NETLINK_TYPE_U32 },
-        [NDA_IFINDEX]           = { .type = NETLINK_TYPE_U32 },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_neigh);
-
-static const NLType rtnl_addrlabel_types[] = {
-        [IFAL_ADDRESS]         = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
-        [IFAL_LABEL]           = { .type = NETLINK_TYPE_U32 },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_addrlabel);
-
-static const NLType rtnl_routing_policy_rule_types[] = {
-        [FRA_DST]                 = { .type = NETLINK_TYPE_IN_ADDR },
-        [FRA_SRC]                 = { .type = NETLINK_TYPE_IN_ADDR },
-        [FRA_IIFNAME]             = { .type = NETLINK_TYPE_STRING },
-        [FRA_GOTO]                = { .type = NETLINK_TYPE_U32 },
-        [FRA_PRIORITY]            = { .type = NETLINK_TYPE_U32 },
-        [FRA_FWMARK]              = { .type = NETLINK_TYPE_U32 },
-        [FRA_FLOW]                = { .type = NETLINK_TYPE_U32 },
-        [FRA_TUN_ID]              = { .type = NETLINK_TYPE_U64 },
-        [FRA_SUPPRESS_IFGROUP]    = { .type = NETLINK_TYPE_U32 },
-        [FRA_SUPPRESS_PREFIXLEN]  = { .type = NETLINK_TYPE_U32 },
-        [FRA_TABLE]               = { .type = NETLINK_TYPE_U32 },
-        [FRA_FWMASK]              = { .type = NETLINK_TYPE_U32 },
-        [FRA_OIFNAME]             = { .type = NETLINK_TYPE_STRING },
-        [FRA_PAD]                 = { .type = NETLINK_TYPE_U32 },
-        [FRA_L3MDEV]              = { .type = NETLINK_TYPE_U8 },
-        [FRA_UID_RANGE]           = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct fib_rule_uid_range) },
-        [FRA_PROTOCOL]            = { .type = NETLINK_TYPE_U8 },
-        [FRA_IP_PROTO]            = { .type = NETLINK_TYPE_U8 },
-        [FRA_SPORT_RANGE]         = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct fib_rule_port_range) },
-        [FRA_DPORT_RANGE]         = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct fib_rule_port_range) },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_routing_policy_rule);
-
-static const NLType rtnl_nexthop_types[] = {
-        [NHA_ID]                  = { .type = NETLINK_TYPE_U32 },
+        [RTA_EXPIRES]           = BUILD_POLICY(U32),
+        [RTA_UID]               = BUILD_POLICY(U32),
+        [RTA_TTL_PROPAGATE]     = BUILD_POLICY(U8),
+        [RTA_IP_PROTO]          = BUILD_POLICY(U8),
+        [RTA_SPORT]             = BUILD_POLICY(U16),
+        [RTA_DPORT]             = BUILD_POLICY(U16),
+        [RTA_NH_ID]             = BUILD_POLICY(U32),
+};
+
+DEFINE_POLICY_SET(rtnl_route);
+
+static const NLAPolicy rtnl_neigh_policies[] = {
+        [NDA_DST]               = BUILD_POLICY(IN_ADDR),
+        [NDA_LLADDR]            = BUILD_POLICY(ETHER_ADDR),
+        [NDA_CACHEINFO]         = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct nda_cacheinfo)),
+        [NDA_PROBES]            = BUILD_POLICY(U32),
+        [NDA_VLAN]              = BUILD_POLICY(U16),
+        [NDA_PORT]              = BUILD_POLICY(U16),
+        [NDA_VNI]               = BUILD_POLICY(U32),
+        [NDA_IFINDEX]           = BUILD_POLICY(U32),
+};
+
+DEFINE_POLICY_SET(rtnl_neigh);
+
+static const NLAPolicy rtnl_addrlabel_policies[] = {
+        [IFAL_ADDRESS]         = BUILD_POLICY_WITH_SIZE(IN_ADDR, sizeof(struct in6_addr)),
+        [IFAL_LABEL]           = BUILD_POLICY(U32),
+};
+
+DEFINE_POLICY_SET(rtnl_addrlabel);
+
+static const NLAPolicy rtnl_routing_policy_rule_policies[] = {
+        [FRA_DST]                 = BUILD_POLICY(IN_ADDR),
+        [FRA_SRC]                 = BUILD_POLICY(IN_ADDR),
+        [FRA_IIFNAME]             = BUILD_POLICY(STRING),
+        [FRA_GOTO]                = BUILD_POLICY(U32),
+        [FRA_PRIORITY]            = BUILD_POLICY(U32),
+        [FRA_FWMARK]              = BUILD_POLICY(U32),
+        [FRA_FLOW]                = BUILD_POLICY(U32),
+        [FRA_TUN_ID]              = BUILD_POLICY(U64),
+        [FRA_SUPPRESS_IFGROUP]    = BUILD_POLICY(U32),
+        [FRA_SUPPRESS_PREFIXLEN]  = BUILD_POLICY(U32),
+        [FRA_TABLE]               = BUILD_POLICY(U32),
+        [FRA_FWMASK]              = BUILD_POLICY(U32),
+        [FRA_OIFNAME]             = BUILD_POLICY(STRING),
+        [FRA_PAD]                 = BUILD_POLICY(U32),
+        [FRA_L3MDEV]              = BUILD_POLICY(U8),
+        [FRA_UID_RANGE]           = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct fib_rule_uid_range)),
+        [FRA_PROTOCOL]            = BUILD_POLICY(U8),
+        [FRA_IP_PROTO]            = BUILD_POLICY(U8),
+        [FRA_SPORT_RANGE]         = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct fib_rule_port_range)),
+        [FRA_DPORT_RANGE]         = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct fib_rule_port_range)),
+};
+
+DEFINE_POLICY_SET(rtnl_routing_policy_rule);
+
+static const NLAPolicy rtnl_nexthop_policies[] = {
+        [NHA_ID]                  = BUILD_POLICY(U32),
         [NHA_GROUP]               = { /* array of struct nexthop_grp */ },
-        [NHA_GROUP_TYPE]          = { .type = NETLINK_TYPE_U16 },
-        [NHA_BLACKHOLE]           = { .type = NETLINK_TYPE_FLAG },
-        [NHA_OIF]                 = { .type = NETLINK_TYPE_U32 },
-        [NHA_GATEWAY]             = { .type = NETLINK_TYPE_IN_ADDR },
-        [NHA_ENCAP_TYPE]          = { .type = NETLINK_TYPE_U16 },
+        [NHA_GROUP_TYPE]          = BUILD_POLICY(U16),
+        [NHA_BLACKHOLE]           = BUILD_POLICY(FLAG),
+        [NHA_OIF]                 = BUILD_POLICY(U32),
+        [NHA_GATEWAY]             = BUILD_POLICY(IN_ADDR),
+        [NHA_ENCAP_TYPE]          = BUILD_POLICY(U16),
         [NHA_ENCAP]               = { .type = NETLINK_TYPE_NESTED },
-        [NHA_GROUPS]              = { .type = NETLINK_TYPE_FLAG },
-        [NHA_MASTER]              = { .type = NETLINK_TYPE_U32 },
-        [NHA_FDB]                 = { .type = NETLINK_TYPE_FLAG },
+        [NHA_GROUPS]              = BUILD_POLICY(FLAG),
+        [NHA_MASTER]              = BUILD_POLICY(U32),
+        [NHA_FDB]                 = BUILD_POLICY(FLAG),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_nexthop);
+DEFINE_POLICY_SET(rtnl_nexthop);
 
-static const NLType rtnl_tca_option_data_cake_types[] = {
-        [TCA_CAKE_BASE_RATE64]   = { .type = NETLINK_TYPE_U64 },
-        [TCA_CAKE_DIFFSERV_MODE] = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_ATM]           = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_FLOW_MODE]     = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_OVERHEAD]      = { .type = NETLINK_TYPE_S32 },
-        [TCA_CAKE_RTT]           = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_TARGET]        = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_AUTORATE]      = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_MEMORY]        = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_NAT]           = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_RAW]           = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_WASH]          = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_MPU]           = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_INGRESS]       = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_ACK_FILTER]    = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_SPLIT_GSO]     = { .type = NETLINK_TYPE_U32 },
-        [TCA_CAKE_FWMARK]        = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_tca_option_data_cake_policies[] = {
+        [TCA_CAKE_BASE_RATE64]   = BUILD_POLICY(U64),
+        [TCA_CAKE_DIFFSERV_MODE] = BUILD_POLICY(U32),
+        [TCA_CAKE_ATM]           = BUILD_POLICY(U32),
+        [TCA_CAKE_FLOW_MODE]     = BUILD_POLICY(U32),
+        [TCA_CAKE_OVERHEAD]      = BUILD_POLICY(S32),
+        [TCA_CAKE_RTT]           = BUILD_POLICY(U32),
+        [TCA_CAKE_TARGET]        = BUILD_POLICY(U32),
+        [TCA_CAKE_AUTORATE]      = BUILD_POLICY(U32),
+        [TCA_CAKE_MEMORY]        = BUILD_POLICY(U32),
+        [TCA_CAKE_NAT]           = BUILD_POLICY(U32),
+        [TCA_CAKE_RAW]           = BUILD_POLICY(U32),
+        [TCA_CAKE_WASH]          = BUILD_POLICY(U32),
+        [TCA_CAKE_MPU]           = BUILD_POLICY(U32),
+        [TCA_CAKE_INGRESS]       = BUILD_POLICY(U32),
+        [TCA_CAKE_ACK_FILTER]    = BUILD_POLICY(U32),
+        [TCA_CAKE_SPLIT_GSO]     = BUILD_POLICY(U32),
+        [TCA_CAKE_FWMARK]        = BUILD_POLICY(U32),
 };
 
-static const NLType rtnl_tca_option_data_codel_types[] = {
-        [TCA_CODEL_TARGET]        = { .type = NETLINK_TYPE_U32 },
-        [TCA_CODEL_LIMIT]         = { .type = NETLINK_TYPE_U32 },
-        [TCA_CODEL_INTERVAL]      = { .type = NETLINK_TYPE_U32 },
-        [TCA_CODEL_ECN]           = { .type = NETLINK_TYPE_U32 },
-        [TCA_CODEL_CE_THRESHOLD]  = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_tca_option_data_codel_policies[] = {
+        [TCA_CODEL_TARGET]        = BUILD_POLICY(U32),
+        [TCA_CODEL_LIMIT]         = BUILD_POLICY(U32),
+        [TCA_CODEL_INTERVAL]      = BUILD_POLICY(U32),
+        [TCA_CODEL_ECN]           = BUILD_POLICY(U32),
+        [TCA_CODEL_CE_THRESHOLD]  = BUILD_POLICY(U32),
 };
 
-static const NLType rtnl_tca_option_data_drr_types[] = {
-        [TCA_DRR_QUANTUM] = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_tca_option_data_drr_policies[] = {
+        [TCA_DRR_QUANTUM] = BUILD_POLICY(U32),
 };
 
-static const NLType rtnl_tca_option_data_ets_quanta_types[] = {
-        [TCA_ETS_QUANTA_BAND] = { .type = NETLINK_TYPE_U32, },
+static const NLAPolicy rtnl_tca_option_data_ets_quanta_policies[] = {
+        [TCA_ETS_QUANTA_BAND] = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_tca_option_data_ets_quanta);
+DEFINE_POLICY_SET(rtnl_tca_option_data_ets_quanta);
 
-static const NLType rtnl_tca_option_data_ets_prio_types[] = {
-        [TCA_ETS_PRIOMAP_BAND] = { .type = NETLINK_TYPE_U8, },
+static const NLAPolicy rtnl_tca_option_data_ets_prio_policies[] = {
+        [TCA_ETS_PRIOMAP_BAND] = BUILD_POLICY(U8),
 };
 
-DEFINE_TYPE_SYSTEM(rtnl_tca_option_data_ets_prio);
+DEFINE_POLICY_SET(rtnl_tca_option_data_ets_prio);
 
-static const NLType rtnl_tca_option_data_ets_types[] = {
-        [TCA_ETS_NBANDS]      = { .type = NETLINK_TYPE_U8 },
-        [TCA_ETS_NSTRICT]     = { .type = NETLINK_TYPE_U8 },
-        [TCA_ETS_QUANTA]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_option_data_ets_quanta_type_system },
-        [TCA_ETS_PRIOMAP]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_option_data_ets_prio_type_system },
-        [TCA_ETS_QUANTA_BAND] = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_tca_option_data_ets_policies[] = {
+        [TCA_ETS_NBANDS]      = BUILD_POLICY(U8),
+        [TCA_ETS_NSTRICT]     = BUILD_POLICY(U8),
+        [TCA_ETS_QUANTA]      = BUILD_POLICY_NESTED(rtnl_tca_option_data_ets_quanta),
+        [TCA_ETS_PRIOMAP]     = BUILD_POLICY_NESTED(rtnl_tca_option_data_ets_prio),
+        [TCA_ETS_QUANTA_BAND] = BUILD_POLICY(U32),
 };
 
-static const NLType rtnl_tca_option_data_fq_types[] = {
-        [TCA_FQ_PLIMIT]             = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_FLOW_PLIMIT]        = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_QUANTUM]            = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_INITIAL_QUANTUM]    = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_RATE_ENABLE]        = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_FLOW_DEFAULT_RATE]  = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_FLOW_MAX_RATE]      = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_BUCKETS_LOG]        = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_FLOW_REFILL_DELAY]  = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_LOW_RATE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_CE_THRESHOLD]       = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_ORPHAN_MASK]        = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_tca_option_data_fq_policies[] = {
+        [TCA_FQ_PLIMIT]             = BUILD_POLICY(U32),
+        [TCA_FQ_FLOW_PLIMIT]        = BUILD_POLICY(U32),
+        [TCA_FQ_QUANTUM]            = BUILD_POLICY(U32),
+        [TCA_FQ_INITIAL_QUANTUM]    = BUILD_POLICY(U32),
+        [TCA_FQ_RATE_ENABLE]        = BUILD_POLICY(U32),
+        [TCA_FQ_FLOW_DEFAULT_RATE]  = BUILD_POLICY(U32),
+        [TCA_FQ_FLOW_MAX_RATE]      = BUILD_POLICY(U32),
+        [TCA_FQ_BUCKETS_LOG]        = BUILD_POLICY(U32),
+        [TCA_FQ_FLOW_REFILL_DELAY]  = BUILD_POLICY(U32),
+        [TCA_FQ_LOW_RATE_THRESHOLD] = BUILD_POLICY(U32),
+        [TCA_FQ_CE_THRESHOLD]       = BUILD_POLICY(U32),
+        [TCA_FQ_ORPHAN_MASK]        = BUILD_POLICY(U32),
 };
 
-static const NLType rtnl_tca_option_data_fq_codel_types[] = {
-        [TCA_FQ_CODEL_TARGET]          = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_CODEL_LIMIT]           = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_CODEL_INTERVAL]        = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_CODEL_ECN]             = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_CODEL_FLOWS]           = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_CODEL_QUANTUM]         = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_CODEL_CE_THRESHOLD]    = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_CODEL_DROP_BATCH_SIZE] = { .type = NETLINK_TYPE_U32 },
-        [TCA_FQ_CODEL_MEMORY_LIMIT]    = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_tca_option_data_fq_codel_policies[] = {
+        [TCA_FQ_CODEL_TARGET]          = BUILD_POLICY(U32),
+        [TCA_FQ_CODEL_LIMIT]           = BUILD_POLICY(U32),
+        [TCA_FQ_CODEL_INTERVAL]        = BUILD_POLICY(U32),
+        [TCA_FQ_CODEL_ECN]             = BUILD_POLICY(U32),
+        [TCA_FQ_CODEL_FLOWS]           = BUILD_POLICY(U32),
+        [TCA_FQ_CODEL_QUANTUM]         = BUILD_POLICY(U32),
+        [TCA_FQ_CODEL_CE_THRESHOLD]    = BUILD_POLICY(U32),
+        [TCA_FQ_CODEL_DROP_BATCH_SIZE] = BUILD_POLICY(U32),
+        [TCA_FQ_CODEL_MEMORY_LIMIT]    = BUILD_POLICY(U32),
 };
 
-static const NLType rtnl_tca_option_data_fq_pie_types[] = {
-        [TCA_FQ_PIE_LIMIT]   = { .type = NETLINK_TYPE_U32 },
-};
-
-static const NLType rtnl_tca_option_data_gred_types[] = {
-        [TCA_GRED_DPS] = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct tc_gred_sopt) },
-};
-
-static const NLType rtnl_tca_option_data_hhf_types[] = {
-        [TCA_HHF_BACKLOG_LIMIT] = { .type = NETLINK_TYPE_U32 },
-};
-
-static const NLType rtnl_tca_option_data_htb_types[] = {
-        [TCA_HTB_PARMS]  = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct tc_htb_opt) },
-        [TCA_HTB_INIT]   = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct tc_htb_glob) },
-        [TCA_HTB_CTAB]   = { .type = NETLINK_TYPE_BINARY, .size = TC_RTAB_SIZE },
-        [TCA_HTB_RTAB]   = { .type = NETLINK_TYPE_BINARY, .size = TC_RTAB_SIZE },
-        [TCA_HTB_RATE64] = { .type = NETLINK_TYPE_U64 },
-        [TCA_HTB_CEIL64] = { .type = NETLINK_TYPE_U64 },
-};
-
-static const NLType rtnl_tca_option_data_pie_types[] = {
-        [TCA_PIE_LIMIT]   = { .type = NETLINK_TYPE_U32 },
-};
-
-static const NLType rtnl_tca_option_data_qfq_types[] = {
-        [TCA_QFQ_WEIGHT] = { .type = NETLINK_TYPE_U32 },
-        [TCA_QFQ_LMAX]   = { .type = NETLINK_TYPE_U32 },
-};
-
-static const NLType rtnl_tca_option_data_sfb_types[] = {
-        [TCA_SFB_PARMS] = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct tc_sfb_qopt) },
+static const NLAPolicy rtnl_tca_option_data_fq_pie_policies[] = {
+        [TCA_FQ_PIE_LIMIT]   = BUILD_POLICY(U32),
+};
+
+static const NLAPolicy rtnl_tca_option_data_gred_policies[] = {
+        [TCA_GRED_DPS] = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct tc_gred_sopt)),
+};
+
+static const NLAPolicy rtnl_tca_option_data_hhf_policies[] = {
+        [TCA_HHF_BACKLOG_LIMIT] = BUILD_POLICY(U32),
+};
+
+static const NLAPolicy rtnl_tca_option_data_htb_policies[] = {
+        [TCA_HTB_PARMS]  = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct tc_htb_opt)),
+        [TCA_HTB_INIT]   = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct tc_htb_glob)),
+        [TCA_HTB_CTAB]   = BUILD_POLICY_WITH_SIZE(BINARY, TC_RTAB_SIZE),
+        [TCA_HTB_RTAB]   = BUILD_POLICY_WITH_SIZE(BINARY, TC_RTAB_SIZE),
+        [TCA_HTB_RATE64] = BUILD_POLICY(U64),
+        [TCA_HTB_CEIL64] = BUILD_POLICY(U64),
+};
+
+static const NLAPolicy rtnl_tca_option_data_pie_policies[] = {
+        [TCA_PIE_LIMIT]   = BUILD_POLICY(U32),
+};
+
+static const NLAPolicy rtnl_tca_option_data_qfq_policies[] = {
+        [TCA_QFQ_WEIGHT] = BUILD_POLICY(U32),
+        [TCA_QFQ_LMAX]   = BUILD_POLICY(U32),
+};
+
+static const NLAPolicy rtnl_tca_option_data_sfb_policies[] = {
+        [TCA_SFB_PARMS] = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct tc_sfb_qopt)),
 };
 
-static const NLType rtnl_tca_option_data_tbf_types[] = {
-        [TCA_TBF_PARMS]   = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct tc_tbf_qopt) },
-        [TCA_TBF_RTAB]    = { .type = NETLINK_TYPE_BINARY, .size = TC_RTAB_SIZE },
-        [TCA_TBF_PTAB]    = { .type = NETLINK_TYPE_BINARY, .size = TC_RTAB_SIZE },
-        [TCA_TBF_RATE64]  = { .type = NETLINK_TYPE_U64 },
-        [TCA_TBF_PRATE64] = { .type = NETLINK_TYPE_U64 },
-        [TCA_TBF_BURST]   = { .type = NETLINK_TYPE_U32 },
-        [TCA_TBF_PBURST]  = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy rtnl_tca_option_data_tbf_policies[] = {
+        [TCA_TBF_PARMS]   = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct tc_tbf_qopt)),
+        [TCA_TBF_RTAB]    = BUILD_POLICY_WITH_SIZE(BINARY, TC_RTAB_SIZE),
+        [TCA_TBF_PTAB]    = BUILD_POLICY_WITH_SIZE(BINARY, TC_RTAB_SIZE),
+        [TCA_TBF_RATE64]  = BUILD_POLICY(U64),
+        [TCA_TBF_PRATE64] = BUILD_POLICY(U64),
+        [TCA_TBF_BURST]   = BUILD_POLICY(U32),
+        [TCA_TBF_PBURST]  = BUILD_POLICY(U32),
 };
 
-static const NLTypeSystemUnionElement rtnl_tca_option_data_type_systems[] = {
-        { .name = "cake",     .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_cake),     },
-        { .name = "codel",    .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_codel),    },
-        { .name = "drr",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_drr),      },
-        { .name = "ets",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_ets),      },
-        { .name = "fq",       .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_fq),       },
-        { .name = "fq_codel", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_fq_codel), },
-        { .name = "fq_pie",   .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_fq_pie),   },
-        { .name = "gred",     .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_gred),     },
-        { .name = "hhf",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_hhf),      },
-        { .name = "htb",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_htb),      },
-        { .name = "pie",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_pie),      },
-        { .name = "qfq",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_qfq),      },
-        { .name = "sfb",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_sfb),      },
-        { .name = "tbf",      .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_tbf),      },
-};
-
-DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(rtnl_tca_option_data, TCA_KIND);
-
-static const NLType rtnl_tca_types[] = {
-        [TCA_KIND]           = { .type = NETLINK_TYPE_STRING },
-        [TCA_OPTIONS]        = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_tca_option_data_type_system_union },
-        [TCA_INGRESS_BLOCK]  = { .type = NETLINK_TYPE_U32 },
-        [TCA_EGRESS_BLOCK]   = { .type = NETLINK_TYPE_U32 },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_tca);
-
-static const NLType rtnl_mdb_types[] = {
-        [MDBA_SET_ENTRY]     = { .type = NETLINK_TYPE_BINARY, .size = sizeof(struct br_port_msg) },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl_mdb);
-
-static const NLType rtnl_types[] = {
-        [RTM_NEWLINK]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system,                .size = sizeof(struct ifinfomsg) },
-        [RTM_DELLINK]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system,                .size = sizeof(struct ifinfomsg) },
-        [RTM_GETLINK]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system,                .size = sizeof(struct ifinfomsg) },
-        [RTM_SETLINK]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system,                .size = sizeof(struct ifinfomsg) },
-        [RTM_NEWLINKPROP]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system,                .size = sizeof(struct ifinfomsg) },
-        [RTM_DELLINKPROP]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system,                .size = sizeof(struct ifinfomsg) },
-        [RTM_GETLINKPROP]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system,                .size = sizeof(struct ifinfomsg) },
-        [RTM_NEWADDR]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system,             .size = sizeof(struct ifaddrmsg) },
-        [RTM_DELADDR]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system,             .size = sizeof(struct ifaddrmsg) },
-        [RTM_GETADDR]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system,             .size = sizeof(struct ifaddrmsg) },
-        [RTM_NEWROUTE]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system,               .size = sizeof(struct rtmsg) },
-        [RTM_DELROUTE]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system,               .size = sizeof(struct rtmsg) },
-        [RTM_GETROUTE]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system,               .size = sizeof(struct rtmsg) },
-        [RTM_NEWNEIGH]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system,               .size = sizeof(struct ndmsg) },
-        [RTM_DELNEIGH]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system,               .size = sizeof(struct ndmsg) },
-        [RTM_GETNEIGH]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system,               .size = sizeof(struct ndmsg) },
-        [RTM_NEWADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system,           .size = sizeof(struct ifaddrlblmsg) },
-        [RTM_DELADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system,           .size = sizeof(struct ifaddrlblmsg) },
-        [RTM_GETADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system,           .size = sizeof(struct ifaddrlblmsg) },
-        [RTM_NEWRULE]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct fib_rule_hdr) },
-        [RTM_DELRULE]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct fib_rule_hdr) },
-        [RTM_GETRULE]      = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct fib_rule_hdr) },
-        [RTM_NEWNEXTHOP]   = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system,             .size = sizeof(struct nhmsg) },
-        [RTM_DELNEXTHOP]   = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system,             .size = sizeof(struct nhmsg) },
-        [RTM_GETNEXTHOP]   = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system,             .size = sizeof(struct nhmsg) },
-        [RTM_NEWQDISC]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system,                 .size = sizeof(struct tcmsg) },
-        [RTM_DELQDISC]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system,                 .size = sizeof(struct tcmsg) },
-        [RTM_GETQDISC]     = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system,                 .size = sizeof(struct tcmsg) },
-        [RTM_NEWTCLASS]    = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system,                 .size = sizeof(struct tcmsg) },
-        [RTM_DELTCLASS]    = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system,                 .size = sizeof(struct tcmsg) },
-        [RTM_GETTCLASS]    = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system,                 .size = sizeof(struct tcmsg) },
-        [RTM_NEWMDB]       = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system,                 .size = sizeof(struct br_port_msg) },
-        [RTM_DELMDB]       = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system,                 .size = sizeof(struct br_port_msg) },
-        [RTM_GETMDB]       = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system,                 .size = sizeof(struct br_port_msg) },
-};
-
-DEFINE_TYPE_SYSTEM(rtnl);
-
-const NLType *rtnl_get_type(uint16_t nlmsg_type) {
-        return type_system_get_type(&rtnl_type_system, nlmsg_type);
+static const NLAPolicySetUnionElement rtnl_tca_option_data_policy_set_union_elements[] = {
+        BUILD_UNION_ELEMENT_BY_STRING("cake",     rtnl_tca_option_data_cake),
+        BUILD_UNION_ELEMENT_BY_STRING("codel",    rtnl_tca_option_data_codel),
+        BUILD_UNION_ELEMENT_BY_STRING("drr",      rtnl_tca_option_data_drr),
+        BUILD_UNION_ELEMENT_BY_STRING("ets",      rtnl_tca_option_data_ets),
+        BUILD_UNION_ELEMENT_BY_STRING("fq",       rtnl_tca_option_data_fq),
+        BUILD_UNION_ELEMENT_BY_STRING("fq_codel", rtnl_tca_option_data_fq_codel),
+        BUILD_UNION_ELEMENT_BY_STRING("fq_pie",   rtnl_tca_option_data_fq_pie),
+        BUILD_UNION_ELEMENT_BY_STRING("gred",     rtnl_tca_option_data_gred),
+        BUILD_UNION_ELEMENT_BY_STRING("hhf",      rtnl_tca_option_data_hhf),
+        BUILD_UNION_ELEMENT_BY_STRING("htb",      rtnl_tca_option_data_htb),
+        BUILD_UNION_ELEMENT_BY_STRING("pie",      rtnl_tca_option_data_pie),
+        BUILD_UNION_ELEMENT_BY_STRING("qfq",      rtnl_tca_option_data_qfq),
+        BUILD_UNION_ELEMENT_BY_STRING("sfb",      rtnl_tca_option_data_sfb),
+        BUILD_UNION_ELEMENT_BY_STRING("tbf",      rtnl_tca_option_data_tbf),
+};
+
+DEFINE_POLICY_SET_UNION(rtnl_tca_option_data, TCA_KIND);
+
+static const NLAPolicy rtnl_tca_policies[] = {
+        [TCA_KIND]           = BUILD_POLICY(STRING),
+        [TCA_OPTIONS]        = BUILD_POLICY_NESTED_UNION_BY_STRING(rtnl_tca_option_data),
+        [TCA_INGRESS_BLOCK]  = BUILD_POLICY(U32),
+        [TCA_EGRESS_BLOCK]   = BUILD_POLICY(U32),
+};
+
+DEFINE_POLICY_SET(rtnl_tca);
+
+static const NLAPolicy rtnl_mdb_policies[] = {
+        [MDBA_SET_ENTRY]     = BUILD_POLICY_WITH_SIZE(BINARY, sizeof(struct br_port_msg)),
+};
+
+DEFINE_POLICY_SET(rtnl_mdb);
+
+static const NLAPolicy rtnl_policies[] = {
+        [RTM_NEWLINK]      = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_link, sizeof(struct ifinfomsg)),
+        [RTM_DELLINK]      = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_link, sizeof(struct ifinfomsg)),
+        [RTM_GETLINK]      = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_link, sizeof(struct ifinfomsg)),
+        [RTM_SETLINK]      = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_link, sizeof(struct ifinfomsg)),
+        [RTM_NEWLINKPROP]  = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_link, sizeof(struct ifinfomsg)),
+        [RTM_DELLINKPROP]  = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_link, sizeof(struct ifinfomsg)),
+        [RTM_GETLINKPROP]  = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_link, sizeof(struct ifinfomsg)),
+        [RTM_NEWADDR]      = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_address, sizeof(struct ifaddrmsg)),
+        [RTM_DELADDR]      = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_address, sizeof(struct ifaddrmsg)),
+        [RTM_GETADDR]      = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_address, sizeof(struct ifaddrmsg)),
+        [RTM_NEWROUTE]     = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_route, sizeof(struct rtmsg)),
+        [RTM_DELROUTE]     = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_route, sizeof(struct rtmsg)),
+        [RTM_GETROUTE]     = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_route, sizeof(struct rtmsg)),
+        [RTM_NEWNEIGH]     = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_neigh, sizeof(struct ndmsg)),
+        [RTM_DELNEIGH]     = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_neigh, sizeof(struct ndmsg)),
+        [RTM_GETNEIGH]     = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_neigh, sizeof(struct ndmsg)),
+        [RTM_NEWADDRLABEL] = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_addrlabel, sizeof(struct ifaddrlblmsg)),
+        [RTM_DELADDRLABEL] = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_addrlabel, sizeof(struct ifaddrlblmsg)),
+        [RTM_GETADDRLABEL] = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_addrlabel, sizeof(struct ifaddrlblmsg)),
+        [RTM_NEWRULE]      = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_routing_policy_rule, sizeof(struct fib_rule_hdr)),
+        [RTM_DELRULE]      = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_routing_policy_rule, sizeof(struct fib_rule_hdr)),
+        [RTM_GETRULE]      = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_routing_policy_rule, sizeof(struct fib_rule_hdr)),
+        [RTM_NEWNEXTHOP]   = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_nexthop, sizeof(struct nhmsg)),
+        [RTM_DELNEXTHOP]   = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_nexthop, sizeof(struct nhmsg)),
+        [RTM_GETNEXTHOP]   = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_nexthop, sizeof(struct nhmsg)),
+        [RTM_NEWQDISC]     = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_tca, sizeof(struct tcmsg)),
+        [RTM_DELQDISC]     = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_tca, sizeof(struct tcmsg)),
+        [RTM_GETQDISC]     = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_tca, sizeof(struct tcmsg)),
+        [RTM_NEWTCLASS]    = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_tca, sizeof(struct tcmsg)),
+        [RTM_DELTCLASS]    = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_tca, sizeof(struct tcmsg)),
+        [RTM_GETTCLASS]    = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_tca, sizeof(struct tcmsg)),
+        [RTM_NEWMDB]       = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_mdb, sizeof(struct br_port_msg)),
+        [RTM_DELMDB]       = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_mdb, sizeof(struct br_port_msg)),
+        [RTM_GETMDB]       = BUILD_POLICY_NESTED_WITH_SIZE(rtnl_mdb, sizeof(struct br_port_msg)),
+};
+
+DEFINE_POLICY_SET(rtnl);
+
+const NLAPolicy *rtnl_get_policy(uint16_t nlmsg_type) {
+        return policy_set_get_policy(&rtnl_policy_set, nlmsg_type);
 }
index 0a2a3effb28067cfdaeb91f1754201152ef835e6..21ef80c2ece987dfc96f073458b09b08c64491de 100644 (file)
 #include "netlink-internal.h"
 #include "netlink-types-internal.h"
 
-static const NLType empty_types[1] = {
+static const NLAPolicy empty_policies[1] = {
         /* fake array to avoid .types==NULL, which denotes invalid type-systems */
 };
 
-DEFINE_TYPE_SYSTEM(empty);
+DEFINE_POLICY_SET(empty);
 
-static const NLType error_types[] = {
-        [NLMSGERR_ATTR_MSG]  = { .type = NETLINK_TYPE_STRING },
-        [NLMSGERR_ATTR_OFFS] = { .type = NETLINK_TYPE_U32 },
+static const NLAPolicy error_policies[] = {
+        [NLMSGERR_ATTR_MSG]  = BUILD_POLICY(STRING),
+        [NLMSGERR_ATTR_OFFS] = BUILD_POLICY(U32),
 };
 
-DEFINE_TYPE_SYSTEM(error);
+DEFINE_POLICY_SET(error);
 
-static const NLType basic_types[] = {
-        [NLMSG_DONE]  = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system },
-        [NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &error_type_system, .size = sizeof(struct nlmsgerr) },
+static const NLAPolicy basic_policies[] = {
+        [NLMSG_DONE]  = BUILD_POLICY_NESTED(empty),
+        [NLMSG_ERROR] = BUILD_POLICY_NESTED_WITH_SIZE(error, sizeof(struct nlmsgerr)),
 };
 
-DEFINE_TYPE_SYSTEM(basic);
+DEFINE_POLICY_SET(basic);
 
-uint16_t type_get_type(const NLType *type) {
-        assert(type);
-        return type->type;
+NLAType policy_get_type(const NLAPolicy *policy) {
+        return ASSERT_PTR(policy)->type;
 }
 
-size_t type_get_size(const NLType *type) {
-        assert(type);
-        return type->size;
+size_t policy_get_size(const NLAPolicy *policy) {
+        return ASSERT_PTR(policy)->size;
 }
 
-const NLTypeSystem *type_get_type_system(const NLType *nl_type) {
-        assert(nl_type);
-        assert(nl_type->type == NETLINK_TYPE_NESTED);
-        assert(nl_type->type_system);
-        return nl_type->type_system;
+const NLAPolicySet *policy_get_policy_set(const NLAPolicy *policy) {
+        assert(policy);
+        assert(policy->type == NETLINK_TYPE_NESTED);
+
+        return ASSERT_PTR(policy->policy_set);
 }
 
-const NLTypeSystemUnion *type_get_type_system_union(const NLType *nl_type) {
-        assert(nl_type);
-        assert(nl_type->type == NETLINK_TYPE_UNION);
-        assert(nl_type->type_system_union);
-        return nl_type->type_system_union;
+const NLAPolicySetUnion *policy_get_policy_set_union(const NLAPolicy *policy) {
+        assert(policy);
+        assert(IN_SET(policy->type, NETLINK_TYPE_NESTED_UNION_BY_STRING, NETLINK_TYPE_NESTED_UNION_BY_FAMILY));
+
+        return ASSERT_PTR(policy->policy_set_union);
 }
 
-int type_system_root_get_type_system_and_header_size(
+int netlink_get_policy_set_and_header_size(
                 sd_netlink *nl,
                 uint16_t type,
-                const NLTypeSystem **ret_type_system,
+                const NLAPolicySet **ret_policy_set,
                 size_t *ret_header_size) {
 
-        const NLType *nl_type;
+        const NLAPolicy *policy;
 
         assert(nl);
 
         if (IN_SET(type, NLMSG_DONE, NLMSG_ERROR))
-                nl_type = type_system_get_type(&basic_type_system, type);
+                policy = policy_set_get_policy(&basic_policy_set, type);
         else
                 switch (nl->protocol) {
                 case NETLINK_ROUTE:
-                        nl_type = rtnl_get_type(type);
+                        policy = rtnl_get_policy(type);
                         break;
                 case NETLINK_NETFILTER:
-                        nl_type = nfnl_get_type(type);
+                        policy = nfnl_get_policy(type);
                         break;
                 case NETLINK_GENERIC:
-                        return genl_get_type_system_and_header_size(nl, type, ret_type_system, ret_header_size);
+                        return genl_get_policy_set_and_header_size(nl, type, ret_policy_set, ret_header_size);
                 default:
                         return -EOPNOTSUPP;
                 }
-        if (!nl_type)
+        if (!policy)
                 return -EOPNOTSUPP;
 
-        if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
+        if (policy_get_type(policy) != NETLINK_TYPE_NESTED)
                 return -EOPNOTSUPP;
 
-        if (ret_type_system)
-                *ret_type_system = type_get_type_system(nl_type);
+        if (ret_policy_set)
+                *ret_policy_set = policy_get_policy_set(policy);
         if (ret_header_size)
-                *ret_header_size = type_get_size(nl_type);
+                *ret_header_size = policy_get_size(policy);
         return 0;
 }
 
-const NLType *type_system_get_type(const NLTypeSystem *type_system, uint16_t type) {
-        const NLType *nl_type;
+const NLAPolicy *policy_set_get_policy(const NLAPolicySet *policy_set, uint16_t attr_type) {
+        const NLAPolicy *policy;
 
-        assert(type_system);
-        assert(type_system->types);
+        assert(policy_set);
+        assert(policy_set->policies);
 
-        if (type >= type_system->count)
+        if (attr_type >= policy_set->count)
                 return NULL;
 
-        nl_type = &type_system->types[type];
+        policy = &policy_set->policies[attr_type];
 
-        if (nl_type->type == NETLINK_TYPE_UNSPEC)
+        if (policy->type == NETLINK_TYPE_UNSPEC)
                 return NULL;
 
-        return nl_type;
+        return policy;
 }
 
-const NLTypeSystem *type_system_get_type_system(const NLTypeSystem *type_system, uint16_t type) {
-        const NLType *nl_type;
+const NLAPolicySet *policy_set_get_policy_set(const NLAPolicySet *policy_set, uint16_t attr_type) {
+        const NLAPolicy *policy;
 
-        nl_type = type_system_get_type(type_system, type);
-        if (!nl_type)
+        policy = policy_set_get_policy(policy_set, attr_type);
+        if (!policy)
                 return NULL;
 
-        return type_get_type_system(nl_type);
+        return policy_get_policy_set(policy);
 }
 
-const NLTypeSystemUnion *type_system_get_type_system_union(const NLTypeSystem *type_system, uint16_t type) {
-        const NLType *nl_type;
+const NLAPolicySetUnion *policy_set_get_policy_set_union(const NLAPolicySet *policy_set, uint16_t attr_type) {
+        const NLAPolicy *policy;
 
-        nl_type = type_system_get_type(type_system, type);
-        if (!nl_type)
+        policy = policy_set_get_policy(policy_set, attr_type);
+        if (!policy)
                 return NULL;
 
-        return type_get_type_system_union(nl_type);
+        return policy_get_policy_set_union(policy);
 }
 
-NLMatchType type_system_union_get_match_type(const NLTypeSystemUnion *type_system_union) {
-        assert(type_system_union);
-        return type_system_union->match_type;
-}
+uint16_t policy_set_union_get_match_attribute(const NLAPolicySetUnion *policy_set_union) {
+        assert(policy_set_union->match_attribute != 0);
 
-uint16_t type_system_union_get_match_attribute(const NLTypeSystemUnion *type_system_union) {
-        assert(type_system_union);
-        assert(type_system_union->match_type == NL_MATCH_SIBLING);
-        return type_system_union->match_attribute;
+        return policy_set_union->match_attribute;
 }
 
-const NLTypeSystem *type_system_union_get_type_system_by_string(const NLTypeSystemUnion *type_system_union, const char *key) {
-        assert(type_system_union);
-        assert(type_system_union->elements);
-        assert(type_system_union->match_type == NL_MATCH_SIBLING);
-        assert(key);
+const NLAPolicySet *policy_set_union_get_policy_set_by_string(const NLAPolicySetUnion *policy_set_union, const char *string) {
+        assert(policy_set_union);
+        assert(policy_set_union->elements);
+        assert(string);
 
-        for (size_t i = 0; i < type_system_union->count; i++)
-                if (streq(type_system_union->elements[i].name, key))
-                        return &type_system_union->elements[i].type_system;
+        for (size_t i = 0; i < policy_set_union->count; i++)
+                if (streq(policy_set_union->elements[i].string, string))
+                        return &policy_set_union->elements[i].policy_set;
 
         return NULL;
 }
 
-const NLTypeSystem *type_system_union_get_type_system_by_protocol(const NLTypeSystemUnion *type_system_union, uint16_t protocol) {
-        assert(type_system_union);
-        assert(type_system_union->elements);
-        assert(type_system_union->match_type == NL_MATCH_PROTOCOL);
+const NLAPolicySet *policy_set_union_get_policy_set_by_family(const NLAPolicySetUnion *policy_set_union, int family) {
+        assert(policy_set_union);
+        assert(policy_set_union->elements);
 
-        for (size_t i = 0; i < type_system_union->count; i++)
-                if (type_system_union->elements[i].protocol == protocol)
-                        return &type_system_union->elements[i].type_system;
+        for (size_t i = 0; i < policy_set_union->count; i++)
+                if (policy_set_union->elements[i].family == family)
+                        return &policy_set_union->elements[i].policy_set;
 
         return NULL;
 }
index d481f3072fbec6149ca4b9a429fa1dd4e716b0d3..e034a984e9b0d0e1860d8804fc5f2d77e9f6290e 100644 (file)
@@ -1,10 +1,14 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include <errno.h>
+
 #include "sd-netlink.h"
 
-enum {
-        NETLINK_TYPE_UNSPEC,
+typedef enum NLAType {
+        NETLINK_TYPE_UNSPEC,                    /* NLA_UNSPEC */
+        NETLINK_TYPE_BINARY,                    /* NLA_BINARY */
+        NETLINK_TYPE_FLAG,                      /* NLA_FLAG */
         NETLINK_TYPE_U8,                        /* NLA_U8 */
         NETLINK_TYPE_U16,                       /* NLA_U16 */
         NETLINK_TYPE_U32,                       /* NLA_U32 */
@@ -14,51 +18,46 @@ enum {
         NETLINK_TYPE_S32,                       /* NLA_S32 */
         NETLINK_TYPE_S64,                       /* NLA_S64 */
         NETLINK_TYPE_STRING,                    /* NLA_STRING */
-        NETLINK_TYPE_FLAG,                      /* NLA_FLAG */
+        NETLINK_TYPE_BITFIELD32,                /* NLA_BITFIELD32 */
+        NETLINK_TYPE_REJECT,                    /* NLA_REJECT */
         NETLINK_TYPE_IN_ADDR,
         NETLINK_TYPE_ETHER_ADDR,
         NETLINK_TYPE_CACHE_INFO,
-        NETLINK_TYPE_NESTED,                    /* NLA_NESTED */
-        NETLINK_TYPE_UNION,
         NETLINK_TYPE_SOCKADDR,
-        NETLINK_TYPE_BINARY,
-        NETLINK_TYPE_BITFIELD32,                /* NLA_BITFIELD32 */
-        NETLINK_TYPE_REJECT,                    /* NLA_REJECT */
-};
-
-typedef enum NLMatchType {
-        NL_MATCH_SIBLING,
-        NL_MATCH_PROTOCOL,
-} NLMatchType;
-
-typedef struct NLTypeSystemUnion NLTypeSystemUnion;
-typedef struct NLTypeSystem NLTypeSystem;
-typedef struct NLType NLType;
-
-const NLType *rtnl_get_type(uint16_t nlmsg_type);
-const NLType *nfnl_get_type(uint16_t nlmsg_type);
-const NLTypeSystem *genl_get_type_system_by_name(const char *name);
-int genl_get_type_system_and_header_size(
+        NETLINK_TYPE_NESTED,                    /* NLA_NESTED */
+        NETLINK_TYPE_NESTED_UNION_BY_STRING,
+        NETLINK_TYPE_NESTED_UNION_BY_FAMILY,
+        _NETLINK_TYPE_MAX,
+        _NETLINK_TYPE_INVALID = -EINVAL,
+} NLAType;
+
+typedef struct NLAPolicy NLAPolicy;
+typedef struct NLAPolicySet NLAPolicySet;
+typedef struct NLAPolicySetUnion NLAPolicySetUnion;
+
+const NLAPolicy *rtnl_get_policy(uint16_t nlmsg_type);
+const NLAPolicy *nfnl_get_policy(uint16_t nlmsg_type);
+const NLAPolicySet *genl_get_policy_set_by_name(const char *name);
+int genl_get_policy_set_and_header_size(
                 sd_netlink *nl,
                 uint16_t id,
-                const NLTypeSystem **ret_type_system,
+                const NLAPolicySet **ret_policy_set,
                 size_t *ret_header_size);
 
-uint16_t type_get_type(const NLType *type);
-size_t type_get_size(const NLType *type);
-const NLTypeSystem *type_get_type_system(const NLType *type);
-const NLTypeSystemUnion *type_get_type_system_union(const NLType *type);
+NLAType policy_get_type(const NLAPolicy *policy);
+size_t policy_get_size(const NLAPolicy *policy);
+const NLAPolicySet *policy_get_policy_set(const NLAPolicy *policy);
+const NLAPolicySetUnion *policy_get_policy_set_union(const NLAPolicy *policy);
 
-int type_system_root_get_type_system_and_header_size(
+int netlink_get_policy_set_and_header_size(
                 sd_netlink *nl,
                 uint16_t type,
-                const NLTypeSystem **ret_type_system,
+                const NLAPolicySet **ret_policy_set,
                 size_t *ret_header_size);
 
-const NLType *type_system_get_type(const NLTypeSystem *type_system, uint16_t type);
-const NLTypeSystem *type_system_get_type_system(const NLTypeSystem *type_system, uint16_t type);
-const NLTypeSystemUnion *type_system_get_type_system_union(const NLTypeSystem *type_system, uint16_t type);
-NLMatchType type_system_union_get_match_type(const NLTypeSystemUnion *type_system_union);
-uint16_t type_system_union_get_match_attribute(const NLTypeSystemUnion *type_system_union);
-const NLTypeSystem *type_system_union_get_type_system_by_string(const NLTypeSystemUnion *type_system_union, const char *key);
-const NLTypeSystem *type_system_union_get_type_system_by_protocol(const NLTypeSystemUnion *type_system_union, uint16_t protocol);
+const NLAPolicy *policy_set_get_policy(const NLAPolicySet *policy_set, uint16_t attr_type);
+const NLAPolicySet *policy_set_get_policy_set(const NLAPolicySet *type_system, uint16_t attr_type);
+const NLAPolicySetUnion *policy_set_get_policy_set_union(const NLAPolicySet *type_system, uint16_t attr_type);
+uint16_t policy_set_union_get_match_attribute(const NLAPolicySetUnion *policy_set_union);
+const NLAPolicySet *policy_set_union_get_policy_set_by_string(const NLAPolicySetUnion *type_system_union, const char *string);
+const NLAPolicySet *policy_set_union_get_policy_set_by_family(const NLAPolicySetUnion *type_system_union, int family);
index 541eb1110ae572910dc57e4b1d961145f8230195..2d87fe011ee093a41a0b7458e31a3a9d34021fdc 100644 (file)
@@ -71,51 +71,51 @@ int sd_netlink_detach_event(sd_netlink *nl);
 int sd_netlink_attach_filter(sd_netlink *nl, size_t len, struct sock_filter *filter);
 
 /* message */
-int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data);
-int sd_netlink_message_append_strv(sd_netlink_message *m, unsigned short type, char * const *data);
-int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type);
-int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data);
-int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data);
-int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, uint32_t data);
-int sd_netlink_message_append_u64(sd_netlink_message *m, unsigned short type, uint64_t data);
-int sd_netlink_message_append_s8(sd_netlink_message *m, unsigned short type, int8_t data);
-int sd_netlink_message_append_s16(sd_netlink_message *m, unsigned short type, int16_t data);
-int sd_netlink_message_append_s32(sd_netlink_message *m, unsigned short type, int32_t data);
-int sd_netlink_message_append_s64(sd_netlink_message *m, unsigned short type, int64_t data);
-int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len);
+int sd_netlink_message_append_string(sd_netlink_message *m, uint16_t attr_type, const char *data);
+int sd_netlink_message_append_strv(sd_netlink_message *m, uint16_t attr_type, char * const *data);
+int sd_netlink_message_append_flag(sd_netlink_message *m, uint16_t attr_type);
+int sd_netlink_message_append_u8(sd_netlink_message *m, uint16_t attr_type, uint8_t data);
+int sd_netlink_message_append_u16(sd_netlink_message *m, uint16_t attr_type, uint16_t data);
+int sd_netlink_message_append_u32(sd_netlink_message *m, uint16_t attr_type, uint32_t data);
+int sd_netlink_message_append_u64(sd_netlink_message *m, uint16_t attr_type, uint64_t data);
+int sd_netlink_message_append_s8(sd_netlink_message *m, uint16_t attr_type, int8_t data);
+int sd_netlink_message_append_s16(sd_netlink_message *m, uint16_t attr_type, int16_t data);
+int sd_netlink_message_append_s32(sd_netlink_message *m, uint16_t attr_type, int32_t data);
+int sd_netlink_message_append_s64(sd_netlink_message *m, uint16_t attr_type, int64_t data);
+int sd_netlink_message_append_data(sd_netlink_message *m, uint16_t attr_type, const void *data, size_t len);
 int sd_netlink_message_append_container_data(
                 sd_netlink_message *m,
-                unsigned short container_type,
-                unsigned short type,
+                uint16_t container_type,
+                uint16_t attr_type,
                 const void *data,
                 size_t len);
-int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data);
-int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data);
-int sd_netlink_message_append_sockaddr_in(sd_netlink_message *m, unsigned short type, const struct sockaddr_in *data);
-int sd_netlink_message_append_sockaddr_in6(sd_netlink_message *m, unsigned short type, const struct sockaddr_in6 *data);
-int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data);
-int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short type, const struct ifa_cacheinfo *info);
-
-int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type);
-int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned short type, const char *key);
+int sd_netlink_message_append_in_addr(sd_netlink_message *m, uint16_t attr_type, const struct in_addr *data);
+int sd_netlink_message_append_in6_addr(sd_netlink_message *m, uint16_t attr_type, const struct in6_addr *data);
+int sd_netlink_message_append_sockaddr_in(sd_netlink_message *m, uint16_t attr_type, const struct sockaddr_in *data);
+int sd_netlink_message_append_sockaddr_in6(sd_netlink_message *m, uint16_t attr_type, const struct sockaddr_in6 *data);
+int sd_netlink_message_append_ether_addr(sd_netlink_message *m, uint16_t attr_type, const struct ether_addr *data);
+int sd_netlink_message_append_cache_info(sd_netlink_message *m, uint16_t attr_type, const struct ifa_cacheinfo *info);
+
+int sd_netlink_message_open_container(sd_netlink_message *m, uint16_t attr_type);
+int sd_netlink_message_open_container_union(sd_netlink_message *m, uint16_t attr_type, const char *key);
 int sd_netlink_message_close_container(sd_netlink_message *m);
 
-int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t size, void *data);
-int sd_netlink_message_read_data(sd_netlink_message *m, unsigned short type, size_t *ret_size, void **ret_data);
-int sd_netlink_message_read_data_suffix0(sd_netlink_message *m, unsigned short type, size_t *ret_size, void **ret_data);
-int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data);
-int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data);
-int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret);
-int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data);
-int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data);
-int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data);
-int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short type, struct ether_addr *data);
-int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info);
-int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data);
-int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data);
-int sd_netlink_message_has_flag(sd_netlink_message *m, unsigned short type);
-int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type);
-int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type);
+int sd_netlink_message_read(sd_netlink_message *m, uint16_t attr_type, size_t size, void *data);
+int sd_netlink_message_read_data(sd_netlink_message *m, uint16_t attr_type, size_t *ret_size, void **ret_data);
+int sd_netlink_message_read_data_suffix0(sd_netlink_message *m, uint16_t attr_type, size_t *ret_size, void **ret_data);
+int sd_netlink_message_read_string_strdup(sd_netlink_message *m, uint16_t attr_type, char **data);
+int sd_netlink_message_read_string(sd_netlink_message *m, uint16_t attr_type, const char **data);
+int sd_netlink_message_read_strv(sd_netlink_message *m, uint16_t container_type, uint16_t attr_type, char ***ret);
+int sd_netlink_message_read_u8(sd_netlink_message *m, uint16_t attr_type, uint8_t *data);
+int sd_netlink_message_read_u16(sd_netlink_message *m, uint16_t attr_type, uint16_t *data);
+int sd_netlink_message_read_u32(sd_netlink_message *m, uint16_t attr_type, uint32_t *data);
+int sd_netlink_message_read_ether_addr(sd_netlink_message *m, uint16_t attr_type, struct ether_addr *data);
+int sd_netlink_message_read_cache_info(sd_netlink_message *m, uint16_t attr_type, struct ifa_cacheinfo *info);
+int sd_netlink_message_read_in_addr(sd_netlink_message *m, uint16_t attr_type, struct in_addr *data);
+int sd_netlink_message_read_in6_addr(sd_netlink_message *m, uint16_t attr_type, struct in6_addr *data);
+int sd_netlink_message_has_flag(sd_netlink_message *m, uint16_t attr_type);
+int sd_netlink_message_enter_container(sd_netlink_message *m, uint16_t attr_type);
+int sd_netlink_message_enter_array(sd_netlink_message *m, uint16_t attr_type);
 int sd_netlink_message_exit_container(sd_netlink_message *m);
 
 int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type);