11 #include <sys/socket.h>
13 #include <linux/netlink.h>
14 #include <linux/netfilter/nfnetlink.h>
15 #include <linux/netfilter/nf_tables.h>
17 #include <libmnl/libmnl.h>
18 #include <libnftnl/common.h>
19 #include <libnftnl/set.h>
25 struct nlmsghdr *nftnl_nlmsg_build_hdr(
char *buf, uint16_t cmd, uint16_t family,
26 uint16_t type, uint32_t seq)
31 nlh = mnl_nlmsg_put_header(buf);
32 nlh->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | cmd;
33 nlh->nlmsg_flags = NLM_F_REQUEST | type;
36 nfh = mnl_nlmsg_put_extra_header(nlh,
sizeof(
struct nfgenmsg));
37 nfh->nfgen_family = family;
38 nfh->version = NFNETLINK_V0;
43 EXPORT_SYMBOL(nftnl_nlmsg_build_hdr, nft_nlmsg_build_hdr);
45 struct nftnl_parse_err *nftnl_parse_err_alloc(
void)
47 struct nftnl_parse_err *err;
49 err = calloc(1,
sizeof(
struct nftnl_parse_err));
53 err->error = NFTNL_PARSE_EOPNOTSUPP;
57 EXPORT_SYMBOL(nftnl_parse_err_alloc, nft_parse_err_alloc);
59 void nftnl_parse_err_free(
struct nftnl_parse_err *err)
63 EXPORT_SYMBOL(nftnl_parse_err_free, nft_parse_err_free);
65 int nftnl_parse_perror(
const char *msg,
struct nftnl_parse_err *err)
68 case NFTNL_PARSE_EBADINPUT:
69 return fprintf(stderr,
"%s: Bad input format in line %d column %d\n",
70 msg, err->line, err->column);
71 case NFTNL_PARSE_EMISSINGNODE:
72 return fprintf(stderr,
"%s: Node \"%s\" not found\n",
74 case NFTNL_PARSE_EBADTYPE:
75 return fprintf(stderr,
"%s: Invalid type in node \"%s\"\n",
77 case NFTNL_PARSE_EOPNOTSUPP:
78 return fprintf(stderr,
"%s: Operation not supported\n", msg);
80 return fprintf(stderr,
"%s: Undefined error\n", msg);
83 EXPORT_SYMBOL(nftnl_parse_perror, nft_parse_perror);
85 int nftnl_cmd_header_snprintf(
char *buf,
size_t size, uint32_t cmd, uint32_t type,
88 NFTNL_BUF_INIT(b, buf, size);
90 if (cmd == NFTNL_CMD_UNSPEC)
94 case NFTNL_OUTPUT_XML:
95 case NFTNL_OUTPUT_JSON:
96 nftnl_buf_open_array(&b, type, nftnl_cmd2tag(cmd));
101 return snprintf(buf, size,
"%9s",
"[ADD] ");
102 case NFTNL_CMD_DELETE:
103 return snprintf(buf, size,
"%9s",
"[DELETE] ");
105 return snprintf(buf, size,
"%9s",
"[unknown] ");
109 return nftnl_buf_done(&b);
112 static int nftnl_cmd_header_fprintf_cb(
char *buf,
size_t size,
void *obj,
113 uint32_t cmd, uint32_t type,
116 return nftnl_cmd_header_snprintf(buf, size, cmd, type, flags);
119 int nftnl_cmd_header_fprintf(FILE *fp, uint32_t cmd, uint32_t type,
122 return nftnl_fprintf(fp, NULL, cmd, type, flags,
123 nftnl_cmd_header_fprintf_cb);
126 int nftnl_cmd_footer_snprintf(
char *buf,
size_t size, uint32_t cmd, uint32_t type,
129 NFTNL_BUF_INIT(b, buf, size);
131 if (cmd == NFTNL_CMD_UNSPEC)
135 case NFTNL_OUTPUT_XML:
136 case NFTNL_OUTPUT_JSON:
137 nftnl_buf_close_array(&b, type, nftnl_cmd2tag(cmd));
142 return nftnl_buf_done(&b);
145 static int nftnl_cmd_footer_fprintf_cb(
char *buf,
size_t size,
void *obj,
146 uint32_t cmd, uint32_t type,
149 return nftnl_cmd_footer_snprintf(buf, size, cmd, type, flags);
152 int nftnl_cmd_footer_fprintf(FILE *fp, uint32_t cmd, uint32_t type,
155 return nftnl_fprintf(fp, NULL, cmd, type, flags,
156 nftnl_cmd_footer_fprintf_cb);
159 static void nftnl_batch_build_hdr(
char *buf, uint16_t type, uint32_t seq)
161 struct nlmsghdr *nlh;
162 struct nfgenmsg *nfg;
164 nlh = mnl_nlmsg_put_header(buf);
165 nlh->nlmsg_type = type;
166 nlh->nlmsg_flags = NLM_F_REQUEST;
167 nlh->nlmsg_seq = seq;
169 nfg = mnl_nlmsg_put_extra_header(nlh,
sizeof(*nfg));
170 nfg->nfgen_family = AF_UNSPEC;
171 nfg->version = NFNETLINK_V0;
172 nfg->res_id = NFNL_SUBSYS_NFTABLES;
175 void nftnl_batch_begin(
char *buf, uint32_t seq)
177 nftnl_batch_build_hdr(buf, NFNL_MSG_BATCH_BEGIN, seq);
179 EXPORT_SYMBOL(nftnl_batch_begin, nft_batch_begin);
181 void nftnl_batch_end(
char *buf, uint32_t seq)
183 nftnl_batch_build_hdr(buf, NFNL_MSG_BATCH_END, seq);
185 EXPORT_SYMBOL(nftnl_batch_end, nft_batch_end);
187 int nftnl_batch_is_supported(
void)
189 struct mnl_socket *nl;
190 struct mnl_nlmsg_batch *b;
191 char buf[MNL_SOCKET_BUFFER_SIZE];
192 uint32_t seq = time(NULL), req_seq;
195 nl = mnl_socket_open(NETLINK_NETFILTER);
199 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
202 b = mnl_nlmsg_batch_start(buf,
sizeof(buf));
204 nftnl_batch_begin(mnl_nlmsg_batch_current(b), seq++);
205 mnl_nlmsg_batch_next(b);
208 nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(b),
209 NFT_MSG_NEWSET, AF_INET,
211 mnl_nlmsg_batch_next(b);
213 nftnl_batch_end(mnl_nlmsg_batch_current(b), seq++);
214 mnl_nlmsg_batch_next(b);
216 ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(b),
217 mnl_nlmsg_batch_size(b));
221 mnl_nlmsg_batch_stop(b);
223 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
225 ret = mnl_cb_run(buf, ret, req_seq, mnl_socket_get_portid(nl),
230 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
232 mnl_socket_close(nl);
239 return (ret == -1 && errno == EINVAL) ? 1 : 0;
241 mnl_nlmsg_batch_stop(b);
244 EXPORT_SYMBOL(nftnl_batch_is_supported, nft_batch_is_supported);