1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <netinet/in.h>
4 #include <sys/socket.h>
5 #include <linux/if.h>
6 #include <linux/netfilter/nf_tables.h>
7 #include <linux/netfilter/nfnetlink.h>
8 
9 #include "netlink-types-internal.h"
10 #include "string-table.h"
11 
12 static const NLType nfnl_nft_table_types[] = {
13         [NFTA_TABLE_NAME]  = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
14         [NFTA_TABLE_FLAGS] = { .type = NETLINK_TYPE_U32 },
15 };
16 
17 DEFINE_TYPE_SYSTEM(nfnl_nft_table);
18 
19 static const NLType nfnl_nft_chain_hook_types[] = {
20         [NFTA_HOOK_HOOKNUM]  = { .type = NETLINK_TYPE_U32 },
21         [NFTA_HOOK_PRIORITY] = { .type = NETLINK_TYPE_U32 },
22         [NFTA_HOOK_DEV]      = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
23 };
24 
25 DEFINE_TYPE_SYSTEM(nfnl_nft_chain_hook);
26 
27 static const NLType nfnl_nft_chain_types[] = {
28         [NFTA_CHAIN_TABLE] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
29         [NFTA_CHAIN_NAME]  = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
30         [NFTA_CHAIN_HOOK]  = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_chain_hook_type_system },
31         [NFTA_CHAIN_TYPE]  = { .type = NETLINK_TYPE_STRING, .size = 16 },
32         [NFTA_CHAIN_FLAGS] = { .type = NETLINK_TYPE_U32 },
33 };
34 
35 DEFINE_TYPE_SYSTEM(nfnl_nft_chain);
36 
37 static const NLType nfnl_nft_expr_meta_types[] = {
38         [NFTA_META_DREG] = { .type = NETLINK_TYPE_U32 },
39         [NFTA_META_KEY]  = { .type = NETLINK_TYPE_U32 },
40         [NFTA_META_SREG] = { .type = NETLINK_TYPE_U32 },
41 };
42 
43 static const NLType nfnl_nft_expr_payload_types[] = {
44         [NFTA_PAYLOAD_DREG]   = { .type = NETLINK_TYPE_U32 },
45         [NFTA_PAYLOAD_BASE]   = { .type = NETLINK_TYPE_U32 },
46         [NFTA_PAYLOAD_OFFSET] = { .type = NETLINK_TYPE_U32 },
47         [NFTA_PAYLOAD_LEN]    = { .type = NETLINK_TYPE_U32 },
48 };
49 
50 static const NLType nfnl_nft_expr_nat_types[] = {
51         [NFTA_NAT_TYPE]          = { .type = NETLINK_TYPE_U32 },
52         [NFTA_NAT_FAMILY]        = { .type = NETLINK_TYPE_U32 },
53         [NFTA_NAT_REG_ADDR_MIN]  = { .type = NETLINK_TYPE_U32 },
54         [NFTA_NAT_REG_ADDR_MAX]  = { .type = NETLINK_TYPE_U32 },
55         [NFTA_NAT_REG_PROTO_MIN] = { .type = NETLINK_TYPE_U32 },
56         [NFTA_NAT_REG_PROTO_MAX] = { .type = NETLINK_TYPE_U32 },
57         [NFTA_NAT_FLAGS]         = { .type = NETLINK_TYPE_U32 },
58 };
59 
60 static const NLType nfnl_nft_data_types[] = {
61         [NFTA_DATA_VALUE] = { .type = NETLINK_TYPE_BINARY },
62 };
63 
64 DEFINE_TYPE_SYSTEM(nfnl_nft_data);
65 
66 static const NLType nfnl_nft_expr_bitwise_types[] = {
67         [NFTA_BITWISE_SREG] = { .type = NETLINK_TYPE_U32 },
68         [NFTA_BITWISE_DREG] = { .type = NETLINK_TYPE_U32 },
69         [NFTA_BITWISE_LEN]  = { .type = NETLINK_TYPE_U32 },
70         [NFTA_BITWISE_MASK] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
71         [NFTA_BITWISE_XOR]  = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
72 };
73 
74 static const NLType nfnl_nft_expr_cmp_types[] = {
75         [NFTA_CMP_SREG] = { .type = NETLINK_TYPE_U32 },
76         [NFTA_CMP_OP]   = { .type = NETLINK_TYPE_U32 },
77         [NFTA_CMP_DATA] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
78 };
79 
80 static const NLType nfnl_nft_expr_fib_types[] = {
81         [NFTA_FIB_DREG]   = { .type = NETLINK_TYPE_U32 },
82         [NFTA_FIB_RESULT] = { .type = NETLINK_TYPE_U32 },
83         [NFTA_FIB_FLAGS]  = { .type = NETLINK_TYPE_U32 },
84 };
85 
86 static const NLType nfnl_nft_expr_lookup_types[] = {
87         [NFTA_LOOKUP_SET]   = { .type = NETLINK_TYPE_STRING },
88         [NFTA_LOOKUP_SREG]  = { .type = NETLINK_TYPE_U32 },
89         [NFTA_LOOKUP_DREG]  = { .type = NETLINK_TYPE_U32 },
90         [NFTA_LOOKUP_FLAGS] = { .type = NETLINK_TYPE_U32 },
91 };
92 
93 static const NLType nfnl_nft_expr_masq_types[] = {
94         [NFTA_MASQ_FLAGS]         = { .type = NETLINK_TYPE_U32 },
95         [NFTA_MASQ_REG_PROTO_MIN] = { .type = NETLINK_TYPE_U32 },
96         [NFTA_MASQ_REG_PROTO_MAX] = { .type = NETLINK_TYPE_U32 },
97 };
98 
99 static const NLTypeSystemUnionElement nfnl_expr_data_type_systems[] = {
100         { .name = "bitwise", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_bitwise), },
101         { .name = "cmp",     .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_cmp),     },
102         { .name = "fib",     .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_fib),     },
103         { .name = "lookup",  .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_lookup),  },
104         { .name = "masq",    .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_masq),    },
105         { .name = "meta",    .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_meta),    },
106         { .name = "nat",     .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_nat),     },
107         { .name = "payload", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_payload), },
108 };
109 
110 DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(nfnl_expr_data, NFTA_EXPR_NAME);
111 
112 static const NLType nfnl_nft_rule_expr_types[] = {
113         [NFTA_EXPR_NAME] = { .type = NETLINK_TYPE_STRING, .size = 16 },
114         [NFTA_EXPR_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &nfnl_expr_data_type_system_union },
115 };
116 
117 DEFINE_TYPE_SYSTEM(nfnl_nft_rule_expr);
118 
119 static const NLType nfnl_nft_rule_types[] = {
120         [NFTA_RULE_TABLE]       = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
121         [NFTA_RULE_CHAIN]       = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
122         [NFTA_RULE_EXPRESSIONS] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_rule_expr_type_system }
123 };
124 
125 DEFINE_TYPE_SYSTEM(nfnl_nft_rule);
126 
127 static const NLType nfnl_nft_set_types[] = {
128         [NFTA_SET_TABLE]      = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
129         [NFTA_SET_NAME]       = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
130         [NFTA_SET_FLAGS]      = { .type = NETLINK_TYPE_U32 },
131         [NFTA_SET_KEY_TYPE]   = { .type = NETLINK_TYPE_U32 },
132         [NFTA_SET_KEY_LEN]    = { .type = NETLINK_TYPE_U32 },
133         [NFTA_SET_DATA_TYPE]  = { .type = NETLINK_TYPE_U32 },
134         [NFTA_SET_DATA_LEN]   = { .type = NETLINK_TYPE_U32 },
135         [NFTA_SET_POLICY]     = { .type = NETLINK_TYPE_U32 },
136         [NFTA_SET_ID]         = { .type = NETLINK_TYPE_U32 },
137 };
138 
139 DEFINE_TYPE_SYSTEM(nfnl_nft_set);
140 
141 static const NLType nfnl_nft_setelem_types[] = {
142         [NFTA_SET_ELEM_KEY]   = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
143         [NFTA_SET_ELEM_DATA]  = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
144         [NFTA_SET_ELEM_FLAGS] = { .type = NETLINK_TYPE_U32 },
145 };
146 
147 DEFINE_TYPE_SYSTEM(nfnl_nft_setelem);
148 
149 static const NLType nfnl_nft_setelem_list_types[] = {
150         [NFTA_SET_ELEM_LIST_TABLE]    = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
151         [NFTA_SET_ELEM_LIST_SET]      = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
152         [NFTA_SET_ELEM_LIST_ELEMENTS] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_type_system },
153 };
154 
155 DEFINE_TYPE_SYSTEM(nfnl_nft_setelem_list);
156 
157 static const NLType nfnl_subsys_nft_types [] = {
158         [NFT_MSG_DELTABLE]   = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_table_type_system,        .size = sizeof(struct nfgenmsg) },
159         [NFT_MSG_NEWTABLE]   = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_table_type_system,        .size = sizeof(struct nfgenmsg) },
160         [NFT_MSG_NEWCHAIN]   = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_chain_type_system,        .size = sizeof(struct nfgenmsg) },
161         [NFT_MSG_NEWRULE]    = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_rule_type_system,         .size = sizeof(struct nfgenmsg) },
162         [NFT_MSG_NEWSET]     = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_set_type_system,          .size = sizeof(struct nfgenmsg) },
163         [NFT_MSG_NEWSETELEM] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_list_type_system, .size = sizeof(struct nfgenmsg) },
164         [NFT_MSG_DELSETELEM] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_list_type_system, .size = sizeof(struct nfgenmsg) },
165 };
166 
167 DEFINE_TYPE_SYSTEM(nfnl_subsys_nft);
168 
169 static const NLType nfnl_msg_batch_types [] = {
170         [NFNL_BATCH_GENID] = { .type = NETLINK_TYPE_U32 }
171 };
172 
173 DEFINE_TYPE_SYSTEM(nfnl_msg_batch);
174 
175 static const NLType nfnl_subsys_none_types[] = {
176         [NFNL_MSG_BATCH_BEGIN] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_msg_batch_type_system, .size = sizeof(struct nfgenmsg) },
177         [NFNL_MSG_BATCH_END]   = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_msg_batch_type_system, .size = sizeof(struct nfgenmsg) },
178 };
179 
180 DEFINE_TYPE_SYSTEM(nfnl_subsys_none);
181 
182 static const NLType nfnl_types[] = {
183         [NFNL_SUBSYS_NONE]     = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_subsys_none_type_system },
184         [NFNL_SUBSYS_NFTABLES] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_subsys_nft_type_system },
185 };
186 
187 DEFINE_TYPE_SYSTEM(nfnl);
188 
nfnl_get_type(uint16_t nlmsg_type)189 const NLType *nfnl_get_type(uint16_t nlmsg_type) {
190         const NLTypeSystem *subsys;
191 
192         subsys = type_system_get_type_system(&nfnl_type_system, nlmsg_type >> 8);
193         if (!subsys)
194                 return NULL;
195 
196         return type_system_get_type(subsys, nlmsg_type & ((1U << 8) - 1));
197 }
198