1384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/*
2384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
3384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso *
4384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * This program is free software; you can redistribute it and/or modify
5384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * it under the terms of the GNU General Public License as published
6384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * by the Free Software Foundation; either version 2 of the License, or
7384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * (at your option) any later version.
8384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso *
9384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * This code has been sponsored by Sophos Astaro <http://www.sophos.com>
10384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso */
11384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
12384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <unistd.h>
13384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <fcntl.h>
14384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <sys/types.h>
15384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <sys/socket.h>
16384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <stdbool.h>
17384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <errno.h>
18384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <netdb.h>	/* getprotobynumber */
19384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <time.h>
208b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso#include <stdarg.h>
210a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo#include <inttypes.h>
22384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
23384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <xtables.h>
24384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libiptc/libxtc.h>
25384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libiptc/xtcshared.h>
26384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
27384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <stdlib.h>
28384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <string.h>
29384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
30384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/x_tables.h>
310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka#include <linux/netfilter_ipv4/ip_tables.h>
320391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka#include <linux/netfilter_ipv6/ip6_tables.h>
330391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka#include <netinet/ip6.h>
34384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
35384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netlink.h>
36384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nfnetlink.h>
37384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nf_tables.h>
38384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nf_tables_compat.h>
39384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
40384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libmnl/libmnl.h>
41a4e1098169a67716a81316c36ce22ddcb33df1c0Tomasz Bursztyka#include <libnftnl/table.h>
42a4e1098169a67716a81316c36ce22ddcb33df1c0Tomasz Bursztyka#include <libnftnl/chain.h>
43a4e1098169a67716a81316c36ce22ddcb33df1c0Tomasz Bursztyka#include <libnftnl/rule.h>
44a4e1098169a67716a81316c36ce22ddcb33df1c0Tomasz Bursztyka#include <libnftnl/expr.h>
45f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso#include <libnftnl/set.h>
46d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay#include <libnftnl/udata.h>
47384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
48384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <netinet/in.h>	/* inet_ntoa */
49384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <arpa/inet.h>
50384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
51384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include "nft.h"
52384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include "xshared.h" /* proto_to_name */
53077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka#include "nft-shared.h"
548b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso#include "xtables-config-parser.h"
55384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
56384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void *nft_fn;
57384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
5884909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longoint mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
5984909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	     int (*cb)(const struct nlmsghdr *nlh, void *data),
6084909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	     void *data)
61384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
62384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
63384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
64384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
65cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0)
66384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
67384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
68384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
69384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (ret > 0) {
70384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = mnl_cb_run(buf, ret, h->seq, h->portid, cb, data);
71384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (ret <= 0)
72384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
73384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
74384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
75384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
76384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
77384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
78384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
79384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
80384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
81384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
82384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
83d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic LIST_HEAD(batch_page_list);
84d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic int batch_num_pages;
85d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
86d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostruct batch_page {
87d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct list_head	head;
88d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct mnl_nlmsg_batch	*batch;
89d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso};
90d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
91d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso/* selected batch page is 256 Kbytes long to load ruleset of
92d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso * half a million rules without hitting -EMSGSIZE due to large
93d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso * iovec.
94d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso */
95d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso#define BATCH_PAGE_SIZE getpagesize() * 32
96d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
97742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic struct mnl_nlmsg_batch *mnl_nftnl_batch_alloc(void)
98d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
99d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	static char *buf;
100d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
101d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	/* libmnl needs higher buffer to handle batch overflows */
102d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	buf = malloc(BATCH_PAGE_SIZE + getpagesize());
103d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (buf == NULL)
104d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return NULL;
105d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
106d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return mnl_nlmsg_batch_start(buf, BATCH_PAGE_SIZE);
107d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
108d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
109d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic struct mnl_nlmsg_batch *
110742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusomnl_nftnl_batch_page_add(struct mnl_nlmsg_batch *batch)
111d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
112d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct batch_page *batch_page;
113d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
114d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	batch_page = malloc(sizeof(struct batch_page));
115d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (batch_page == NULL)
116d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return NULL;
117d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
118d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	batch_page->batch = batch;
119d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	list_add_tail(&batch_page->head, &batch_page_list);
120d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	batch_num_pages++;
121d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
122742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	return mnl_nftnl_batch_alloc();
123d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
124d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
125d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic int nlbuffsiz;
126d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
127d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic void mnl_nft_set_sndbuffer(const struct mnl_socket *nl)
128d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
129d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	int newbuffsiz;
130d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
131d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (batch_num_pages * BATCH_PAGE_SIZE <= nlbuffsiz)
132d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return;
133d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
134d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	newbuffsiz = batch_num_pages * BATCH_PAGE_SIZE;
135d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
136d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	/* Rise sender buffer length to avoid hitting -EMSGSIZE */
137d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (setsockopt(mnl_socket_get_fd(nl), SOL_SOCKET, SO_SNDBUFFORCE,
138d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		       &newbuffsiz, sizeof(socklen_t)) < 0)
139d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return;
140d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
141d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	nlbuffsiz = newbuffsiz;
142d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
143d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
144742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic void mnl_nftnl_batch_reset(void)
1459470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso{
1469470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso	struct batch_page *batch_page, *next;
1479470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso
1489470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso	list_for_each_entry_safe(batch_page, next, &batch_page_list, head) {
1499470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso		list_del(&batch_page->head);
1509470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso		free(batch_page->batch);
1519470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso		free(batch_page);
1529470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso		batch_num_pages--;
1539470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso	}
1549470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso}
1559470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso
156d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nl)
157d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
158d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	static const struct sockaddr_nl snl = {
159d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.nl_family = AF_NETLINK
160d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	};
161d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct iovec iov[batch_num_pages];
162d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct msghdr msg = {
163d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.msg_name	= (struct sockaddr *) &snl,
164d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.msg_namelen	= sizeof(snl),
165d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.msg_iov	= iov,
166d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.msg_iovlen	= batch_num_pages,
167d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	};
1689470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso	struct batch_page *batch_page;
1699470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso	int i = 0, ret;
170d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
171d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	mnl_nft_set_sndbuffer(nl);
172d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
1739470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso	list_for_each_entry(batch_page, &batch_page_list, head) {
174d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		iov[i].iov_base = mnl_nlmsg_batch_head(batch_page->batch);
175d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		iov[i].iov_len = mnl_nlmsg_batch_size(batch_page->batch);
176d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		i++;
177d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso#ifdef NL_DEBUG
178d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		mnl_nlmsg_fprintf(stdout,
179d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso				  mnl_nlmsg_batch_head(batch_page->batch),
180d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso				  mnl_nlmsg_batch_size(batch_page->batch),
181d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso				  sizeof(struct nfgenmsg));
182d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso#endif
183d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	}
184d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
1859470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso	ret = sendmsg(mnl_socket_get_fd(nl), &msg, 0);
186742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	mnl_nftnl_batch_reset();
1879470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso
1889470040d53ca7136b54f32507fe3d31d12736d22Pablo Neira Ayuso	return ret;
189d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
190d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
191742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic int mnl_nftnl_batch_talk(struct nft_handle *h)
192d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
193d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	int ret, fd = mnl_socket_get_fd(h->nl);
194d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	char rcv_buf[MNL_SOCKET_BUFFER_SIZE];
195d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	fd_set readfds;
196d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct timeval tv = {
197d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.tv_sec		= 0,
198d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.tv_usec	= 0
199d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	};
200d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	int err = 0;
201d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
202d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	ret = mnl_nft_socket_sendmsg(h->nl);
203cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (ret == -1)
204d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return -1;
205d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
206d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	FD_ZERO(&readfds);
207d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	FD_SET(fd, &readfds);
208d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
209d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	/* receive and digest all the acknowledgments from the kernel. */
210d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	ret = select(fd+1, &readfds, NULL, NULL, &tv);
211cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (ret == -1)
212d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return -1;
213cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso
214d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	while (ret > 0 && FD_ISSET(fd, &readfds)) {
215d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		ret = mnl_socket_recvfrom(h->nl, rcv_buf, sizeof(rcv_buf));
216cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso		if (ret == -1)
217d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			return -1;
218d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2193f37696b7ce5bea29e742f7d8efc33dd82fb878cPablo Neira Ayuso		ret = mnl_cb_run(rcv_buf, ret, 0, h->portid, NULL, NULL);
2203f37696b7ce5bea29e742f7d8efc33dd82fb878cPablo Neira Ayuso		/* Annotate first error and continue, make sure we get all
2213f37696b7ce5bea29e742f7d8efc33dd82fb878cPablo Neira Ayuso		 * acknoledgments.
2223f37696b7ce5bea29e742f7d8efc33dd82fb878cPablo Neira Ayuso		 */
2233f37696b7ce5bea29e742f7d8efc33dd82fb878cPablo Neira Ayuso		if (!err && ret == -1)
224d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			err = errno;
225d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
226d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		ret = select(fd+1, &readfds, NULL, NULL, &tv);
227cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso		if (ret == -1)
228d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			return -1;
229cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso
230d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		FD_ZERO(&readfds);
231d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		FD_SET(fd, &readfds);
232d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	}
2333f37696b7ce5bea29e742f7d8efc33dd82fb878cPablo Neira Ayuso	errno = err;
234d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return err ? -1 : 0;
235d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
236d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
237742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic void mnl_nftnl_batch_begin(struct mnl_nlmsg_batch *batch, uint32_t seq)
238d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
239742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq);
240d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (!mnl_nlmsg_batch_next(batch))
241742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		mnl_nftnl_batch_page_add(batch);
242d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
243d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
244742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic void mnl_nftnl_batch_end(struct mnl_nlmsg_batch *batch, uint32_t seq)
245d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
246742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq);
2471f932f08a17c55f1689a432433f9f2a0cf6f014fPablo Neira Ayuso	if (!mnl_nlmsg_batch_next(batch))
248742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		mnl_nftnl_batch_page_add(batch);
249d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
250d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
251f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusoenum obj_update_type {
252f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	NFT_COMPAT_TABLE_ADD,
253f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	NFT_COMPAT_CHAIN_ADD,
2541d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	NFT_COMPAT_CHAIN_USER_ADD,
2551d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	NFT_COMPAT_CHAIN_USER_DEL,
256f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	NFT_COMPAT_CHAIN_UPDATE,
257d87b76cfc3b1c003fec75b8a4ea639aa444014f3Arturo Borrero	NFT_COMPAT_CHAIN_RENAME,
258f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	NFT_COMPAT_RULE_APPEND,
259f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	NFT_COMPAT_RULE_INSERT,
260f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	NFT_COMPAT_RULE_REPLACE,
261f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	NFT_COMPAT_RULE_DELETE,
262f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	NFT_COMPAT_RULE_FLUSH,
263f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso};
264f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
265f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusoenum obj_action {
266f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	NFT_COMPAT_COMMIT,
267f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	NFT_COMPAT_ABORT,
268f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso};
269f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
270f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusostruct obj_update {
271f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	struct list_head	head;
272f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	enum obj_update_type	type;
273f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	union {
274742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		struct nftnl_table	*table;
275742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		struct nftnl_chain	*chain;
276742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		struct nftnl_rule		*rule;
277f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		void			*ptr;
278f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	};
279f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso};
280f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
281f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusostatic int batch_add(struct nft_handle *h, enum obj_update_type type, void *ptr)
282f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso{
283f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	struct obj_update *obj;
284f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
285f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	obj = calloc(1, sizeof(struct obj_update));
286f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	if (obj == NULL)
287f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		return -1;
288f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
289f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	obj->ptr = ptr;
290f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	obj->type = type;
291f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	list_add_tail(&obj->head, &h->obj_list);
292f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	h->obj_list_num++;
293f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
294f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	return 0;
295f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso}
296f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
297f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusostatic int batch_table_add(struct nft_handle *h, enum obj_update_type type,
298742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			   struct nftnl_table *t)
299f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso{
300f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	return batch_add(h, type, t);
301f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso}
302f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
303f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusostatic int batch_chain_add(struct nft_handle *h, enum obj_update_type type,
304742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			   struct nftnl_chain *c)
305f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso{
306f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	return batch_add(h, type, c);
307f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso}
308f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
309f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusostatic int batch_rule_add(struct nft_handle *h, enum obj_update_type type,
310742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			  struct nftnl_rule *r)
311f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso{
312f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	return batch_add(h, type, r);
313f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso}
314f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
315afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longostruct builtin_table xtables_ipv4[TABLES_MAX] = {
316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[RAW] = {
317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "raw",
318e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
319e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
320e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "PREROUTING",
321890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3225b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -300,	/* NF_IP_PRI_RAW */
323e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
324e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
325e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
326e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
327890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3285b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -300,	/* NF_IP_PRI_RAW */
329e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
330e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
331e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
332384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
333384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[MANGLE] = {
334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "mangle",
335e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
336e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
337e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "PREROUTING",
338890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3395b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
340e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
341e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
342e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
343e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
344890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3455b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
346e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
347e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
348e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
349e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
350890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3515b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
352e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
353e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
354e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
355e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
356890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "route",
3575b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
358e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
359e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
360e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
361e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "POSTROUTING",
362890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3635b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
364e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_POST_ROUTING,
365e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
366e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[FILTER] = {
369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "filter",
370e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
371e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
372e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
373890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3745b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
375e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
376e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
377e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
378e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
379890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3805b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
381e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
382e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
383e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
384e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
385890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3865b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
387e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
388e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
389e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[SECURITY] = {
392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "security",
393e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
394e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
395e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
396890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3975b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
398e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
399e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
400e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
401e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
402890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
4035b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
404e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
405e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
406e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
407e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
408890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
4095b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
410e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
411e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		},
413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
414890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	[NAT] = {
415890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		.name	= "nat",
416890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		.chains = {
417890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
41886eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.name	= "PREROUTING",
419890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
420890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= -100, /* NF_IP_PRI_NAT_DST */
42186eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
422890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
423890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
424890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "INPUT",
425890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
426890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= 100, /* NF_IP_PRI_NAT_SRC */
427890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
428890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
429890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
430890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "POSTROUTING",
431890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
432890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= 100, /* NF_IP_PRI_NAT_SRC */
433890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_POST_ROUTING,
434890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
43586eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso			{
43686eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.name	= "OUTPUT",
43786eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.type	= "nat",
43886eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.prio	= -100, /* NF_IP_PRI_NAT_DST */
43986eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
44086eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso			},
441890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		},
442890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	},
443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso};
444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
44584909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo#include <linux/netfilter_arp.h>
44684909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo
44784909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longostruct builtin_table xtables_arp[TABLES_MAX] = {
44884909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	[FILTER] = {
44984909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	.name   = "filter",
45084909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	.chains = {
45184909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			{
45284909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.name   = "INPUT",
45384909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.type   = "filter",
45484909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.prio   = NF_IP_PRI_FILTER,
45584909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.hook   = NF_ARP_IN,
45684909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			},
45784909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			{
45884909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.name   = "FORWARD",
45984909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.type   = "filter",
46084909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.prio   = NF_IP_PRI_FILTER,
46184909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.hook   = NF_ARP_FORWARD,
46284909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			},
46384909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			{
46484909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.name   = "OUTPUT",
46584909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.type   = "filter",
46684909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.prio   = NF_IP_PRI_FILTER,
46784909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.hook   = NF_ARP_OUT,
46884909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			},
46984909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo		},
47084909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	},
47184909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo};
47284909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo
473da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso#include <linux/netfilter_bridge.h>
474da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso
475da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayusostruct builtin_table xtables_bridge[TABLES_MAX] = {
476da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso	[FILTER] = {
477da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso		.name = "filter",
478da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso		.chains = {
479da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			{
480da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.name   = "INPUT",
481da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.type   = "filter",
482da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.prio   = NF_BR_PRI_FILTER_BRIDGED,
483da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.hook   = NF_BR_LOCAL_IN,
484da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			},
485da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			{
486da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.name   = "FORWARD",
487da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.type   = "filter",
488da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.prio   = NF_BR_PRI_FILTER_BRIDGED,
489da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.hook   = NF_BR_FORWARD,
490da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			},
491da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			{
492da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.name   = "OUTPUT",
493da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.type   = "filter",
494da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.prio   = NF_BR_PRI_FILTER_BRIDGED,
495da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.hook   = NF_BR_LOCAL_OUT,
496da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			},
497da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso		},
498da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso	},
499da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso	[NAT] = {
500da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso		.name = "nat",
501da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso		.chains = {
502da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			{
503da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.name   = "PREROUTING",
504da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.type   = "filter",
505da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.prio   = NF_BR_PRI_NAT_DST_BRIDGED,
506da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.hook   = NF_BR_PRE_ROUTING,
507da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			},
508da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			{
509da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.name   = "OUTPUT",
510da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.type   = "filter",
511da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.prio   = NF_BR_PRI_NAT_DST_OTHER,
512da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.hook   = NF_BR_LOCAL_OUT,
513da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			},
514da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			{
515da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.name   = "POSTROUTING",
516da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.type   = "filter",
517da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.prio   = NF_BR_PRI_NAT_SRC,
518da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso				.hook   = NF_BR_POST_ROUTING,
519da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			},
520da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso		},
521da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso	},
522da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso};
523da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso
524742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusoint nft_table_add(struct nft_handle *h, struct nftnl_table *t, uint16_t flags)
5255b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso{
5265b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
5275b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	struct nlmsghdr *nlh;
5285b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	int ret;
5295b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
530742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nlh = nftnl_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
531f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso					NLM_F_ACK|flags, h->seq);
532742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_nlmsg_build_payload(nlh, t);
533742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_free(t);
5345b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
535837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka#ifdef NLDEBUG
536837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka	char tmp[1024];
537837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka
538837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka	nft_table_snprintf(tmp, sizeof(tmp), t, 0, 0);
5391835790d7f7517f4c101e1c1f3df5519a6c228e7Tomasz Bursztyka	printf("DEBUG: table: %s\n", tmp);
540837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
541837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka#endif
542837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka
5435b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
544f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
545f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	return (ret == 0 || (ret == -1 && errno == EEXIST)) ? 0 : -1;
546f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso}
547f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
548f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusostatic int nft_table_builtin_add(struct nft_handle *h,
549f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				 struct builtin_table *_t)
550f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso{
551742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table *t;
552f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	int ret;
553f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
554f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	if (_t->initialized)
555f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		return 0;
556f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
557742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	t = nftnl_table_alloc();
558f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	if (t == NULL)
559f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		return -1;
560f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
561742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_set(t, NFTNL_TABLE_NAME, (char *)_t->name);
562f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
563f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	if (h->batch_support)
564f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		ret = batch_table_add(h, NFT_COMPAT_TABLE_ADD, t);
565f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	else
566f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		ret = nft_table_add(h, t, NLM_F_EXCL);
567f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
568f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	if (ret == 0)
569e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka		_t->initialized = true;
570e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka
5715b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	return ret;
5725b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso}
5735b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
574742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic struct nftnl_chain *
575c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_alloc(struct builtin_table *table,
576c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			struct builtin_chain *chain, int policy)
577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
578742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
580742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_alloc();
581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL)
582c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		return NULL;
583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
584742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table->name);
585742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain->name);
586742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_set_u32(c, NFTNL_CHAIN_HOOKNUM, chain->hook);
587742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_set_u32(c, NFTNL_CHAIN_PRIO, chain->prio);
588742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, policy);
589742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_set(c, NFTNL_CHAIN_TYPE, (char *)chain->type);
590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
591c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return c;
592c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
593c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
594742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusoint nft_chain_add(struct nft_handle *h, struct nftnl_chain *c, uint16_t flags)
595c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
596c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
597c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct nlmsghdr *nlh;
598c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
599890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	/* NLM_F_CREATE requests module autoloading */
600742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
601f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso					NLM_F_ACK|flags|NLM_F_CREATE,
602890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso					h->seq);
603742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_nlmsg_build_payload(nlh, c);
604742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_free(c);
605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
606f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso#ifdef NLDEBUG
607f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	char tmp[1024];
608f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
609f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	nft_chain_snprintf(tmp, sizeof(tmp), c, 0, 0);
610f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	printf("DEBUG: chain: %s\n", tmp);
611f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
612f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso#endif
613f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
614f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
615f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso}
616f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
61763f1391a5441bb092f7a1a4023e2f158ee9231a2Pablo Neira Ayusostatic void nft_chain_builtin_add(struct nft_handle *h,
61863f1391a5441bb092f7a1a4023e2f158ee9231a2Pablo Neira Ayuso				  struct builtin_table *table,
6193599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayuso				  struct builtin_chain *chain)
620f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso{
621742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
622f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
6233599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayuso	c = nft_chain_builtin_alloc(table, chain, NF_ACCEPT);
624f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	if (c == NULL)
625f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		return;
626f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
627f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	if (h->batch_support)
628f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
629f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	else
630f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		nft_chain_add(h, c, NLM_F_EXCL);
631c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
632c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
633c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in table already exists */
63463f1391a5441bb092f7a1a4023e2f158ee9231a2Pablo Neira Ayusostatic struct builtin_table *
63584909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longonft_table_builtin_find(struct nft_handle *h, const char *table)
636c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
637c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	int i;
638c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	bool found = false;
639c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
640c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	for (i=0; i<TABLES_MAX; i++) {
64167da6075a4e7ced0e8cc452d73ce8ab06cbf8cd9Tomasz Bursztyka		if (h->tables[i].name == NULL)
642da871de2a6efb576b6378a66222c0871f4282e96Pablo Neira Ayuso			continue;
64367da6075a4e7ced0e8cc452d73ce8ab06cbf8cd9Tomasz Bursztyka
644afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longo		if (strcmp(h->tables[i].name, table) != 0)
645c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			continue;
646c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
647c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		found = true;
648c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		break;
649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
650c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
651afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longo	return found ? &h->tables[i] : NULL;
652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
654c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in chain already exists */
65563f1391a5441bb092f7a1a4023e2f158ee9231a2Pablo Neira Ayusostatic struct builtin_chain *
656e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusonft_chain_builtin_find(struct builtin_table *t, const char *chain)
657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
658e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int i;
659c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	bool found = false;
660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
661e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	for (i=0; i<NF_IP_NUMHOOKS && t->chains[i].name != NULL; i++) {
662e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (strcmp(t->chains[i].name, chain) != 0)
663e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			continue;
664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
665e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		found = true;
666e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		break;
667e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	}
668e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	return found ? &t->chains[i] : NULL;
669e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso}
670e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
6713599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayusostatic void nft_chain_builtin_init(struct nft_handle *h,
6723599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayuso				   struct builtin_table *table)
673e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso{
6743599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayuso	int i;
675742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list *list = nft_chain_dump(h);
676742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
677e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
678b06fcdb858deefe35baaaf2f2f912616fb38644bPablo Neira Ayuso	/* Initialize built-in chains if they don't exist yet */
679e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	for (i=0; i<NF_IP_NUMHOOKS && table->chains[i].name != NULL; i++) {
680b06fcdb858deefe35baaaf2f2f912616fb38644bPablo Neira Ayuso
681b06fcdb858deefe35baaaf2f2f912616fb38644bPablo Neira Ayuso		c = nft_chain_list_find(list, table->name,
682b06fcdb858deefe35baaaf2f2f912616fb38644bPablo Neira Ayuso					table->chains[i].name);
683b06fcdb858deefe35baaaf2f2f912616fb38644bPablo Neira Ayuso		if (c != NULL)
684b06fcdb858deefe35baaaf2f2f912616fb38644bPablo Neira Ayuso			continue;
685b06fcdb858deefe35baaaf2f2f912616fb38644bPablo Neira Ayuso
6863599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayuso		nft_chain_builtin_add(h, table, &table->chains[i]);
687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
688b06fcdb858deefe35baaaf2f2f912616fb38644bPablo Neira Ayuso
689742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_free(list);
690c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
691c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
6923599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayusostatic int nft_xt_builtin_init(struct nft_handle *h, const char *table)
693c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
694c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	int ret = 0;
695c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_table *t;
696c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
697afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longo	t = nft_table_builtin_find(h, table);
698c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (t == NULL) {
699c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		ret = -1;
700c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		goto out;
701c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
702ee85b1bc1bb9f91daf2004823dfa204dbc52f52aPablo Neira Ayuso	if (nft_table_builtin_add(h, t) < 0) {
703e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		/* Built-in table already initialized, skip. */
704e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (errno == EEXIST)
705e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			goto out;
706c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
7073599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayuso	nft_chain_builtin_init(h, t);
708c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusoout:
709c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return ret;
710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
712742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic bool nft_chain_builtin(struct nftnl_chain *c)
7137244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka{
7147244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka	/* Check if this chain has hook number, in that case is built-in.
7157244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka	 * Should we better export the flags to user-space via nf_tables?
7167244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka	 */
717742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	return nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM) != NULL;
7187244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka}
7197244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka
720f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusostatic bool mnl_batch_supported(struct nft_handle *h)
721f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso{
722f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
723f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	uint32_t seq = 1;
724f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	int ret;
725f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
726742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	mnl_nftnl_batch_begin(h->batch, seq++);
727f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
728742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch),
729f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				NFT_MSG_NEWSET, AF_INET,
730f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				NLM_F_ACK, seq++);
731f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	mnl_nlmsg_batch_next(h->batch);
732f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
733742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	mnl_nftnl_batch_end(h->batch, seq++);
734f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
735f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	ret = mnl_socket_sendto(h->nl, mnl_nlmsg_batch_head(h->batch),
736f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				mnl_nlmsg_batch_size(h->batch));
737f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	if (ret < 0)
738f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		goto err;
739f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
740f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	mnl_nlmsg_batch_reset(h->batch);
741f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
742f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
743f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	while (ret > 0) {
744f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(h->nl),
745f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				 NULL, NULL);
746f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		if (ret <= 0)
747f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			break;
748f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
749f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
750f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	}
751f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
752f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	/* We're sending an incomplete message to see if the kernel supports
753f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	 * set messages in batches. EINVAL means that we sent an incomplete
754f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	 * message with missing attributes. The kernel just ignores messages
755f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	 * that we cannot include in the batch.
756f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	 */
757f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	return (ret == -1 && errno == EINVAL) ? true : false;
758f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusoerr:
759f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	mnl_nlmsg_batch_reset(h->batch);
760f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	return ret;
761f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso}
762f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
763afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longoint nft_init(struct nft_handle *h, struct builtin_table *t)
764384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->nl = mnl_socket_open(NETLINK_NETFILTER);
766cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (h->nl == NULL)
767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
769cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0)
770384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
771cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso
772384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->portid = mnl_socket_get_portid(h->nl);
773afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longo	h->tables = t;
774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
775495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso	INIT_LIST_HEAD(&h->obj_list);
776d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
777742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	h->batch = mnl_nftnl_batch_alloc();
778f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	h->batch_support = mnl_batch_supported(h);
779d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
780384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
781384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
783ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garaystatic void flush_rule_cache(struct nft_handle *h)
784ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay{
785ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	if (!h->rule_cache)
786ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay		return;
787ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay
788ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	nftnl_rule_list_free(h->rule_cache);
789ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	h->rule_cache = NULL;
790ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay}
791ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay
792384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusovoid nft_fini(struct nft_handle *h)
793384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
794ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	flush_rule_cache(h);
795384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(h->nl);
796b0194cea194b510c675ca05415da15cff57afe47Ana Rey	free(mnl_nlmsg_batch_head(h->batch));
797b0194cea194b510c675ca05415da15cff57afe47Ana Rey	mnl_nlmsg_batch_stop(h->batch);
798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
800742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic void nft_chain_print_debug(struct nftnl_chain *c, struct nlmsghdr *nlh)
801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
802384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
803384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_snprintf(tmp, sizeof(tmp), c, 0, 0);
8061835790d7f7517f4c101e1c1f3df5519a6c228e7Tomasz Bursztyka	printf("DEBUG: chain: %s\n", tmp);
807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
810384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
811742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic struct nftnl_chain *nft_chain_new(struct nft_handle *h,
812f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				       const char *table, const char *chain,
813f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				       int policy,
814f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				       const struct xt_counters *counters)
815384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
816742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
817c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_table *_t;
818c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_chain *_c;
819c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
820afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longo	_t = nft_table_builtin_find(h, table);
821c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	/* if this built-in table does not exists, create it */
822c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_t != NULL)
823ee85b1bc1bb9f91daf2004823dfa204dbc52f52aPablo Neira Ayuso		nft_table_builtin_add(h, _t);
824c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
825e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	_c = nft_chain_builtin_find(_t, chain);
826c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_c != NULL) {
827c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		/* This is a built-in chain */
828c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		c = nft_chain_builtin_alloc(_t, _c, policy);
829c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		if (c == NULL)
830f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			return NULL;
831c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	} else {
83220c156f9f4c43857a622f015a3022517601c3600Tomasz Bursztyka		errno = ENOENT;
833f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		return NULL;
834c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
836384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (counters) {
837742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES,
838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->bcnt);
839742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS,
840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->pcnt);
841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
842384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
843f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	return c;
844384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
845384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
846384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_set(struct nft_handle *h, const char *table,
847384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const char *chain, const char *policy,
848384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const struct xt_counters *counters)
849384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
850742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c = NULL;
851f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	int ret;
852384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
853384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_chain_set;
854384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
855384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(policy, "DROP") == 0)
856f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		c = nft_chain_new(h, table, chain, NF_DROP, counters);
857384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else if (strcmp(policy, "ACCEPT") == 0)
858f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		c = nft_chain_new(h, table, chain, NF_ACCEPT, counters);
859f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
860f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	if (c == NULL)
861f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		return 0;
862f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
863f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	if (h->batch_support)
864f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		ret = batch_chain_add(h, NFT_COMPAT_CHAIN_UPDATE, c);
865f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	else
866f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		ret = nft_chain_add(h, c, 0);
867384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
868384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
871384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
872742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic int __add_match(struct nftnl_expr *e, struct xt_entry_match *m)
873384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	void *info;
875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
876742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set(e, NFTNL_EXPR_MT_NAME, m->u.user.name, strlen(m->u.user.name));
877742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set_u32(e, NFTNL_EXPR_MT_REV, m->u.user.revision);
878384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
879384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	info = calloc(1, m->u.match_size);
880384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (info == NULL)
881f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
882384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
8835eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso	memcpy(info, m->data, m->u.match_size - sizeof(*m));
884742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set(e, NFTNL_EXPR_MT_INFO, info, m->u.match_size - sizeof(*m));
885f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
886f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
887384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
888384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
889742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusoint add_match(struct nftnl_rule *r, struct xt_entry_match *m)
890384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
891742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_expr *expr;
892f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	int ret;
893384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
894742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	expr = nftnl_expr_alloc("match");
895384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
896f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
897384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
898f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	ret = __add_match(expr, m);
899742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_add_expr(r, expr);
900f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
901f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return ret;
902384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
903384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
904742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic int __add_target(struct nftnl_expr *e, struct xt_entry_target *t)
905384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
9065eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso	void *info;
907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
908742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set(e, NFTNL_EXPR_TG_NAME, t->u.user.name,
909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  strlen(t->u.user.name));
910742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set_u32(e, NFTNL_EXPR_TG_REV, t->u.user.revision);
911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
9125eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso	info = calloc(1, t->u.target_size);
9135eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso	if (info == NULL)
9145eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso		return -ENOMEM;
915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
9165eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso	memcpy(info, t->data, t->u.target_size - sizeof(*t));
917742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set(e, NFTNL_EXPR_TG_INFO, info, t->u.target_size - sizeof(*t));
918f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
919f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
922742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusoint add_target(struct nftnl_rule *r, struct xt_entry_target *t)
923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
924742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_expr *expr;
925f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	int ret;
926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
927742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	expr = nftnl_expr_alloc("target");
928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
929f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
931f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	ret = __add_target(expr, t);
932742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_add_expr(r, expr);
933f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
934f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return ret;
935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
937742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusoint add_jumpto(struct nftnl_rule *r, const char *name, int verdict)
938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
939742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_expr *expr;
940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
941742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	expr = nftnl_expr_alloc("immediate");
942384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
943f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
944384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
945742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_DREG, NFT_REG_VERDICT);
946742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_VERDICT, verdict);
947742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set_str(expr, NFTNL_EXPR_IMM_CHAIN, (char *)name);
948742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_add_expr(r, expr);
949f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
950f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
953742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusoint add_verdict(struct nftnl_rule *r, int verdict)
954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
955742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_expr *expr;
956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
957742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	expr = nftnl_expr_alloc("immediate");
958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
959f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
961742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_DREG, NFT_REG_VERDICT);
962742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_VERDICT, verdict);
963742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_add_expr(r, expr);
964f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
965f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
968742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusoint add_action(struct nftnl_rule *r, struct iptables_command_state *cs,
969d007e1a59e4beaddab430992302d43b122ffc801Pablo Neira Ayuso	       bool goto_set)
970c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso{
971c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       int ret = 0;
972c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso
973c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       /* If no target at all, add nothing (default to continue) */
974c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       if (cs->target != NULL) {
975c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       /* Standard target? */
976c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
977c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_verdict(r, NF_ACCEPT);
978c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
979c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_verdict(r, NF_DROP);
980c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
981c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_verdict(r, NFT_RETURN);
982c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       else
983c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_target(r, cs->target->t);
984c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       } else if (strlen(cs->jumpto) > 0) {
985c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       /* Not standard, then it's a go / jump to chain */
986d007e1a59e4beaddab430992302d43b122ffc801Pablo Neira Ayuso	       if (goto_set)
987c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_jumpto(r, cs->jumpto, NFT_GOTO);
988c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       else
989c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_jumpto(r, cs->jumpto, NFT_JUMP);
990c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       }
991c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       return ret;
992c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso}
993c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso
994742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic void nft_rule_print_debug(struct nftnl_rule *r, struct nlmsghdr *nlh)
995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
996384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
997384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
998384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_snprintf(tmp, sizeof(tmp), r, 0, 0);
10001835790d7f7517f4c101e1c1f3df5519a6c228e7Tomasz Bursztyka	printf("DEBUG: rule: %s\n", tmp);
1001384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
1002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
1003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1005742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusoint add_counters(struct nftnl_rule *r, uint64_t packets, uint64_t bytes)
1006384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1007742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_expr *expr;
1008384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1009742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	expr = nftnl_expr_alloc("counter");
1010384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
1011f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
1012384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1013742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set_u64(expr, NFTNL_EXPR_CTR_PACKETS, packets);
1014742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_expr_set_u64(expr, NFTNL_EXPR_CTR_BYTES, bytes);
1015384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1016742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_add_expr(r, expr);
1017f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
1018f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
1019384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1020384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1021d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garayenum udata_type {
1022d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay	UDATA_TYPE_COMMENT,
1023d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay	__UDATA_TYPE_MAX,
1024d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay};
1025d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay#define UDATA_TYPE_MAX (__UDATA_TYPE_MAX - 1)
1026d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay
1027d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garayint add_comment(struct nftnl_rule *r, const char *comment)
1028d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay{
1029d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay	struct nftnl_udata_buf *udata;
1030d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay
1031d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay	udata = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
1032d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay	if (!udata)
1033d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay		return -ENOMEM;
1034d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay
1035d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay	if (!nftnl_udata_put_strz(udata, UDATA_TYPE_COMMENT, comment))
1036d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay		return -ENOMEM;
1037d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay	nftnl_rule_set_data(r, NFTNL_RULE_USERDATA,
1038d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay			    nftnl_udata_buf_data(udata),
1039d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay			    nftnl_udata_buf_len(udata));
1040d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay
1041d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay	nftnl_udata_buf_free(udata);
1042d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay
1043d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay	return 0;
1044d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay}
1045d64ef34a99610a6fb54d43660ac31555da858231Pablo M. Bermudo Garay
1046a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garaystatic int parse_udata_cb(const struct nftnl_udata *attr, void *data)
1047a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay{
1048a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	unsigned char *value = nftnl_udata_get(attr);
1049a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	uint8_t type = nftnl_udata_type(attr);
1050a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	uint8_t len = nftnl_udata_len(attr);
1051a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	const struct nftnl_udata **tb = data;
1052a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay
1053a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	switch (type) {
1054a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	case UDATA_TYPE_COMMENT:
1055a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay		if (value[len - 1] != '\0')
1056a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay			return -1;
1057a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay		break;
1058a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	default:
1059a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay		return 0;
1060a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	}
1061a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	tb[type] = attr;
1062a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	return 0;
1063a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay}
1064a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay
1065a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garaychar *get_comment(const void *data, uint32_t data_len)
1066a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay{
1067a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	const struct nftnl_udata *tb[UDATA_TYPE_MAX + 1] = {};
1068a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay
1069a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	if (nftnl_udata_parse(data, data_len, parse_udata_cb, tb) < 0)
1070a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay		return NULL;
1071a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay
1072a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	if (!tb[UDATA_TYPE_COMMENT])
1073a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay		return NULL;
1074a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay
1075a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay	return nftnl_udata_get(tb[UDATA_TYPE_COMMENT]);
1076a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay}
1077a44bee8c3582cb72868a3b7f703494dd2b24bf7dPablo M. Bermudo Garay
1078742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusovoid add_compat(struct nftnl_rule *r, uint32_t proto, bool inv)
10792a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso{
1080742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_set_u32(r, NFTNL_RULE_COMPAT_PROTO, proto);
1081742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_set_u32(r, NFTNL_RULE_COMPAT_FLAGS,
10822a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso			      inv ? NFT_RULE_COMPAT_F_INV : 0);
10832a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso}
10842a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso
1085742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic struct nftnl_rule *
1086cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusonft_rule_new(struct nft_handle *h, const char *chain, const char *table,
1087c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	     void *data)
1088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1089742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
1090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1091742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	r = nftnl_rule_alloc();
1092cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	if (r == NULL)
1093cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso		return NULL;
1094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1095742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, h->family);
1096742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_set(r, NFTNL_RULE_TABLE, (char *)table);
1097742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_set(r, NFTNL_RULE_CHAIN, (char *)chain);
1098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1099c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	if (h->ops->add(r, data) < 0)
1100cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso		goto err;
1101cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1102cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	return r;
1103cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusoerr:
1104742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_free(r);
1105cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	return NULL;
1106cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso}
1107cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1108cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusoint
1109cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusonft_rule_append(struct nft_handle *h, const char *chain, const char *table,
1110b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		void *data, uint64_t handle, bool verbose)
1111cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso{
1112742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
1113d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	int type;
1114cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1115cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
1116cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
11173599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayuso		nft_xt_builtin_init(h, table);
1118cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1119cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	nft_fn = nft_rule_append;
1120cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1121b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso	r = nft_rule_new(h, chain, table, data);
1122d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (r == NULL)
1123d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return 0;
1124384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11250a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	if (handle > 0) {
1126742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_rule_set(r, NFTNL_RULE_HANDLE, &handle);
1127495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso		type = NFT_COMPAT_RULE_REPLACE;
1128cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	} else
1129495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso		type = NFT_COMPAT_RULE_APPEND;
1130384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1131495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso	if (batch_rule_add(h, type, r) < 0)
1132742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_rule_free(r);
1133384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1134ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	flush_rule_cache(h);
1135d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return 1;
1136384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1137384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11381ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayusovoid
11398877968858a8dd6b7ae096988d57a7511c81733dGiuseppe Longonft_rule_print_save(const void *data,
1140742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		    struct nftnl_rule *r, enum nft_rule_print type,
1141cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka		    unsigned int format)
1142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1143742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	const char *chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
1144742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY);
1145cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka	struct nft_family_ops *ops;
1146384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11471aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo	ops = nft_family_ops_lookup(family);
11481aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo
11491aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo	if (!(format & FMT_NOCOUNTS) && ops->save_counters)
11501aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo		ops->save_counters(data);
11511aefddd07ca8e51f0528366835cf466d57bd459fGiuseppe Longo
1152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
11531ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	switch(type) {
11541ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	case NFT_RULE_APPEND:
11551ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		printf("-A %s ", chain);
11561ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		break;
11571ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	case NFT_RULE_DEL:
11581ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		printf("-D %s ", chain);
11591ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		break;
11601ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	}
1161384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11628877968858a8dd6b7ae096988d57a7511c81733dGiuseppe Longo	if (ops->save_firewall)
11638877968858a8dd6b7ae096988d57a7511c81733dGiuseppe Longo		ops->save_firewall(data, format);
1164cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka
1165384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1167742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
1168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1169742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
1170742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list *list = data;
1171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1172742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_alloc();
1173cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (c == NULL)
1174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1176742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	if (nftnl_chain_nlmsg_parse(nlh, c) < 0)
1177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1179742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_add_tail(c, list);
1180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1182384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1183742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_free(c);
1184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1187384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1188742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic struct nftnl_chain_list *nftnl_chain_list_get(struct nft_handle *h)
1189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1192742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list *list;
1193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1194742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	list = nftnl_chain_list_alloc();
1195384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1196b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		errno = ENOMEM;
1197b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		return NULL;
1198384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1199384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1200742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
1201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1203742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	mnl_talk(h, nlh, nftnl_chain_list_cb, list);
1204384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1205384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1206384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1207384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1208742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostruct nftnl_chain_list *nft_chain_dump(struct nft_handle *h)
1209384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1210742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	return nftnl_chain_list_get(h);
1211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic const char *policy_name[NF_ACCEPT+1] = {
1214384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_DROP] = "DROP",
1215384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_ACCEPT] = "ACCEPT",
1216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso};
1217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1218742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic void nft_chain_print_save(struct nftnl_chain *c, bool basechain)
1219384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1220742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
1221742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	uint64_t pkts = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS);
1222742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	uint64_t bytes = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES);
1223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
1225384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (basechain) {
1226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t pol = NF_ACCEPT;
1227384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* no default chain policy? don't crash, display accept */
1229742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		if (nftnl_chain_get(c, NFTNL_CHAIN_POLICY))
1230742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
1231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
12320a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		printf(":%s %s [%"PRIu64":%"PRIu64"]\n", chain, policy_name[pol],
1233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					     pkts, bytes);
1234384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else
12350a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		printf(":%s - [%"PRIu64":%"PRIu64"]\n", chain, pkts, bytes);
1236384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1238742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusoint nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list,
1239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   const char *table)
1240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1241742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list_iter *iter;
1242742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
1243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1244742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_chain_list_iter_create(list);
1245b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1248742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_list_iter_next(iter);
1249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
1251742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
1252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
1253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
1255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
12577244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka		basechain = nft_chain_builtin(c);
1258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_print_save(c, basechain);
1259384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1260742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		c = nftnl_chain_list_iter_next(iter);
1261384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1262384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1263742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_iter_destroy(iter);
1264742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_free(list);
1265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1269742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data)
1270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1271742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
1272742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list *list = data;
1273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1274742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	r = nftnl_rule_alloc();
1275cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (r == NULL)
1276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1278742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	if (nftnl_rule_nlmsg_parse(nlh, r) < 0)
1279384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1281742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_list_add_tail(r, list);
1282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1285742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_free(r);
1286742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_list_free(list);
1287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1291742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h)
1292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1295742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list *list;
1296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1298ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	if (h->rule_cache)
1299ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay		return h->rule_cache;
1300ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay
1301742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	list = nftnl_rule_list_alloc();
1302b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1305742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
1306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1307384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1308742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	ret = mnl_talk(h, nlh, nftnl_rule_list_cb, list);
1309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1310742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_rule_list_free(list);
1311384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return NULL;
1312384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1314ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	h->rule_cache = list;
1315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_save(struct nft_handle *h, const char *table, bool counters)
1319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1320742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list *list;
1321742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list_iter *iter;
1322742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
1323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
1325b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1328742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_rule_list_iter_create(list);
1329b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1332742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	r = nftnl_rule_list_iter_next(iter);
1333384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
1334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
1335742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
1336cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka		struct iptables_command_state cs = {};
1337384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0)
1339384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1340384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1341cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka		nft_rule_to_iptables_command_state(r, &cs);
1342cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka
1343cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka		nft_rule_print_save(&cs, r, NFT_RULE_APPEND,
1344cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka				    counters ? 0 : FMT_NOCOUNTS);
1345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1347742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		r = nftnl_rule_list_iter_next(iter);
1348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1350742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_list_iter_destroy(iter);
1351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1352384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1354384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1355384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
1358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1359742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
1360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1361742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	r = nftnl_rule_alloc();
1362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL)
1363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1364384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1365742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_set(r, NFTNL_RULE_TABLE, (char *)table);
1366742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_set(r, NFTNL_RULE_CHAIN, (char *)chain);
1367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1368495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso	if (batch_rule_add(h, NFT_COMPAT_RULE_FLUSH, r) < 0)
1369742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_rule_free(r);
1370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
1373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1375742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list *list;
1376742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list_iter *iter;
1377742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
1378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_flush;
1380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1381742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	list = nftnl_chain_list_get(h);
1382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
1384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1387742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_chain_list_iter_create(list);
1388b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1389b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
1390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1391742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_list_iter_next(iter);
1392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1394742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
1395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1396742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
1397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		__nft_rule_flush(h, table_name, chain_name);
1405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
140636ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
140736ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
1408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1409742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		c = nftnl_chain_list_iter_next(iter);
1410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1412742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_iter_destroy(iter);
1413ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	flush_rule_cache(h);
1414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1415742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_free(list);
1416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table)
1422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1423742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
1424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14267bc5f6c133bf38c696dc8c14cb479167711437c2Ana Rey	nft_fn = nft_chain_user_add;
14277bc5f6c133bf38c696dc8c14cb479167711437c2Ana Rey
1428e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
14298b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
14303599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayuso		nft_xt_builtin_init(h, table);
1431e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
1432742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_alloc();
1433b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (c == NULL)
1434b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		return 0;
1435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1436742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
1437742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain);
1438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14391d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	if (h->batch_support) {
14401d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
14411d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	} else {
14421d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		char buf[MNL_SOCKET_BUFFER_SIZE];
14431d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		struct nlmsghdr *nlh;
1444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1445742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
14461d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso						h->family,
14471d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso						NLM_F_ACK|NLM_F_EXCL, h->seq);
1448742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_nlmsg_build_payload(nlh, c);
1449742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_free(c);
14501d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		ret = mnl_talk(h, nlh, NULL, NULL);
14511d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	}
1452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1456384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1457742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic int __nft_chain_del(struct nft_handle *h, struct nftnl_chain *c)
1458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1459384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1461384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1462742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, h->family,
1463384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1464742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_nlmsg_build_payload(nlh, c);
1465384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14662e256aa818ba5ddf13a4e85f071ef1bf3c485558Tomasz Bursztyka	return mnl_talk(h, nlh, NULL, NULL);
1467384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1468384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1469384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table)
1470384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1471742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list *list;
1472742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list_iter *iter;
1473742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
1474384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
1475384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int deleted_ctr = 0;
1476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1477742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	list = nftnl_chain_list_get(h);
1478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1481742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_chain_list_iter_create(list);
1482b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1483b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
1484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1485742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_list_iter_next(iter);
1486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1488742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
1489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1490742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
1491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* don't delete built-in chain */
1493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_builtin(c))
1494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
15021d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		if (h->batch_support)
15031d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso			ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
15041d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		else
15051d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso			ret = __nft_chain_del(h, c);
15061d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso
1507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (ret < 0)
1508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		deleted_ctr++;
151136ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo
151236ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
151336ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
1514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1515742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		c = nftnl_chain_list_iter_next(iter);
1516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1518742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_iter_destroy(iter);
1519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
15201d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	if (!h->batch_support)
1521742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_list_free(list);
1522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* chain not found */
15241d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	if (deleted_ctr == 0) {
15251d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		ret = -1;
1526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
15271d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	}
1528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1533742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostruct nftnl_chain *
1534742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusonft_chain_list_find(struct nftnl_chain_list *list,
15350aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		    const char *table, const char *chain)
15369c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso{
1537742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list_iter *iter;
1538742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
15399c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
1540742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_chain_list_iter_create(list);
1541b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
15429c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return NULL;
15439c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
1544742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_list_iter_next(iter);
15459c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	while (c != NULL) {
15469c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		const char *table_name =
1547742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
15489c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		const char *chain_name =
1549742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
15509c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
15519c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
15529c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			goto next;
15539c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
15549c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		if (strcmp(chain, chain_name) != 0)
15559c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			goto next;
15569c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
1557742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_list_iter_destroy(iter);
15589c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return c;
15599c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayusonext:
1560742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		c = nftnl_chain_list_iter_next(iter);
15619c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	}
1562742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_iter_destroy(iter);
15639c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	return NULL;
15649c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso}
15659c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
1566742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic struct nftnl_chain *
15670aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonft_chain_find(struct nft_handle *h, const char *table, const char *chain)
15680aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{
1569742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list *list;
15700aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1571742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	list = nftnl_chain_list_get(h);
1572b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
15730aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		return NULL;
15740aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1575e127d223d01aaa0886c7f279110ac36651b9a057Tomasz Bursztyka	return nft_chain_list_find(list, table, chain);
15760aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso}
15770aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_rename(struct nft_handle *h,const char *chain,
1579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  const char *table, const char *newname)
1580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1581742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
15829c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	uint64_t handle;
1583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1585d87b76cfc3b1c003fec75b8a4ea639aa444014f3Arturo Borrero	nft_fn = nft_chain_user_add;
1586d87b76cfc3b1c003fec75b8a4ea639aa444014f3Arturo Borrero
15874493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	/* If built-in chains don't exist for this table, create them */
15888b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
15893599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayuso		nft_xt_builtin_init(h, table);
15904493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
1591d87b76cfc3b1c003fec75b8a4ea639aa444014f3Arturo Borrero	/* Config load changed errno. Ensure genuine info for our callers. */
1592d87b76cfc3b1c003fec75b8a4ea639aa444014f3Arturo Borrero	errno = 0;
1593d87b76cfc3b1c003fec75b8a4ea639aa444014f3Arturo Borrero
15949c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	/* Find the old chain to be renamed */
15959c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	c = nft_chain_find(h, table, chain);
15969c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	if (c == NULL) {
15979c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		errno = ENOENT;
15989c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return -1;
15999c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	}
1600742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	handle = nftnl_chain_get_u64(c, NFTNL_CHAIN_HANDLE);
16019c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
16029c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	/* Now prepare the new name for the chain */
1603742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_alloc();
1604b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (c == NULL)
16054493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka		return -1;
16064493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
1607742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
1608742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)newname);
1609742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_set_u64(c, NFTNL_CHAIN_HANDLE, handle);
1610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
16111d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	if (h->batch_support) {
1612d87b76cfc3b1c003fec75b8a4ea639aa444014f3Arturo Borrero		ret = batch_chain_add(h, NFT_COMPAT_CHAIN_RENAME, c);
16131d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	} else {
16141d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		char buf[MNL_SOCKET_BUFFER_SIZE];
16151d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		struct nlmsghdr *nlh;
16164493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
1617742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
16181d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso						h->family, NLM_F_ACK, h->seq);
1619742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_nlmsg_build_payload(nlh, c);
1620742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_free(c);
16211d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso
16221d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		ret = mnl_talk(h, nlh, NULL, NULL);
16231d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	}
16244493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
16254493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	/* the core expects 1 for success and 0 for error */
16264493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	return ret == 0 ? 1 : 0;
1627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1629742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic int nftnl_table_list_cb(const struct nlmsghdr *nlh, void *data)
1630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1631742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table *t;
1632742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table_list *list = data;
1633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1634742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	t = nftnl_table_alloc();
1635cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (t == NULL)
1636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1637384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1638742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	if (nftnl_table_nlmsg_parse(nlh, t) < 0)
1639384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1641742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_list_add_tail(t, list);
1642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1645742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_free(t);
1646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1650742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h)
1651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1654742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table_list *list;
1655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1656742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	list = nftnl_table_list_alloc();
1657b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1660742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
1661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1663742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	mnl_talk(h, nlh, nftnl_table_list_cb, list);
1664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusobool nft_table_find(struct nft_handle *h, const char *tablename)
1669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1670742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table_list *list;
1671742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table_list_iter *iter;
1672742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table *t;
1673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool ret = false;
1674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1675742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	list = nftnl_table_list_get(h);
1676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1679742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_table_list_iter_create(list);
1680b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1683742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	t = nftnl_table_list_iter_next(iter);
1684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
1685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *this_tablename =
1686742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_table_get(t, NFTNL_TABLE_NAME);
1687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(tablename, this_tablename) == 0)
1689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return true;
1690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1691742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		t = nftnl_table_list_iter_next(iter);
1692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1694742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_list_free(list);
1695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1700384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_for_each_table(struct nft_handle *h,
1701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       int (*func)(struct nft_handle *h, const char *tablename, bool counters),
1702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       bool counters)
1703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 1;
1705742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table_list *list;
1706742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table_list_iter *iter;
1707742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table *t;
1708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1709742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	list = nftnl_table_list_get(h);
1710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
1712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1715742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_table_list_iter_create(list);
1716b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1719742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	t = nftnl_table_list_iter_next(iter);
1720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
1721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *tablename =
1722742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_table_get(t, NFTNL_TABLE_NAME);
1723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		func(h, tablename, counters);
1725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1726742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		t = nftnl_table_list_iter_next(iter);
1727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1729742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_list_free(list);
1730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
17360aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusoint nft_table_purge_chains(struct nft_handle *h, const char *this_table,
1737742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			   struct nftnl_chain_list *chain_list)
17380aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{
1739742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list_iter *iter;
1740742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *chain_obj;
17410aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1742742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_chain_list_iter_create(chain_list);
1743b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
17440aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		return 0;
17450aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1746742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	chain_obj = nftnl_chain_list_iter_next(iter);
17470aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	while (chain_obj != NULL) {
17480aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		const char *table =
1749742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(chain_obj, NFTNL_CHAIN_TABLE);
17500aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
17510aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if (strcmp(this_table, table) != 0)
17520aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			goto next;
17530aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
17540aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if (nft_chain_builtin(chain_obj))
17550aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			goto next;
17560aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
17570aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if ( __nft_chain_del(h, chain_obj) < 0) {
17580aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			if (errno != EBUSY)
17590aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso				return -1;
17600aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		}
17610aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonext:
1762742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		chain_obj = nftnl_chain_list_iter_next(iter);
17630aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	}
1764742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_iter_destroy(iter);
17650aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
17660aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	return 0;
17670aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso}
17680aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1769742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic int __nft_rule_del(struct nft_handle *h, struct nftnl_rule_list *list,
1770742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			  struct nftnl_rule *r)
1771384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1772384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1773384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1774742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_list_del(r);
1775384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1776495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso	ret = batch_rule_add(h, NFT_COMPAT_RULE_DELETE, r);
1777d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (ret < 0) {
1778742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_rule_free(r);
1779d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return -1;
1780d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	}
1781d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return 1;
1782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1783384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1784742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusostatic struct nftnl_rule *
1785742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusonft_rule_find(struct nft_handle *h, struct nftnl_rule_list *list,
1786e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso	      const char *chain, const char *table, void *data, int rulenum)
17873aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso{
1788742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
1789742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list_iter *iter;
17903aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int rule_ctr = 0;
17913aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	bool found = false;
17923aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1793742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_rule_list_iter_create(list);
1794b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1795384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1796384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1797742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	r = nftnl_rule_list_iter_next(iter);
1798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
1799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
1800742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
1801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
1802742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
1803384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
1805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0) {
1806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different chain / table\n");
1807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1810384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (rulenum >= 0) {
1811384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Delete by rule number case */
181234344db9878ed53b387180362b1be77001e03e45Thomas Woerner			if (rule_ctr == rulenum) {
181334344db9878ed53b387180362b1be77001e03e45Thomas Woerner			    found = true;
181434344db9878ed53b387180362b1be77001e03e45Thomas Woerner			    break;
181534344db9878ed53b387180362b1be77001e03e45Thomas Woerner			}
1816384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
1817e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso			found = h->ops->rule_find(h->ops, r, data);
1818e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso			if (found)
1819e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso				break;
1820384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
18214acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka		rule_ctr++;
182234344db9878ed53b387180362b1be77001e03e45Thomas Woernernext:
1823742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		r = nftnl_rule_list_iter_next(iter);
1824384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1825384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1826742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_list_iter_destroy(iter);
1827384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
18283aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return found ? r : NULL;
1829384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1830384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_check(struct nft_handle *h, const char *chain,
1832b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		   const char *table, void *data, bool verbose)
1833384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1834742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list *list;
18353aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret;
18363aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1837384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_check;
1838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
18392abd049177fa42993e4b1de588e92282a200ee43Pablo M. Bermudo Garay	list = nft_rule_list_get(h);
1840b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
18413aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
18423aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1843b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso	ret = nft_rule_find(h, list, chain, table, data, -1) ? 1 : 0;
18443aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (ret == 0)
18453aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
18463aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
18473aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
1848384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1849384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1850384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete(struct nft_handle *h, const char *chain,
1851b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		    const char *table, void *data, bool verbose)
1852384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
18533aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
1854742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
1855742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list *list;
18563aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1857384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete;
1858384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
18592abd049177fa42993e4b1de588e92282a200ee43Pablo M. Bermudo Garay	list = nft_rule_list_get(h);
1860b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
18613aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
18623aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1863b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso	r = nft_rule_find(h, list, chain, table, data, -1);
18643aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
1865d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		ret =__nft_rule_del(h, list, r);
1866d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		if (ret < 0)
1867d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			errno = ENOMEM;
18683aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
18693aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
18703aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1871ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	flush_rule_cache(h);
18723aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
18733aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
1874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1876cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusostatic int
1877cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusonft_rule_add(struct nft_handle *h, const char *chain,
1878cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	     const char *table, struct iptables_command_state *cs,
1879cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	     uint64_t handle, bool verbose)
1880cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso{
1881742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
1882cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1883cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	r = nft_rule_new(h, chain, table, cs);
1884d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (r == NULL)
1885d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return 0;
1886d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
188766a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso	if (handle > 0)
1888742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle);
1889cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1890495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso	if (batch_rule_add(h, NFT_COMPAT_RULE_INSERT, r) < 0) {
1891742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_rule_free(r);
1892d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return 0;
1893cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	}
1894cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1895ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	flush_rule_cache(h);
1896d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return 1;
1897cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso}
1898cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1899cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusoint nft_rule_insert(struct nft_handle *h, const char *chain,
1900b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		    const char *table, void *data, int rulenum, bool verbose)
1901cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso{
1902742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list *list;
1903742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
190466a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso	uint64_t handle = 0;
1905cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1906cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
1907cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
19083599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayuso		nft_xt_builtin_init(h, table);
1909cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1910cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	nft_fn = nft_rule_insert;
1911cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
191266a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso	if (rulenum > 0) {
19132abd049177fa42993e4b1de588e92282a200ee43Pablo M. Bermudo Garay		list = nft_rule_list_get(h);
191466a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		if (list == NULL)
191566a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso			goto err;
1916cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1917b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		r = nft_rule_find(h, list, chain, table, data, rulenum);
191866a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		if (r == NULL) {
19198e1522698a7495002e5154f5643abb68e9c3a89aThomas Woerner			/* special case: iptables allows to insert into
19208e1522698a7495002e5154f5643abb68e9c3a89aThomas Woerner			 * rule_count + 1 position.
19218e1522698a7495002e5154f5643abb68e9c3a89aThomas Woerner			 */
19228e1522698a7495002e5154f5643abb68e9c3a89aThomas Woerner			r = nft_rule_find(h, list, chain, table, data,
19238e1522698a7495002e5154f5643abb68e9c3a89aThomas Woerner					  rulenum - 1);
19248e1522698a7495002e5154f5643abb68e9c3a89aThomas Woerner			if (r != NULL) {
1925ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay				flush_rule_cache(h);
19268e1522698a7495002e5154f5643abb68e9c3a89aThomas Woerner				return nft_rule_append(h, chain, table, data,
19278e1522698a7495002e5154f5643abb68e9c3a89aThomas Woerner						       0, verbose);
19288e1522698a7495002e5154f5643abb68e9c3a89aThomas Woerner			}
19298e1522698a7495002e5154f5643abb68e9c3a89aThomas Woerner
193066a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso			errno = ENOENT;
193166a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso			goto err;
193266a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		}
1933cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1934742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE);
193566a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		DEBUGP("adding after rule handle %"PRIu64"\n", handle);
1936cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1937ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay		flush_rule_cache(h);
1938cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	}
1939cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1940b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso	return nft_rule_add(h, chain, table, data, handle, verbose);
1941cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusoerr:
1942ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	flush_rule_cache(h);
1943cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	return 0;
1944cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso}
1945cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1946384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete_num(struct nft_handle *h, const char *chain,
19473aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso			const char *table, int rulenum, bool verbose)
1948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
19493aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
1950742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
1951742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list *list;
19523aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete_num;
1954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
19552abd049177fa42993e4b1de588e92282a200ee43Pablo M. Bermudo Garay	list = nft_rule_list_get(h);
1956b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
19573aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
19583aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1959e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso	r = nft_rule_find(h, list, chain, table, NULL, rulenum);
19603aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
19613aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		ret = 1;
19623aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
19633aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("deleting rule by number %d\n", rulenum);
1964d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		ret = __nft_rule_del(h, list, r);
1965d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		if (ret < 0)
1966d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			errno = ENOMEM;
19673aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
19683aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
19693aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1970ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	flush_rule_cache(h);
19713aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
19723aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
1973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_replace(struct nft_handle *h, const char *chain,
1976b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		     const char *table, void *data, int rulenum, bool verbose)
1977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
19783aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
1979742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
1980742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list *list;
1981384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_replace;
1983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
19842abd049177fa42993e4b1de588e92282a200ee43Pablo M. Bermudo Garay	list = nft_rule_list_get(h);
1985b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
19863aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
19873aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1988b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso	r = nft_rule_find(h, list, chain, table, data, rulenum);
19893aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
19901298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso		DEBUGP("replacing rule with handle=%llu\n",
19911298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso			(unsigned long long)
1992742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE));
1993384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1994b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		ret = nft_rule_append(h, chain, table, data,
1995742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso				      nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE),
1996cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso				      verbose);
19973aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
19983aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
19993aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2000ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	flush_rule_cache(h);
20013aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
20023aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2005384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
2006b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka__nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
2007384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int rulenum, unsigned int format,
2008742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		void (*cb)(struct nftnl_rule *r, unsigned int num,
2009384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			   unsigned int format))
2010384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2011742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list *list;
2012742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list_iter *iter;
2013742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
2014384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int rule_ctr = 0, ret = 0;
2015384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2016384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
2017b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
2018384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2019384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2020742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_rule_list_iter_create(list);
2021b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2022b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2023384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2024742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	r = nftnl_rule_list_iter_next(iter);
2025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
2026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
2027742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
2028384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
2029742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
2030384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2031384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
2032384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0)
2033384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2034384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
203534344db9878ed53b387180362b1be77001e03e45Thomas Woerner		rule_ctr++;
203634344db9878ed53b387180362b1be77001e03e45Thomas Woerner
20370b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		if (rulenum > 0 && rule_ctr != rulenum) {
2038384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* List by rule number case */
20390b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			goto next;
20400b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		}
2041384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
20428aa384a7d54734fd830840a2593cd4f07749976fTomasz Bursztyka		cb(r, rule_ctr, format);
20430b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		if (rulenum > 0 && rule_ctr == rulenum) {
20440b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			ret = 1;
20450b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			break;
2046384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
20470b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo
2048384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2049742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		r = nftnl_rule_list_iter_next(iter);
2050384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2051384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2052742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_list_iter_destroy(iter);
2053b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
2054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == 0)
2055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
2056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2057384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
2058384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2059384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2060384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
2061384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  int rulenum, unsigned int format)
2062384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2063e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka	const struct nft_family_ops *ops;
2064742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list *list;
2065742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list_iter *iter;
2066742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
20670a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo	bool found = false;
2068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2069aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka	/* If built-in chains don't exist for this table, create them */
2070a4e78370af8498e2de65fcb8aafed39a4482966cPablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) {
20713599c617f6509d120dfddf78a024bdd32633cf2dPablo Neira Ayuso		nft_xt_builtin_init(h, table);
2072a4e78370af8498e2de65fcb8aafed39a4482966cPablo Neira Ayuso		/* Force table and chain creation, otherwise first iptables -L
2073a4e78370af8498e2de65fcb8aafed39a4482966cPablo Neira Ayuso		 * lists no table/chains.
2074a4e78370af8498e2de65fcb8aafed39a4482966cPablo Neira Ayuso		 */
2075a4e78370af8498e2de65fcb8aafed39a4482966cPablo Neira Ayuso		if (!list_empty(&h->obj_list))
2076a4e78370af8498e2de65fcb8aafed39a4482966cPablo Neira Ayuso			nft_commit(h);
2077a4e78370af8498e2de65fcb8aafed39a4482966cPablo Neira Ayuso	}
2078aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka
2079e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka	ops = nft_family_ops_lookup(h->family);
2080e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka
2081b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka	if (chain && rulenum) {
2082b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka		__nft_rule_list(h, chain, table,
2083e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka				rulenum, format, ops->print_firewall);
2084b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka		return 1;
2085b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka	}
2086b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka
2087384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
2088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2089742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_chain_list_iter_create(list);
2090b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2091b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
209351e83a4deb4849152a29c160893f0823846d47a0Giuseppe Longo	if (ops->print_table_header)
209451e83a4deb4849152a29c160893f0823846d47a0Giuseppe Longo		ops->print_table_header(table);
209551e83a4deb4849152a29c160893f0823846d47a0Giuseppe Longo
2096742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_list_iter_next(iter);
2097384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2099742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
2100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2101742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
2102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
2103742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
2104384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t refs =
2105742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_u32(c, NFTNL_CHAIN_USE);
2106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct xt_counters ctrs = {
2107742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			.pcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
2108742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			.bcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES),
2109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		};
2110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
2111384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2112742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		if (nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM))
2113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			basechain = true;
2114384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2115384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2116384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2117384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
2118384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2119384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
21200a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		if (found)
21210a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo			printf("\n");
21220a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
21234272426912b0951b4dc7f40179d5217b513775e1Pablo Neira Ayuso		ops->print_header(format, chain_name, policy_name[policy],
21244272426912b0951b4dc7f40179d5217b513775e1Pablo Neira Ayuso				  &ctrs, basechain, refs);
21257a1026f59c101a67233c65dd5ef9b0ae15945ca5Tomasz Bursztyka
2126b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka		__nft_rule_list(h, chain_name, table,
2127e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka				rulenum, format, ops->print_firewall);
21280a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
2129da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso		/* we printed the chain we wanted, stop processing. */
2130da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso		if (chain)
2131da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso			break;
2132da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso
21330a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		found = true;
21340a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
2135384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2136742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		c = nftnl_chain_list_iter_next(iter);
2137384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2138384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2139742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_iter_destroy(iter);
2140b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
2141742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_free(list);
2142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2143384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2146384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2147742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusolist_save(struct nftnl_rule *r, unsigned int num, unsigned int format)
2148384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2149cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka	struct iptables_command_state cs = {};
2150cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka
2151cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka	nft_rule_to_iptables_command_state(r, &cs);
2152cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka
2153cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka	nft_rule_print_save(&cs, r, NFT_RULE_APPEND, !(format & FMT_NOCOUNTS));
2154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2155384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
2157742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayusonftnl_rule_list_chain_save(struct nft_handle *h, const char *chain,
2158742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			 const char *table, struct nftnl_chain_list *list,
21598dd2627afc462a2591c2f621743cae1a6b98d771Pablo Neira Ayuso			 int counters)
2160384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2161742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list_iter *iter;
2162742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
2163384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2164742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_chain_list_iter_create(list);
2165b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2168742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_list_iter_next(iter);
2169384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2170384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2171742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
2172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2173742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
2174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
2175742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
2176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
21778dd2627afc462a2591c2f621743cae1a6b98d771Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0 ||
21788dd2627afc462a2591c2f621743cae1a6b98d771Pablo Neira Ayuso		    (chain && strcmp(chain, chain_name) != 0))
2179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* this is a base chain */
21827244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka		if (nft_chain_builtin(c)) {
2183384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-P %s %s", chain_name, policy_name[policy]);
2184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (counters) {
21860a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo				printf(" -c %"PRIu64" %"PRIu64"\n",
2187742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso					nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
2188742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso					nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES));
2189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			} else
2190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				printf("\n");
2191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-N %s\n", chain_name);
2193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2194384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2195742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		c = nftnl_chain_list_iter_next(iter);
2196384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2197384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2198742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_iter_destroy(iter);
2199e9a0ef8f1e27f5ef13a27f6cc984e8f2e05afd72Tomasz Bursztyka
2200384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2203384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list_save(struct nft_handle *h, const char *chain,
2204384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       const char *table, int rulenum, int counters)
2205384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2206742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list *list;
2207742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list_iter *iter;
2208742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
220910f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso	int ret = 1;
2210384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
2212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Dump policies and custom chains first */
221410f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso	if (!rulenum)
2215742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_rule_list_chain_save(h, chain, table, list, counters);
2216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Now dump out rules in this table */
2218742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_chain_list_iter_create(list);
2219b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2220b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2222742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_list_iter_next(iter);
2223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2225742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
2226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2227742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
2228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2229384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2230384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
2232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2234b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka		ret = __nft_rule_list(h, chain_name, table, rulenum,
223510f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso				      counters ? 0 : FMT_NOCOUNTS, list_save);
2236da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso
2237da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso		/* we printed the chain we wanted, stop processing. */
2238da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso		if (chain)
2239da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso			break;
2240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2241742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		c = nftnl_chain_list_iter_next(iter);
2242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2243e9a0ef8f1e27f5ef13a27f6cc984e8f2e05afd72Tomasz Bursztyka
2244742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_iter_destroy(iter);
2245b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
2246742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_free(list);
2247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
224810f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso	return ret;
2249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2251a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztykaint nft_rule_zero_counters(struct nft_handle *h, const char *chain,
2252a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka			   const char *table, int rulenum)
2253a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka{
2254a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	struct iptables_command_state cs = {};
2255742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule_list *list;
2256742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_rule *r;
2257a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	int ret = 0;
2258a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2259a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	nft_fn = nft_rule_delete;
2260a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
22612abd049177fa42993e4b1de588e92282a200ee43Pablo M. Bermudo Garay	list = nft_rule_list_get(h);
2262a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	if (list == NULL)
2263a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka		return 0;
2264a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2265e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso	r = nft_rule_find(h, list, chain, table, NULL, rulenum);
2266a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	if (r == NULL) {
2267a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka		errno = ENOENT;
2268a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka		ret = 1;
2269a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka		goto error;
2270a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	}
2271a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2272a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	nft_rule_to_iptables_command_state(r, &cs);
2273a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2274a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	cs.counters.pcnt = cs.counters.bcnt = 0;
2275a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2276a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	ret =  nft_rule_append(h, chain, table, &cs,
2277742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			       nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE),
2278a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka			       false);
2279a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2280a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztykaerror:
2281ef2a7e9fe0d82c691aeee1cbd61095841231974fPablo M. Bermudo Garay	flush_rule_cache(h);
2282a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2283a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	return ret;
2284a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka}
2285a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2286f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusostatic void nft_compat_table_batch_add(struct nft_handle *h, uint16_t type,
2287f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				       uint16_t flags, uint32_t seq,
2288742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso				       struct nftnl_table *table)
2289f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso{
2290f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	struct nlmsghdr *nlh;
2291f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
2292742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nlh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch),
2293f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso					type, h->family, flags, seq);
2294742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_nlmsg_build_payload(nlh, table);
2295742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_free(table);
2296f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso}
2297f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
2298f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusostatic void nft_compat_chain_batch_add(struct nft_handle *h, uint16_t type,
2299f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				       uint16_t flags, uint32_t seq,
2300742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso				       struct nftnl_chain *chain)
2301f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso{
2302f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	struct nlmsghdr *nlh;
2303f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
2304742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nlh = nftnl_chain_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch),
2305f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso					type, h->family, flags, seq);
2306742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_nlmsg_build_payload(nlh, chain);
2307f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	nft_chain_print_debug(chain, nlh);
2308742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_free(chain);
2309f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso}
2310f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
2311f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayusostatic void nft_compat_rule_batch_add(struct nft_handle *h, uint16_t type,
2312f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				      uint16_t flags, uint32_t seq,
2313742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso				      struct nftnl_rule *rule)
2314f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso{
2315f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	struct nlmsghdr *nlh;
2316f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
2317742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nlh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch),
2318f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso				       type, h->family, flags, seq);
2319742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_nlmsg_build_payload(nlh, rule);
2320f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	nft_rule_print_debug(rule, nlh);
2321742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_rule_free(rule);
2322f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso}
2323f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso
2324d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic int nft_action(struct nft_handle *h, int action)
23259e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
2326495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso	struct obj_update *n, *tmp;
2327d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	uint32_t seq = 1;
2328f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso	int ret = 0;
23299e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
2330742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	mnl_nftnl_batch_begin(h->batch, seq++);
23319e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
2332495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso	list_for_each_entry_safe(n, tmp, &h->obj_list, head) {
2333d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		switch (n->type) {
2334f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		case NFT_COMPAT_TABLE_ADD:
2335f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			nft_compat_table_batch_add(h, NFT_MSG_NEWTABLE,
2336f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						   NLM_F_CREATE, seq++,
2337f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						   n->table);
2338f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			break;
2339f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		case NFT_COMPAT_CHAIN_ADD:
2340f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
2341f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						   NLM_F_CREATE, seq++,
2342f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						   n->chain);
2343f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			break;
23441d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		case NFT_COMPAT_CHAIN_USER_ADD:
23451d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso			nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
23461d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso						   NLM_F_EXCL, seq++,
23471d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso						   n->chain);
23481d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso			break;
23491d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		case NFT_COMPAT_CHAIN_USER_DEL:
23501d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso			nft_compat_chain_batch_add(h, NFT_MSG_DELCHAIN,
23511d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso						   0, seq++, n->chain);
23521d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso			break;
2353f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		case NFT_COMPAT_CHAIN_UPDATE:
2354f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
2355f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						   h->restore ?
2356f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						     NLM_F_CREATE : 0,
2357f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						   seq++, n->chain);
2358f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			break;
2359d87b76cfc3b1c003fec75b8a4ea639aa444014f3Arturo Borrero		case NFT_COMPAT_CHAIN_RENAME:
2360d87b76cfc3b1c003fec75b8a4ea639aa444014f3Arturo Borrero			nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN, 0,
2361d87b76cfc3b1c003fec75b8a4ea639aa444014f3Arturo Borrero						   seq++, n->chain);
2362d87b76cfc3b1c003fec75b8a4ea639aa444014f3Arturo Borrero			break;
2363495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso		case NFT_COMPAT_RULE_APPEND:
2364f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
2365f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						  NLM_F_CREATE | NLM_F_APPEND,
2366f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						  seq++, n->rule);
2367d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			break;
2368495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso		case NFT_COMPAT_RULE_INSERT:
2369f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
2370f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						  NLM_F_CREATE, seq++,
2371f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						  n->rule);
2372d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			break;
2373495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso		case NFT_COMPAT_RULE_REPLACE:
2374f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			nft_compat_rule_batch_add(h, NFT_MSG_NEWRULE,
2375f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						  NLM_F_CREATE | NLM_F_REPLACE,
2376f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						  seq++, n->rule);
2377d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			break;
2378495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso		case NFT_COMPAT_RULE_DELETE:
2379495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso		case NFT_COMPAT_RULE_FLUSH:
2380f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso			nft_compat_rule_batch_add(h, NFT_MSG_DELRULE, 0,
2381f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso						  seq++, n->rule);
2382d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			break;
2383d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		}
23849e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
2385495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso		h->obj_list_num--;
2386d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		list_del(&n->head);
2387d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		free(n);
2388d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2389d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		if (!mnl_nlmsg_batch_next(h->batch))
2390742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			h->batch = mnl_nftnl_batch_page_add(h->batch);
2391d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	}
2392d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2393d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	switch (action) {
2394495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso	case NFT_COMPAT_COMMIT:
2395742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		mnl_nftnl_batch_end(h->batch, seq++);
2396d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		break;
2397495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso	case NFT_COMPAT_ABORT:
2398d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		break;
23999e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	}
2400d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2401d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (!mnl_nlmsg_batch_is_empty(h->batch))
2402742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		h->batch = mnl_nftnl_batch_page_add(h->batch);
2403d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2404742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	ret = mnl_nftnl_batch_talk(h);
2405d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2406d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	mnl_nlmsg_batch_reset(h->batch);
2407d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2408f041efe3c26e3059df1ac8f1775f77423d4be5f6Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
24099e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
24109e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
24119e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_commit(struct nft_handle *h)
24129e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
2413495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso	return nft_action(h, NFT_COMPAT_COMMIT);
24149e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
24159e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
24169e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_abort(struct nft_handle *h)
24179e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
2418495f1e8cc1753a3577a0b6c790b96b34859cd9bdPablo Neira Ayuso	return nft_action(h, NFT_COMPAT_ABORT);
24199e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
24209e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
2421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_compatible_revision(const char *name, uint8_t rev, int opt)
2422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct mnl_socket *nl;
2424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
2425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
2426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t portid, seq, type;
2427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
2428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
242985512f09680a798ebe92e96ad62eeae863fbc791Pablo Neira Ayuso	if (opt == IPT_SO_GET_REVISION_MATCH ||
243085512f09680a798ebe92e96ad62eeae863fbc791Pablo Neira Ayuso	    opt == IP6T_SO_GET_REVISION_MATCH)
2431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 0;
2432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
2433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 1;
2434384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = mnl_nlmsg_put_header(buf);
2436384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_type = (NFNL_SUBSYS_NFT_COMPAT << 8) | NFNL_MSG_COMPAT_GET;
2437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
2438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_seq = seq = time(NULL);
2439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
2441384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->nfgen_family = AF_INET;
2442384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->version = NFNETLINK_V0;
2443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->res_id = 0;
2444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_strz(nlh, NFTA_COMPAT_NAME, name);
2446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_REV, htonl(rev));
2447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_TYPE, htonl(type));
2448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	DEBUGP("requesting `%s' rev=%d type=%d via nft_compat\n",
2450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		name, rev, type);
2451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nl = mnl_socket_open(NETLINK_NETFILTER);
2453cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (nl == NULL)
2454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2456cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
2457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2458cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso
2459384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	portid = mnl_socket_get_portid(nl);
2460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2461cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
2462384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2463384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2464384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
2465cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (ret == -1)
2466384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2467384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2468384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
2469cbe036db892c298c33e77dec2c5129dbb4dccc2cPablo Neira Ayuso	if (ret == -1)
2470384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2471384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2472384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
2473384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(nl);
2474384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2475384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret < 0 ? 0 : 1;
2476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/* Translates errno numbers into more human-readable form than strerror. */
2479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoconst char *nft_strerror(int err)
2480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
2482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	static struct table_struct {
2483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		void *fn;
2484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int err;
2485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *message;
2486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} table[] =
2487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  {
2488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, ENOTEMPTY, "Chain is not empty" },
2489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EINVAL, "Can't delete built-in chain" },
24907bc5f6c133bf38c696dc8c14cb479167711437c2Ana Rey	    { nft_chain_user_del, EBUSY, "Directory not empty" },
2491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EMLINK,
2492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Can't delete chain with references left" },
2493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_add, EEXIST, "Chain already exists" },
2494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, E2BIG, "Index of insertion too big" },
24957bc5f6c133bf38c696dc8c14cb479167711437c2Ana Rey	    { nft_rule_check, ENOENT, "Bad rule (does a matching rule exist in that chain?)" },
2496b92426faab5101bc250832fca85ee8fa3548572dAna Rey	    { nft_rule_replace, ENOENT, "Index of replacement too big" },
2497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete_num, E2BIG, "Index of deletion too big" },
2498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/*	    { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
2499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, */
2500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, ELOOP, "Loop found in table" },
2501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, EINVAL, "Target problem" },
2502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    /* ENOENT for DELETE probably means no matching rule */
2503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete, ENOENT,
2504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Bad rule (does a matching rule exist in that chain?)" },
2505384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, ENOENT, "Bad built-in chain name" },
2506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, EINVAL, "Bad policy name" },
2507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, EPERM, "Permission denied (you must be root)" },
2508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, 0, "Incompatible with this kernel" },
2509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
2510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOSYS, "Will be implemented real soon.  I promise ;)" },
2511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOMEM, "Memory allocation problem" },
2512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOENT, "No chain/target/match by that name" },
2513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  };
2514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
2516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if ((!table[i].fn || table[i].fn == nft_fn)
2517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    && table[i].err == err)
2518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return table[i].message;
2519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return strerror(err);
2522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
25238b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
25248b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayusostatic void xtables_config_perror(uint32_t flags, const char *fmt, ...)
25258b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso{
25268b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_list args;
25278b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
25288b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_start(args, fmt);
25298b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
25308b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (flags & NFT_LOAD_VERBOSE)
25318b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		vfprintf(stderr, fmt, args);
25328b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
25338b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_end(args);
25348b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso}
25358b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
25368b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayusoint nft_xtables_config_load(struct nft_handle *h, const char *filename,
25378b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			    uint32_t flags)
25388b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso{
2539742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table_list *table_list = nftnl_table_list_alloc();
2540742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list *chain_list = nftnl_chain_list_alloc();
2541742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table_list_iter *titer = NULL;
2542742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list_iter *citer = NULL;
2543742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_table *table;
2544742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *chain;
2545cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo	uint32_t table_family, chain_family;
2546cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo	bool found = false;
25478b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
2548e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka	if (h->restore)
2549e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka		return 0;
2550e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka
25518b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (xtables_config_parse(filename, table_list, chain_list) < 0) {
25528b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		if (errno == ENOENT) {
25538b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			xtables_config_perror(flags,
25548b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				"configuration file `%s' does not exists\n",
25558b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				filename);
25568b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		} else {
25578b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			xtables_config_perror(flags,
25588b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				"Fatal error parsing config file: %s\n",
25598b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				 strerror(errno));
25608b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
25616a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey		goto err;
25628b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
25638b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
25648b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	/* Stage 1) create tables */
2565742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	titer = nftnl_table_list_iter_create(table_list);
2566742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	while ((table = nftnl_table_list_iter_next(titer)) != NULL) {
2567742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		table_family = nftnl_table_get_u32(table,
2568742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso						      NFTNL_TABLE_FAMILY);
2569cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo		if (h->family != table_family)
2570cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo			continue;
2571cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo
2572cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo		found = true;
2573cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo
2574f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		if (batch_table_add(h, NFT_COMPAT_TABLE_ADD, table) < 0) {
25758b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			if (errno == EEXIST) {
25768b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
25778b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"table `%s' already exists, skipping\n",
2578742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso					(char *)nftnl_table_get(table, NFTNL_TABLE_NAME));
25798b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			} else {
25808b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
25818b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"table `%s' cannot be create, reason `%s'. Exitting\n",
2582742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso					(char *)nftnl_table_get(table, NFTNL_TABLE_NAME),
25838b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					strerror(errno));
25846a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey				goto err;
25858b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			}
25868b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			continue;
25878b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
25888b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		xtables_config_perror(flags, "table `%s' has been created\n",
2589742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			(char *)nftnl_table_get(table, NFTNL_TABLE_NAME));
25908b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
2591742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_list_iter_destroy(titer);
2592742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_list_free(table_list);
25938b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
2594cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo	if (!found)
25956a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey		goto err;
2596cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo
25978b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	/* Stage 2) create chains */
2598742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	citer = nftnl_chain_list_iter_create(chain_list);
2599742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	while ((chain = nftnl_chain_list_iter_next(citer)) != NULL) {
2600742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		chain_family = nftnl_chain_get_u32(chain,
2601742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso						      NFTNL_CHAIN_TABLE);
2602cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo		if (h->family != chain_family)
2603cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo			continue;
2604cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo
2605f1299b98d7ff200eb50ca574278bfeb1368de01bPablo Neira Ayuso		if (batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, chain) < 0) {
26068b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			if (errno == EEXIST) {
26078b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
26088b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"chain `%s' already exists in table `%s', skipping\n",
2609742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso					(char *)nftnl_chain_get(chain, NFTNL_CHAIN_NAME),
2610742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso					(char *)nftnl_chain_get(chain, NFTNL_CHAIN_TABLE));
26118b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			} else {
26128b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
26138b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"chain `%s' cannot be create, reason `%s'. Exitting\n",
2614742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso					(char *)nftnl_chain_get(chain, NFTNL_CHAIN_NAME),
26158b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					strerror(errno));
26166a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey				goto err;
26178b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			}
26188b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			continue;
26198b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
26208b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
26218b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		xtables_config_perror(flags,
26228b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			"chain `%s' in table `%s' has been created\n",
2623742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			(char *)nftnl_chain_get(chain, NFTNL_CHAIN_NAME),
2624742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			(char *)nftnl_chain_get(chain, NFTNL_CHAIN_TABLE));
26258b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
2626742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_iter_destroy(citer);
2627742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_free(chain_list);
26282c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso
26298b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	return 0;
26306a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey
26316a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Reyerr:
2632742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_table_list_free(table_list);
2633742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_free(chain_list);
26346a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey
26356a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey	if (titer != NULL)
2636742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_table_list_iter_destroy(titer);
26376a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey	if (citer != NULL)
2638742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_list_iter_destroy(citer);
26396a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey
26406a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey	return -1;
26418b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso}
2642b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2643b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longoint nft_chain_zero_counters(struct nft_handle *h, const char *chain,
2644b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			    const char *table)
2645b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo{
2646742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list *list;
2647742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain_list_iter *iter;
2648742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	struct nftnl_chain *c;
2649b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	int ret = 0;
2650b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2651742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	list = nftnl_chain_list_get(h);
2652b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	if (list == NULL)
2653b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		goto err;
2654b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2655742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	iter = nftnl_chain_list_iter_create(list);
2656b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2657b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2658b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2659742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	c = nftnl_chain_list_iter_next(iter);
2660b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	while (c != NULL) {
2661b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		const char *chain_name =
2662742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get(c, NFTNL_CHAIN_NAME);
2663b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		const char *chain_table =
2664742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_get(c, NFTNL_CHAIN_TABLE);
2665b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2666b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		if (strcmp(table, chain_table) != 0)
2667b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			goto next;
2668b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2669b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		if (chain != NULL && strcmp(chain, chain_name) != 0)
2670b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			goto next;
2671b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2672742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
2673742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
2674b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2675742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
2676b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
26771d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		if (h->batch_support) {
26781d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso			ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c);
26791d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		} else {
26801d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso			struct nlmsghdr *nlh;
26811d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso			char buf[MNL_SOCKET_BUFFER_SIZE];
26821d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso
2683742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
26841d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso							h->family, NLM_F_ACK,
26851d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso							h->seq);
2686742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso			nftnl_chain_nlmsg_build_payload(nlh, c);
26871d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso			ret = mnl_talk(h, nlh, NULL, NULL);
26881d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso		}
2689b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
269036ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
269136ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
2692b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longonext:
2693742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		c = nftnl_chain_list_iter_next(iter);
2694b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	}
2695b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
26961d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso	if (!h->batch_support)
2697742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso		nftnl_chain_list_free(list);
26981d395bcb585dd941859f2206eed89da23d19909cPablo Neira Ayuso
2699742baabd185c326cc2125e648e240894362eb31cPablo Neira Ayuso	nftnl_chain_list_iter_destroy(iter);
2700b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2701b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longoerr:
2702b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	/* the core expects 1 for success and 0 for error */
2703b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	return ret == 0 ? 1 : 0;
2704b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo}
2705c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero
2706c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrerouint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag)
2707c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero{
2708c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero	if (invflags & flag)
2709c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero		return NFT_CMP_NEQ;
2710c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero
2711c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero	return NFT_CMP_EQ;
2712c82bf9f79bbc299de428fdc2e204d571b6cbc50dArturo Borrero}
27134b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27144b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay#define NFT_COMPAT_EXPR_MAX     8
27154b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27164b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garaystatic const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = {
27174b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	"match",
27184b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	"target",
27194b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	"payload",
27204b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	"meta",
27214b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	"cmp",
27224b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	"bitwise",
27234b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	"counter",
27244b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	"immediate"
27254b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay};
27264b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27274b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27284b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garaystatic int nft_is_expr_compatible(const char *name)
27294b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay{
27304b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	int i;
27314b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27324b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	for (i = 0; i < NFT_COMPAT_EXPR_MAX; i++) {
27334b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		if (strcmp(supported_exprs[i], name) == 0)
27344b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			return 0;
27354b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	}
27364b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27374b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	return 1;
27384b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay}
27394b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27404b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garaystatic int nft_is_rule_compatible(struct nftnl_rule *rule)
27414b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay{
27424b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct nftnl_expr_iter *iter;
27434b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct nftnl_expr *expr;
27444b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	int ret = 0;
27454b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27464b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	iter = nftnl_expr_iter_create(rule);
27474b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	if (iter == NULL)
27484b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		return -1;
27494b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27504b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	expr = nftnl_expr_iter_next(iter);
27514b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	while (expr != NULL) {
27524b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME);
27534b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27544b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		if (nft_is_expr_compatible(name) == 0) {
27554b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			expr = nftnl_expr_iter_next(iter);
27564b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			continue;
27574b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		}
27584b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27594b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		ret = 1;
27604b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		break;
27614b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	}
27624b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27634b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	nftnl_expr_iter_destroy(iter);
27644b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	return ret;
27654b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay}
27664b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27674b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garaystatic int nft_is_chain_compatible(const char *table, const char *chain)
27684b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay{
27694b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	const char *cur_table;
27704b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct builtin_chain *chains;
27714b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	int i, j;
27724b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27734b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	for (i = 0; i < TABLES_MAX; i++) {
27744b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		cur_table = xtables_ipv4[i].name;
27754b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		chains = xtables_ipv4[i].chains;
27764b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27774b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		if (strcmp(table, cur_table) != 0)
27784b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			continue;
27794b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27804b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		for (j = 0; j < NF_INET_NUMHOOKS && chains[j].name; j++) {
27814b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			if (strcmp(chain, chains[j].name) == 0)
27824b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay				return 0;
27834b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		}
27844b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	}
27854b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27864b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	return 1;
27874b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay}
27884b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27894b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garaystatic int nft_are_chains_compatible(struct nft_handle *h)
27904b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay{
27914b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct nftnl_chain_list *list;
27924b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct nftnl_chain_list_iter *iter;
27934b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct nftnl_chain *chain;
27944b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	int ret = 0;
27954b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
27964b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	list = nftnl_chain_list_get(h);
27974b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	if (list == NULL)
27984b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		return -1;
27994b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28004b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	iter = nftnl_chain_list_iter_create(list);
28014b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	if (iter == NULL)
28024b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		return -1;
28034b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28044b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	chain = nftnl_chain_list_iter_next(iter);
28054b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	while (chain != NULL) {
28064b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		if (!nft_chain_builtin(chain))
28074b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			goto next;
28084b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28094b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		const char *table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE);
28104b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		const char *name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME);
28114b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28124b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		if (nft_is_chain_compatible(table, name) == 1) {
28134b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			ret = 1;
28144b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			break;
28154b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		}
28164b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28174b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garaynext:
28184b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		chain = nftnl_chain_list_iter_next(iter);
28194b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	}
28204b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28214b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	nftnl_chain_list_iter_destroy(iter);
28224b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	nftnl_chain_list_free(list);
28234b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	return ret;
28244b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay}
28254b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28264b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garaystatic int nft_is_table_compatible(const char *name)
28274b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay{
28284b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	int i;
28294b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28304b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	for (i = 0; i < TABLES_MAX; i++) {
28314b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		if (strcmp(xtables_ipv4[i].name, name) == 0)
28324b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			return 0;
28334b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	}
28344b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28354b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	return 1;
28364b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay}
28374b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28384b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garaystatic int nft_are_tables_compatible(struct nft_handle *h)
28394b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay{
28404b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct nftnl_table_list *list;
28414b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct nftnl_table_list_iter *iter;
28424b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct nftnl_table *table;
28434b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	int ret = 0;
28444b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28454b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	list = nftnl_table_list_get(h);
28464b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	if (list == NULL)
28474b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		return -1;
28484b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28494b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	iter = nftnl_table_list_iter_create(list);
28504b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	if (iter == NULL)
28514b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		return -1;
28524b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28534b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	table = nftnl_table_list_iter_next(iter);
28544b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	while (table != NULL) {
28554b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		const char *name = nftnl_table_get(table, NFTNL_TABLE_NAME);
28564b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28574b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		if (nft_is_table_compatible(name) == 0) {
28584b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			table = nftnl_table_list_iter_next(iter);
28594b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			continue;
28604b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		}
28614b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28624b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		ret = 1;
28634b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		break;
28644b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	}
28654b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28664b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	nftnl_table_list_iter_destroy(iter);
28674b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	nftnl_table_list_free(list);
28684b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	return ret;
28694b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay}
28704b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28714b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garayint nft_is_ruleset_compatible(struct nft_handle *h)
28724b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay{
28734b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28744b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct nftnl_rule_list *list;
28754b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct nftnl_rule_list_iter *iter;
28764b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	struct nftnl_rule *rule;
28774b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	int ret = 0;
28784b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28794b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	ret = nft_are_tables_compatible(h);
28804b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	if (ret != 0)
28814b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		return ret;
28824b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28834b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	ret = nft_are_chains_compatible(h);
28844b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	if (ret != 0)
28854b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		return ret;
28864b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28874b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	list = nft_rule_list_get(h);
28884b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	if (list == NULL)
28894b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		return -1;
28904b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28914b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	iter = nftnl_rule_list_iter_create(list);
28924b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	if (iter == NULL)
28934b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		return -1;
28944b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
28954b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	rule = nftnl_rule_list_iter_next(iter);
28964b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	while (rule != NULL) {
28974b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		ret = nft_is_rule_compatible(rule);
28984b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		if (ret != 0)
28994b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay			break;
29004b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
29014b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay		rule = nftnl_rule_list_iter_next(iter);
29024b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	}
29034b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay
29044b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	nftnl_rule_list_iter_destroy(iter);
29054b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay	return ret;
29064b791044cd0984c9a1771e86fa77fce9d309d9e7Pablo M. Bermudo Garay}
2907