chiark / gitweb /
sd-netlink: don't treat NULL as root type-system
[elogind.git] / src / libsystemd / sd-netlink / netlink-types.c
index 7715ff8a444982198c847c1d46446843d5402881..40548dcbc0ee79c56380b6c1d853925b622e76d8 100644 (file)
@@ -46,8 +46,22 @@ struct NLType {
         const NLTypeSystemUnion *type_system_union;
 };
 
+struct NLTypeSystem {
+        uint16_t count;
+        const NLType *types;
+};
+
 static const NLTypeSystem rtnl_link_type_system;
 
+static const NLType empty_types[1] = {
+        /* fake array to avoid .types==NULL, which denotes invalid type-systems */
+};
+
+static const NLTypeSystem empty_type_system = {
+        .count = 0,
+        .types = empty_types,
+};
+
 static const NLType rtnl_link_info_data_veth_types[VETH_INFO_MAX + 1] = {
         [VETH_INFO_PEER]  = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
 };
@@ -117,7 +131,7 @@ static const NLType rtnl_bond_arp_target_types[BOND_ARP_TARGETS_MAX + 1] = {
 };
 
 static const NLTypeSystem rtnl_bond_arp_type_system = {
-        .max = ELEMENTSOF(rtnl_bond_arp_target_types) - 1,
+        .count = ELEMENTSOF(rtnl_bond_arp_target_types),
         .types = rtnl_bond_arp_target_types,
 };
 
@@ -218,37 +232,37 @@ static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_
 DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
 
 static const NLTypeSystem rtnl_link_info_data_type_systems[_NL_UNION_LINK_INFO_DATA_MAX] = {
-        [NL_UNION_LINK_INFO_DATA_BOND] =        { .max = ELEMENTSOF(rtnl_link_info_data_bond_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_BOND] =        { .count = ELEMENTSOF(rtnl_link_info_data_bond_types),
                                                   .types = rtnl_link_info_data_bond_types },
-        [NL_UNION_LINK_INFO_DATA_BRIDGE] =      { .max = ELEMENTSOF(rtnl_link_info_data_bridge_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_BRIDGE] =      { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types),
                                                   .types = rtnl_link_info_data_bridge_types },
-        [NL_UNION_LINK_INFO_DATA_VLAN] =        { .max = ELEMENTSOF(rtnl_link_info_data_vlan_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_VLAN] =        { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types),
                                                   .types = rtnl_link_info_data_vlan_types },
-        [NL_UNION_LINK_INFO_DATA_VETH] =        { .max = ELEMENTSOF(rtnl_link_info_data_veth_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_VETH] =        { .count = ELEMENTSOF(rtnl_link_info_data_veth_types),
                                                   .types = rtnl_link_info_data_veth_types },
-        [NL_UNION_LINK_INFO_DATA_MACVLAN] =     { .max = ELEMENTSOF(rtnl_link_info_data_macvlan_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_MACVLAN] =     { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types),
                                                   .types = rtnl_link_info_data_macvlan_types },
-        [NL_UNION_LINK_INFO_DATA_IPVLAN] =      { .max = ELEMENTSOF(rtnl_link_info_data_ipvlan_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_IPVLAN] =      { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types),
                                                   .types = rtnl_link_info_data_ipvlan_types },
-        [NL_UNION_LINK_INFO_DATA_VXLAN] =       { .max = ELEMENTSOF(rtnl_link_info_data_vxlan_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_VXLAN] =       { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types),
                                                   .types = rtnl_link_info_data_vxlan_types },
-        [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .max = ELEMENTSOF(rtnl_link_info_data_iptun_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
                                                   .types = rtnl_link_info_data_iptun_types },
-        [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] =  { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
                                                     .types = rtnl_link_info_data_ipgre_types },
-        [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] =  { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
                                                     .types = rtnl_link_info_data_ipgre_types },
-        [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] =  { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
                                                     .types = rtnl_link_info_data_ipgre_types },
-        [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] =  { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
                                                     .types = rtnl_link_info_data_ipgre_types },
-        [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_iptun_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] =  { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
                                                   .types = rtnl_link_info_data_iptun_types },
-        [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipvti_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] =  { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
                                                   .types = rtnl_link_info_data_ipvti_types },
-        [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipvti_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] =  { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
                                                   .types = rtnl_link_info_data_ipvti_types },
-        [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types) - 1,
+        [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] =  { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types),
                                                      .types = rtnl_link_info_data_ip6tnl_types },
 
 };
@@ -272,7 +286,7 @@ static const NLType rtnl_link_info_types[IFLA_INFO_MAX + 1] = {
 };
 
 static const NLTypeSystem rtnl_link_info_type_system = {
-        .max = ELEMENTSOF(rtnl_link_info_types) - 1,
+        .count = ELEMENTSOF(rtnl_link_info_types),
         .types = rtnl_link_info_types,
 };
 
@@ -288,7 +302,7 @@ static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1]
 };
 
 static const NLTypeSystem rtnl_prot_info_type_systems[AF_MAX] = {
-        [AF_BRIDGE] =   { .max = ELEMENTSOF(rtnl_prot_info_bridge_port_types) - 1,
+        [AF_BRIDGE] =   { .count = ELEMENTSOF(rtnl_prot_info_bridge_port_types),
                           .types = rtnl_prot_info_bridge_port_types },
 };
 
@@ -312,7 +326,7 @@ static const struct NLType rtnl_af_spec_inet6_types[IFLA_INET6_MAX + 1] = {
 };
 
 static const NLTypeSystem rtnl_af_spec_inet6_type_system = {
-        .max = ELEMENTSOF(rtnl_af_spec_inet6_types) - 1,
+        .count = ELEMENTSOF(rtnl_af_spec_inet6_types),
         .types = rtnl_af_spec_inet6_types,
 };
 
@@ -321,7 +335,7 @@ static const NLType rtnl_af_spec_types[AF_MAX + 1] = {
 };
 
 static const NLTypeSystem rtnl_af_spec_type_system = {
-        .max = ELEMENTSOF(rtnl_af_spec_types) - 1,
+        .count = ELEMENTSOF(rtnl_af_spec_types),
         .types = rtnl_af_spec_types,
 };
 
@@ -378,7 +392,7 @@ static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
 };
 
 static const NLTypeSystem rtnl_link_type_system = {
-        .max = ELEMENTSOF(rtnl_link_types) - 1,
+        .count = ELEMENTSOF(rtnl_link_types),
         .types = rtnl_link_types,
 };
 
@@ -398,7 +412,7 @@ static const NLType rtnl_address_types[CONST_MAX(IFA_MAX, IFA_FLAGS) + 1] = {
 };
 
 static const NLTypeSystem rtnl_address_type_system = {
-        .max = ELEMENTSOF(rtnl_address_types) - 1,
+        .count = ELEMENTSOF(rtnl_address_types),
         .types = rtnl_address_types,
 };
 
@@ -424,7 +438,7 @@ static const NLType rtnl_route_types[RTA_MAX + 1] = {
 };
 
 static const NLTypeSystem rtnl_route_type_system = {
-        .max = ELEMENTSOF(rtnl_route_types) - 1,
+        .count = ELEMENTSOF(rtnl_route_types),
         .types = rtnl_route_types,
 };
 
@@ -440,13 +454,13 @@ static const NLType rtnl_neigh_types[NDA_MAX + 1] = {
 };
 
 static const NLTypeSystem rtnl_neigh_type_system = {
-        .max = ELEMENTSOF(rtnl_neigh_types) - 1,
+        .count = ELEMENTSOF(rtnl_neigh_types),
         .types = rtnl_neigh_types,
 };
 
 static const NLType rtnl_types[RTM_MAX + 1] = {
-        [NLMSG_DONE]   = { .type = NETLINK_TYPE_META, .size = 0 },
-        [NLMSG_ERROR]  = { .type = NETLINK_TYPE_META, .size = sizeof(struct nlmsgerr) },
+        [NLMSG_DONE]   = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 },
+        [NLMSG_ERROR]  = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) },
         [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) },
@@ -462,8 +476,8 @@ static const NLType rtnl_types[RTM_MAX + 1] = {
         [RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
 };
 
-const NLTypeSystem rtnl_type_system = {
-        .max = ELEMENTSOF(rtnl_types) - 1,
+const NLTypeSystem type_system_root = {
+        .count = ELEMENTSOF(rtnl_types),
         .types = rtnl_types,
 };
 
@@ -495,17 +509,19 @@ void type_get_type_system_union(const NLType *nl_type, const NLTypeSystemUnion *
         *ret = nl_type->type_system_union;
 }
 
+uint16_t type_system_get_count(const NLTypeSystem *type_system) {
+        assert(type_system);
+        return type_system->count;
+}
+
 int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type) {
         const NLType *nl_type;
 
         assert(ret);
-
-        if (!type_system)
-                type_system = &rtnl_type_system;
-
+        assert(type_system);
         assert(type_system->types);
 
-        if (type > type_system->max)
+        if (type >= type_system->count)
                 return -EOPNOTSUPP;
 
         nl_type = &type_system->types[type];
@@ -579,7 +595,7 @@ int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_sys
                 return -EOPNOTSUPP;
 
         type_system = &type_system_union->type_systems[protocol];
-        if (type_system->max == 0)
+        if (!type_system->types)
                 return -EOPNOTSUPP;
 
         *ret = type_system;