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 static struct nlmsghdr *__nftnl_nlmsg_build_hdr(
char *buf, uint16_t type,
27 uint16_t flags, uint32_t seq,
33 nlh = mnl_nlmsg_put_header(buf);
34 nlh->nlmsg_type = type;
35 nlh->nlmsg_flags = NLM_F_REQUEST | flags;
38 nfh = mnl_nlmsg_put_extra_header(nlh,
sizeof(
struct nfgenmsg));
39 nfh->nfgen_family = family;
40 nfh->version = NFNETLINK_V0;
46 struct nlmsghdr *nftnl_nlmsg_build_hdr(
char *buf, uint16_t type, uint16_t family,
47 uint16_t flags, uint32_t seq)
49 return __nftnl_nlmsg_build_hdr(buf, (NFNL_SUBSYS_NFTABLES << 8) | type,
50 family, flags, seq, 0);
52 EXPORT_SYMBOL(nftnl_nlmsg_build_hdr);
54 struct nftnl_parse_err *nftnl_parse_err_alloc(
void)
56 struct nftnl_parse_err *err;
58 err = calloc(1,
sizeof(
struct nftnl_parse_err));
62 err->error = NFTNL_PARSE_EOPNOTSUPP;
66 EXPORT_SYMBOL(nftnl_parse_err_alloc);
68 void nftnl_parse_err_free(
struct nftnl_parse_err *err)
72 EXPORT_SYMBOL(nftnl_parse_err_free);
74 int nftnl_parse_perror(
const char *msg,
struct nftnl_parse_err *err)
77 case NFTNL_PARSE_EBADINPUT:
78 return fprintf(stderr,
"%s: Bad input format in line %d column %d\n",
79 msg, err->line, err->column);
80 case NFTNL_PARSE_EMISSINGNODE:
81 return fprintf(stderr,
"%s: Node \"%s\" not found\n",
83 case NFTNL_PARSE_EBADTYPE:
84 return fprintf(stderr,
"%s: Invalid type in node \"%s\"\n",
86 case NFTNL_PARSE_EOPNOTSUPP:
87 return fprintf(stderr,
"%s: Operation not supported\n", msg);
89 return fprintf(stderr,
"%s: Undefined error\n", msg);
92 EXPORT_SYMBOL(nftnl_parse_perror);
94 int nftnl_cmd_header_snprintf(
char *buf,
size_t size, uint32_t cmd, uint32_t type,
97 NFTNL_BUF_INIT(b, buf, size);
99 if (cmd == NFTNL_CMD_UNSPEC)
103 case NFTNL_OUTPUT_XML:
104 case NFTNL_OUTPUT_JSON:
105 nftnl_buf_open_array(&b, type, nftnl_cmd2tag(cmd));
110 return snprintf(buf, size,
"%9s",
"[ADD] ");
111 case NFTNL_CMD_DELETE:
112 return snprintf(buf, size,
"%9s",
"[DELETE] ");
114 return snprintf(buf, size,
"%9s",
"[unknown] ");
118 return nftnl_buf_done(&b);
121 static int nftnl_cmd_header_fprintf_cb(
char *buf,
size_t size,
const void *obj,
122 uint32_t cmd, uint32_t type,
125 return nftnl_cmd_header_snprintf(buf, size, cmd, type, flags);
128 int nftnl_cmd_header_fprintf(FILE *fp, uint32_t cmd, uint32_t type,
131 return nftnl_fprintf(fp, NULL, cmd, type, flags,
132 nftnl_cmd_header_fprintf_cb);
135 int nftnl_cmd_footer_snprintf(
char *buf,
size_t size, uint32_t cmd, uint32_t type,
138 NFTNL_BUF_INIT(b, buf, size);
140 if (cmd == NFTNL_CMD_UNSPEC)
144 case NFTNL_OUTPUT_XML:
145 case NFTNL_OUTPUT_JSON:
146 nftnl_buf_close_array(&b, type, nftnl_cmd2tag(cmd));
151 return nftnl_buf_done(&b);
154 static int nftnl_cmd_footer_fprintf_cb(
char *buf,
size_t size,
const void *obj,
155 uint32_t cmd, uint32_t type,
158 return nftnl_cmd_footer_snprintf(buf, size, cmd, type, flags);
161 int nftnl_cmd_footer_fprintf(FILE *fp, uint32_t cmd, uint32_t type,
164 return nftnl_fprintf(fp, NULL, cmd, type, flags,
165 nftnl_cmd_footer_fprintf_cb);
168 struct nlmsghdr *nftnl_batch_begin(
char *buf, uint32_t seq)
170 return __nftnl_nlmsg_build_hdr(buf, NFNL_MSG_BATCH_BEGIN, AF_UNSPEC,
171 0, seq, NFNL_SUBSYS_NFTABLES);
173 EXPORT_SYMBOL(nftnl_batch_begin);
175 struct nlmsghdr *nftnl_batch_end(
char *buf, uint32_t seq)
177 return __nftnl_nlmsg_build_hdr(buf, NFNL_MSG_BATCH_END, AF_UNSPEC,
178 0, seq, NFNL_SUBSYS_NFTABLES);
180 EXPORT_SYMBOL(nftnl_batch_end);
182 int nftnl_batch_is_supported(
void)
184 struct mnl_socket *nl;
185 struct mnl_nlmsg_batch *b;
186 char buf[MNL_SOCKET_BUFFER_SIZE];
187 uint32_t seq = time(NULL), req_seq;
190 nl = mnl_socket_open(NETLINK_NETFILTER);
194 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
197 b = mnl_nlmsg_batch_start(buf,
sizeof(buf));
199 nftnl_batch_begin(mnl_nlmsg_batch_current(b), seq++);
200 mnl_nlmsg_batch_next(b);
203 nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(b),
204 NFT_MSG_NEWSET, AF_INET,
206 mnl_nlmsg_batch_next(b);
208 nftnl_batch_end(mnl_nlmsg_batch_current(b), seq++);
209 mnl_nlmsg_batch_next(b);
211 ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(b),
212 mnl_nlmsg_batch_size(b));
216 mnl_nlmsg_batch_stop(b);
218 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
220 ret = mnl_cb_run(buf, ret, req_seq, mnl_socket_get_portid(nl),
225 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
227 mnl_socket_close(nl);
234 return (ret == -1 && errno == EINVAL) ? 1 : 0;
236 mnl_nlmsg_batch_stop(b);
239 EXPORT_SYMBOL(nftnl_batch_is_supported);