1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include <netinet/in.h>
4 #include <linux/if_addrlabel.h>
5 #include <linux/netfilter/nfnetlink.h>
6 #include <linux/netfilter/nf_tables.h>
7 #include <linux/nexthop.h>
11 #include "sd-netlink.h"
13 #include "format-util.h"
14 #include "netlink-internal.h"
15 #include "netlink-types.h"
16 #include "netlink-util.h"
17 #include "socket-util.h"
20 static int nft_message_new(sd_netlink
*nfnl
, sd_netlink_message
**ret
, int family
, uint16_t type
, uint16_t flags
) {
21 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
23 const NLType
*nl_type
;
27 assert_return(nfnl
, -EINVAL
);
29 r
= type_system_root_get_type(nfnl
, &nl_type
, NFNL_SUBSYS_NFTABLES
);
33 if (type_get_type(nl_type
) != NETLINK_TYPE_NESTED
)
36 r
= message_new_empty(nfnl
, &m
);
40 size
= NLMSG_SPACE(type_get_size(nl_type
));
42 assert(size
>= sizeof(struct nlmsghdr
));
43 m
->hdr
= malloc0(size
);
47 m
->hdr
->nlmsg_flags
= NLM_F_REQUEST
| flags
;
49 type_get_type_system(nl_type
, &m
->containers
[0].type_system
);
51 r
= type_system_get_type_system(m
->containers
[0].type_system
,
52 &m
->containers
[0].type_system
,
57 m
->hdr
->nlmsg_len
= size
;
58 m
->hdr
->nlmsg_type
= NFNL_SUBSYS_NFTABLES
<< 8 | type
;
60 nfh
= NLMSG_DATA(m
->hdr
);
61 nfh
->nfgen_family
= family
;
62 nfh
->version
= NFNETLINK_V0
;
63 nfh
->res_id
= nfnl
->serial
;
69 static int sd_nfnl_message_batch(sd_netlink
*nfnl
, sd_netlink_message
**ret
, int v
) {
70 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
74 r
= message_new(nfnl
, &m
, v
);
78 nfh
= NLMSG_DATA(m
->hdr
);
79 nfh
->nfgen_family
= AF_UNSPEC
;
80 nfh
->version
= NFNETLINK_V0
;
81 nfh
->res_id
= NFNL_SUBSYS_NFTABLES
;
87 int sd_nfnl_message_batch_begin(sd_netlink
*nfnl
, sd_netlink_message
**ret
) {
88 return sd_nfnl_message_batch(nfnl
, ret
, NFNL_MSG_BATCH_BEGIN
);
91 int sd_nfnl_message_batch_end(sd_netlink
*nfnl
, sd_netlink_message
**ret
) {
92 return sd_nfnl_message_batch(nfnl
, ret
, NFNL_MSG_BATCH_END
);
95 int sd_nfnl_nft_message_new_basechain(sd_netlink
*nfnl
, sd_netlink_message
**ret
,
97 const char *table
, const char *chain
,
99 uint8_t hook
, int prio
) {
100 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
103 r
= nft_message_new(nfnl
, &m
, family
, NFT_MSG_NEWCHAIN
, NLM_F_CREATE
| NLM_F_ACK
);
107 r
= sd_netlink_message_append_string(m
, NFTA_CHAIN_TABLE
, table
);
111 r
= sd_netlink_message_append_string(m
, NFTA_CHAIN_NAME
, chain
);
115 r
= sd_netlink_message_append_string(m
, NFTA_CHAIN_TYPE
, type
);
119 r
= sd_netlink_message_open_container(m
, NFTA_CHAIN_HOOK
);
123 r
= sd_netlink_message_append_u32(m
, NFTA_HOOK_HOOKNUM
, htobe32(hook
));
127 r
= sd_netlink_message_append_u32(m
, NFTA_HOOK_PRIORITY
, htobe32(prio
));
131 r
= sd_netlink_message_close_container(m
);
139 int sd_nfnl_nft_message_del_table(sd_netlink
*nfnl
, sd_netlink_message
**ret
,
140 int family
, const char *table
) {
141 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
144 r
= nft_message_new(nfnl
, &m
, family
, NFT_MSG_DELTABLE
, NLM_F_CREATE
| NLM_F_ACK
);
148 r
= sd_netlink_message_append_string(m
, NFTA_TABLE_NAME
, table
);
156 int sd_nfnl_nft_message_new_table(sd_netlink
*nfnl
, sd_netlink_message
**ret
,
157 int family
, const char *table
, uint16_t flags
) {
158 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
161 r
= nft_message_new(nfnl
, &m
, family
, NFT_MSG_NEWTABLE
, NLM_F_CREATE
| flags
);
165 r
= sd_netlink_message_append_string(m
, NFTA_TABLE_NAME
, table
);
173 int sd_nfnl_nft_message_new_rule(sd_netlink
*nfnl
, sd_netlink_message
**ret
,
174 int family
, const char *table
, const char *chain
) {
175 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
178 r
= nft_message_new(nfnl
, &m
, family
, NFT_MSG_NEWRULE
, NLM_F_CREATE
| NLM_F_ACK
);
182 r
= sd_netlink_message_append_string(m
, NFTA_RULE_TABLE
, table
);
186 r
= sd_netlink_message_append_string(m
, NFTA_RULE_CHAIN
, chain
);
194 int sd_nfnl_nft_message_new_set(sd_netlink
*nfnl
, sd_netlink_message
**ret
,
195 int family
, const char *table
, const char *set_name
,
196 uint32_t set_id
, uint32_t klen
) {
197 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
200 r
= nft_message_new(nfnl
, &m
, family
, NFT_MSG_NEWSET
, NLM_F_CREATE
| NLM_F_ACK
);
204 r
= sd_netlink_message_append_string(m
, NFTA_SET_TABLE
, table
);
208 r
= sd_netlink_message_append_string(m
, NFTA_SET_NAME
, set_name
);
212 r
= sd_netlink_message_append_u32(m
, NFTA_SET_ID
, ++set_id
);
216 r
= sd_netlink_message_append_u32(m
, NFTA_SET_KEY_LEN
, htobe32(klen
));
223 int sd_nfnl_nft_message_new_setelems_begin(sd_netlink
*nfnl
, sd_netlink_message
**ret
,
224 int family
, const char *table
, const char *set_name
) {
225 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
228 r
= nft_message_new(nfnl
, &m
, family
, NFT_MSG_NEWSETELEM
, NLM_F_CREATE
| NLM_F_ACK
);
232 r
= sd_netlink_message_append_string(m
, NFTA_SET_ELEM_LIST_TABLE
, table
);
236 r
= sd_netlink_message_append_string(m
, NFTA_SET_ELEM_LIST_SET
, set_name
);
240 r
= sd_netlink_message_open_container(m
, NFTA_SET_ELEM_LIST_ELEMENTS
);
248 int sd_nfnl_nft_message_del_setelems_begin(sd_netlink
*nfnl
, sd_netlink_message
**ret
,
249 int family
, const char *table
, const char *set_name
) {
250 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
253 r
= nft_message_new(nfnl
, &m
, family
, NFT_MSG_DELSETELEM
, NLM_F_ACK
);
257 r
= sd_netlink_message_append_string(m
, NFTA_SET_ELEM_LIST_TABLE
, table
);
261 r
= sd_netlink_message_append_string(m
, NFTA_SET_ELEM_LIST_SET
, set_name
);
265 r
= sd_netlink_message_open_container(m
, NFTA_SET_ELEM_LIST_ELEMENTS
);
273 static int sd_nfnl_add_data(sd_netlink_message
*m
, uint16_t attr
, const void *data
, uint32_t dlen
) {
274 int r
= sd_netlink_message_open_container(m
, attr
);
278 r
= sd_netlink_message_append_data(m
, NFTA_DATA_VALUE
, data
, dlen
);
282 return sd_netlink_message_close_container(m
); /* attr */
285 int sd_nfnl_nft_message_add_setelem(sd_netlink_message
*m
, uint32_t num
,
286 const void *key
, uint32_t klen
,
287 const void *data
, uint32_t dlen
) {
290 r
= sd_netlink_message_open_array(m
, num
);
294 r
= sd_nfnl_add_data(m
, NFTA_SET_ELEM_KEY
, key
, klen
);
299 r
= sd_nfnl_add_data(m
, NFTA_SET_ELEM_DATA
, data
, dlen
);
306 sd_netlink_message_cancel_array(m
);
310 int sd_nfnl_nft_message_add_setelem_end(sd_netlink_message
*m
) {
311 return sd_netlink_message_close_container(m
); /* NFTA_SET_ELEM_LIST_ELEMENTS */
314 int sd_nfnl_socket_open(sd_netlink
**ret
) {
315 return netlink_open_family(ret
, NETLINK_NETFILTER
);