nft.c revision e6b8e172fca48f5d80699afe80947b0fc1f23fd6
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>
45384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
46384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <netinet/in.h>	/* inet_ntoa */
47384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <arpa/inet.h>
48384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
49384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include "nft.h"
50384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include "xshared.h" /* proto_to_name */
51077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka#include "nft-shared.h"
528b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso#include "xtables-config-parser.h"
53384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
54384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void *nft_fn;
55384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
5684909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longoint mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
5784909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	     int (*cb)(const struct nlmsghdr *nlh, void *data),
5884909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	     void *data)
59384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
60384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
61384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
62384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
63384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0) {
64384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_send");
65384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
66384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
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
97d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic struct mnl_nlmsg_batch *mnl_nft_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 *
110d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusomnl_nft_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
122d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return mnl_nft_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
144d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nl)
145d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
146d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	static const struct sockaddr_nl snl = {
147d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.nl_family = AF_NETLINK
148d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	};
149d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct iovec iov[batch_num_pages];
150d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct msghdr msg = {
151d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.msg_name	= (struct sockaddr *) &snl,
152d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.msg_namelen	= sizeof(snl),
153d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.msg_iov	= iov,
154d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		.msg_iovlen	= batch_num_pages,
155d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	};
156d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct batch_page *batch_page, *next;
157d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	int i = 0;
158d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
159d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	mnl_nft_set_sndbuffer(nl);
160d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
161d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	list_for_each_entry_safe(batch_page, next, &batch_page_list, head) {
162d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		iov[i].iov_base = mnl_nlmsg_batch_head(batch_page->batch);
163d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		iov[i].iov_len = mnl_nlmsg_batch_size(batch_page->batch);
164d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		i++;
165d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso#ifdef NL_DEBUG
166d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		mnl_nlmsg_fprintf(stdout,
167d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso				  mnl_nlmsg_batch_head(batch_page->batch),
168d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso				  mnl_nlmsg_batch_size(batch_page->batch),
169d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso				  sizeof(struct nfgenmsg));
170d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso#endif
171d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		list_del(&batch_page->head);
172d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		free(batch_page->batch);
173d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		free(batch_page);
174d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		batch_num_pages--;
175d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	}
176d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
177d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return sendmsg(mnl_socket_get_fd(nl), &msg, 0);
178d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
179d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
180d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic int cb_err(const struct nlmsghdr *nlh, void *data)
181d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
182d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	/* We can provide better error reporting than iptables-restore */
183d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	errno = EINVAL;
184d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return MNL_CB_ERROR;
185d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
186d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
187d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic mnl_cb_t cb_ctl_array[NLMSG_MIN_TYPE] = {
188d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	[NLMSG_ERROR] = cb_err,
189d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso};
190d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
191d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic int mnl_nft_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);
203d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (ret == -1) {
204d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		perror("mnl_socket_sendmsg");
205d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return -1;
206d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	}
207d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
208d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	FD_ZERO(&readfds);
209d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	FD_SET(fd, &readfds);
210d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
211d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	/* receive and digest all the acknowledgments from the kernel. */
212d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	ret = select(fd+1, &readfds, NULL, NULL, &tv);
213d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (ret == -1) {
214d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		perror("select");
215d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return -1;
216d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	}
217d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	while (ret > 0 && FD_ISSET(fd, &readfds)) {
218d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		ret = mnl_socket_recvfrom(h->nl, rcv_buf, sizeof(rcv_buf));
219d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		if (ret == -1) {
220d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			perror("mnl_socket_recvfrom");
221d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			return -1;
222d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		}
223d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
224d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		ret = mnl_cb_run2(rcv_buf, ret, 0, h->portid,
225d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso				  NULL, NULL, cb_ctl_array,
226d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso				  MNL_ARRAY_SIZE(cb_ctl_array));
227d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		/* Continue on error, make sure we get all acknoledgments */
228d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		if (ret == -1)
229d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			err = errno;
230d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
231d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		ret = select(fd+1, &readfds, NULL, NULL, &tv);
232d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		if (ret == -1) {
233d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			perror("select");
234d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			return -1;
235d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		}
236d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		FD_ZERO(&readfds);
237d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		FD_SET(fd, &readfds);
238d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	}
239d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return err ? -1 : 0;
240d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
241d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
242d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic void mnl_nft_batch_put(struct mnl_nlmsg_batch *batch, int type,
243d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			      uint32_t seq)
244d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
245d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct nlmsghdr *nlh;
246d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct nfgenmsg *nfg;
247d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
248d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	nlh = mnl_nlmsg_put_header(mnl_nlmsg_batch_current(batch));
249d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	nlh->nlmsg_type = type;
250d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	nlh->nlmsg_flags = NLM_F_REQUEST;
251d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	nlh->nlmsg_seq = seq;
252d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
253d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
254d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	nfg->nfgen_family = AF_INET;
255d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	nfg->version = NFNETLINK_V0;
256d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	nfg->res_id = NFNL_SUBSYS_NFTABLES;
257d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
258d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (!mnl_nlmsg_batch_next(batch))
259d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		mnl_nft_batch_page_add(batch);
260d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
261d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
262d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic void mnl_nft_batch_begin(struct mnl_nlmsg_batch *batch, uint32_t seq)
263d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
264d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	mnl_nft_batch_put(batch, NFNL_MSG_BATCH_BEGIN, seq);
265d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
266d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
267d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic void mnl_nft_batch_end(struct mnl_nlmsg_batch *batch, uint32_t seq)
268d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
269d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	mnl_nft_batch_put(batch, NFNL_MSG_BATCH_END, seq);
270d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
271d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
272afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longostruct builtin_table xtables_ipv4[TABLES_MAX] = {
273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[RAW] = {
274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "raw",
275e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
276e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
277e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "PREROUTING",
278890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
2795b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -300,	/* NF_IP_PRI_RAW */
280e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
281e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
282e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
283e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
284890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
2855b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -300,	/* NF_IP_PRI_RAW */
286e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
287e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
288e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[MANGLE] = {
291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "mangle",
292e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
293e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
294e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "PREROUTING",
295890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
2965b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
297e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
298e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
299e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
300e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
301890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3025b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
303e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
304e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
305e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
306e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
307890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3085b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
309e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
310e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
311e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
312e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
313890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "route",
3145b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
315e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
316e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
317e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
318e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "POSTROUTING",
319890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3205b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
321e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_POST_ROUTING,
322e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
323e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
325384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[FILTER] = {
326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "filter",
327e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
328e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
329e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
330890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3315b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
332e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
333e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
334e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
335e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
336890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3375b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
338e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
339e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
340e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
341e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
342890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3435b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
344e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
345e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
346e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
347384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[SECURITY] = {
349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "security",
350e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
351e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
352e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
353890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3545b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
355e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
356e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
357e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
358e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
359890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3605b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
361e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
362e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
363e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
364e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
365890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
3665b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
367e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
368e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		},
370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
371890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	[NAT] = {
372890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		.name	= "nat",
373890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		.chains = {
374890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
37586eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.name	= "PREROUTING",
376890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
377890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= -100, /* NF_IP_PRI_NAT_DST */
37886eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
379890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
380890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
381890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "INPUT",
382890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
383890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= 100, /* NF_IP_PRI_NAT_SRC */
384890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
385890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
386890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
387890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "POSTROUTING",
388890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
389890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= 100, /* NF_IP_PRI_NAT_SRC */
390890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_POST_ROUTING,
391890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
39286eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso			{
39386eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.name	= "OUTPUT",
39486eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.type	= "nat",
39586eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.prio	= -100, /* NF_IP_PRI_NAT_DST */
39686eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
39786eed10c9f2c42e0f50eb4e527a48ee9e63146f4Pablo Neira Ayuso			},
398890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		},
399890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	},
400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso};
401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
40284909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo#include <linux/netfilter_arp.h>
40384909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo
40484909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longostruct builtin_table xtables_arp[TABLES_MAX] = {
40584909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	[FILTER] = {
40684909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	.name   = "filter",
40784909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	.chains = {
40884909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			{
40984909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.name   = "INPUT",
41084909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.type   = "filter",
41184909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.prio   = NF_IP_PRI_FILTER,
41284909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.hook   = NF_ARP_IN,
41384909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			},
41484909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			{
41584909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.name   = "FORWARD",
41684909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.type   = "filter",
41784909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.prio   = NF_IP_PRI_FILTER,
41884909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.hook   = NF_ARP_FORWARD,
41984909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			},
42084909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			{
42184909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.name   = "OUTPUT",
42284909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.type   = "filter",
42384909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.prio   = NF_IP_PRI_FILTER,
42484909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo				.hook   = NF_ARP_OUT,
42584909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo			},
42684909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo		},
42784909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo	},
42884909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo};
42984909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longo
43084909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longoint
4315705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusonft_table_builtin_add(struct nft_handle *h, struct builtin_table *_t,
4325705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso			bool dormant)
4335b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso{
4345b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
4355b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	struct nlmsghdr *nlh;
4365b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	struct nft_table *t;
4375b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	int ret;
4385b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
439e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka	if (_t->initialized)
440e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka		return 0;
441e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka
4425b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	t = nft_table_alloc();
4435b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	if (t == NULL)
4445b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso		return -1;
4455b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
4465b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)_t->name);
4475705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (dormant) {
4485705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS,
4495705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso					NFT_TABLE_F_DORMANT);
4505705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	}
4515b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
4520391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
4535b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
4545b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
4555b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_table_free(t);
4565b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
457837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka#ifdef NLDEBUG
458837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka	char tmp[1024];
459837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka
460837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka	nft_table_snprintf(tmp, sizeof(tmp), t, 0, 0);
461837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka	printf("DEBUG: table: %s", tmp);
462837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
463837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka#endif
464837629fed24af7298fbf4cd28c7a51f24b70ee93Tomasz Bursztyka
4655b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
4665b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	if (ret < 0) {
4675b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso		if (errno != EEXIST)
4685b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso			perror("mnl-talk:nft_table_init_one");
4695b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	}
470e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka
471e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka	if (ret == 0 || errno == EEXIST)
472e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka		_t->initialized = true;
473e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka
4745b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	return ret;
4755b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso}
4765b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
47784909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longostruct nft_chain *
478c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_alloc(struct builtin_table *table,
479c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			struct builtin_chain *chain, int policy)
480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL)
485c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		return NULL;
486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table->name);
488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain->name);
489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_HOOKNUM, chain->hook);
4905b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_PRIO, chain->prio);
491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy);
492890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TYPE, (char *)chain->type);
493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
494c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return c;
495c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
496c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
49784909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longovoid
498c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table,
499c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		      struct builtin_chain *chain, int policy)
500c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
501c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
502c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct nlmsghdr *nlh;
503c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct nft_chain *c;
504c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
505c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	c = nft_chain_builtin_alloc(table, chain, policy);
506c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (c == NULL)
507c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		return;
508c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
509890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	/* NLM_F_CREATE requests module autoloading */
5100391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
511890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE,
512890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso					h->seq);
513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_talk(h, nlh, NULL, NULL) < 0) {
517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
518c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			perror("mnl_talk:nft_chain_builtin_add");
519c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
520c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
521c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
522c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in table already exists */
52384909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longostruct builtin_table *
52484909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longonft_table_builtin_find(struct nft_handle *h, const char *table)
525c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
526c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	int i;
527c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	bool found = false;
528c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
529c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	for (i=0; i<TABLES_MAX; i++) {
53067da6075a4e7ced0e8cc452d73ce8ab06cbf8cd9Tomasz Bursztyka		if (h->tables[i].name == NULL)
53167da6075a4e7ced0e8cc452d73ce8ab06cbf8cd9Tomasz Bursztyka			break;
53267da6075a4e7ced0e8cc452d73ce8ab06cbf8cd9Tomasz Bursztyka
533afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longo		if (strcmp(h->tables[i].name, table) != 0)
534c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			continue;
535c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
536c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		found = true;
537c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		break;
538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
539c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
540afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longo	return found ? &h->tables[i] : NULL;
541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
543c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in chain already exists */
54484909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longostruct builtin_chain *
545e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusonft_chain_builtin_find(struct builtin_table *t, const char *chain)
546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
547e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int i;
548c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	bool found = false;
549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
550e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	for (i=0; i<NF_IP_NUMHOOKS && t->chains[i].name != NULL; i++) {
551e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (strcmp(t->chains[i].name, chain) != 0)
552e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			continue;
553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
554e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		found = true;
555e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		break;
556e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	}
557e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	return found ? &t->chains[i] : NULL;
558e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso}
559e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
560e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusostatic void
561e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso__nft_chain_builtin_init(struct nft_handle *h,
562e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			 struct builtin_table *table, const char *chain,
563e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			 int policy)
564e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso{
565e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int i, default_policy;
566e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
567e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* Initialize all built-in chains. Exception, for e one received as
568e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	 * parameter, set the default policy as requested.
569e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	 */
570e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	for (i=0; i<NF_IP_NUMHOOKS && table->chains[i].name != NULL; i++) {
571e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (chain && strcmp(table->chains[i].name, chain) == 0)
572e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			default_policy = policy;
573e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		else
574e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			default_policy = NF_ACCEPT;
575e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
576e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		nft_chain_builtin_add(h, table, &table->chains[i],
577e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso					default_policy);
578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
579c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
580c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
58184909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longoint
582c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_init(struct nft_handle *h, const char *table,
583c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		       const char *chain, int policy)
584c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
585c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	int ret = 0;
586c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_table *t;
587c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
588afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longo	t = nft_table_builtin_find(h, table);
589c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (t == NULL) {
590c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		ret = -1;
591c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		goto out;
592c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
5935705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (nft_table_builtin_add(h, t, false) < 0) {
594e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		/* Built-in table already initialized, skip. */
595e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (errno == EEXIST)
596e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			goto out;
597c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
598e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	__nft_chain_builtin_init(h, t, chain, policy);
599c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusoout:
600c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return ret;
601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
6037244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztykastatic bool nft_chain_builtin(struct nft_chain *c)
6047244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka{
6057244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka	/* Check if this chain has hook number, in that case is built-in.
6067244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka	 * Should we better export the flags to user-space via nf_tables?
6077244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka	 */
6087244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka	return nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM) != NULL;
6097244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka}
6107244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka
611afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longoint nft_init(struct nft_handle *h, struct builtin_table *t)
612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->nl = mnl_socket_open(NETLINK_NETFILTER);
614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (h->nl == NULL) {
615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_open");
616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_bind");
621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->portid = mnl_socket_get_portid(h->nl);
624afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longo	h->tables = t;
625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
626d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	INIT_LIST_HEAD(&h->rule_list);
627d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
628d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	h->batch = mnl_nft_batch_alloc();
629d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusovoid nft_fini(struct nft_handle *h)
634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(h->nl);
636b0194cea194b510c675ca05415da15cff57afe47Ana Rey	free(mnl_nlmsg_batch_head(h->batch));
637b0194cea194b510c675ca05415da15cff57afe47Ana Rey	mnl_nlmsg_batch_stop(h->batch);
638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
639384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_table_add(struct nft_handle *h, const struct nft_table *t)
641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
6450391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_add(struct nft_handle *h, const struct nft_chain *c)
653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
6570391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
6645705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoint nft_table_set_dormant(struct nft_handle *h, const char *table)
6655705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso{
6665705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	int ret = 0, i;
6675705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct builtin_table *t;
6685705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
669afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longo	t = nft_table_builtin_find(h, table);
6705705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (t == NULL) {
6715705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		ret = -1;
6725705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		goto out;
6735705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	}
6745705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	/* Add this table as dormant */
6755705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (nft_table_builtin_add(h, t, true) < 0) {
6765705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		/* Built-in table already initialized, skip. */
6775705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		if (errno == EEXIST)
6785705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso			goto out;
6795705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	}
6805705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	for (i=0; t->chains[i].name != NULL && i<NF_INET_NUMHOOKS; i++)
6815705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		__nft_chain_builtin_init(h, t, t->chains[i].name, NF_ACCEPT);
6825705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoout:
6835705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	return ret;
6845705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso}
6855705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
6865705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoint nft_table_wake_dormant(struct nft_handle *h, const char *table)
6875705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso{
6885705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
6895705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct nlmsghdr *nlh;
6905705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct nft_table *t;
6915705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
6925705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	t = nft_table_alloc();
6935705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (t == NULL)
6945705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		return -1;
6955705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
6965705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)table);
6975705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS, 0);
6985705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
6990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
7005705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso					NLM_F_ACK, h->seq);
7015705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
7025705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_free(t);
7035705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
7045705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
7055705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso}
7065705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_debug(struct nft_chain *c, struct nlmsghdr *nlh)
708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_snprintf(tmp, sizeof(tmp), c, 0, 0);
713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("DEBUG: chain: %s", tmp);
714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_chain_set(struct nft_handle *h, const char *table,
720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain, int policy,
721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const struct xt_counters *counters)
722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
726c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_table *_t;
727c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_chain *_c;
728e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int ret;
729c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
730afae1f841bc2c4b39a38fa97d271f3877d00bf3aGiuseppe Longo	_t = nft_table_builtin_find(h, table);
731c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	/* if this built-in table does not exists, create it */
732c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_t != NULL)
7335705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		nft_table_builtin_add(h, _t, false);
734c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
735e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	_c = nft_chain_builtin_find(_t, chain);
736c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_c != NULL) {
737c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		/* This is a built-in chain */
738c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		c = nft_chain_builtin_alloc(_t, _c, policy);
739c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		if (c == NULL)
740c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			return -1;
741c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	} else {
74220c156f9f4c43857a622f015a3022517601c3600Tomasz Bursztyka		errno = ENOENT;
74320c156f9f4c43857a622f015a3022517601c3600Tomasz Bursztyka		return -1;
744c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
746384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (counters) {
747384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES,
748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->bcnt);
749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_PACKETS,
750384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->pcnt);
751384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
752384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
7530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
754690ea18fdd6f8bc12322a729a2f7c97d8e731c43Tomasz Bursztyka					h->restore ? NLM_F_ACK|NLM_F_CREATE :
755384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
756384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
757384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
758384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_print_debug(c, nlh);
759384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
760384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
761384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
762384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
763384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
764384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:__nft_chain_policy");
765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
766384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
769384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_set(struct nft_handle *h, const char *table,
770384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const char *chain, const char *policy,
771384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const struct xt_counters *counters)
772384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
773384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = -1;
774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
775384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_chain_set;
776384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
777384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(policy, "DROP") == 0)
778384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_set(h, table, chain, NF_DROP, counters);
779384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else if (strcmp(policy, "ACCEPT") == 0)
780384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_set(h, table, chain, NF_ACCEPT, counters);
781384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
783384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
784384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
785384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
786f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztykastatic int __add_match(struct nft_rule_expr *e, struct xt_entry_match *m)
787384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
788384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	void *info;
789384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
790384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_MT_NAME, m->u.user.name, strlen(m->u.user.name));
791384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(e, NFT_EXPR_MT_REV, m->u.user.revision);
792384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
793384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	info = calloc(1, m->u.match_size);
794384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (info == NULL)
795f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
796384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
7975eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso	memcpy(info, m->data, m->u.match_size - sizeof(*m));
798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_MT_INFO, info, m->u.match_size - sizeof(*m));
799f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
800f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
802384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
803c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayusoint add_match(struct nft_rule *r, struct xt_entry_match *m)
804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
806f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	int ret;
807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("match");
809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
810f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
811384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
812f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	ret = __add_match(expr, m);
813384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
814f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
815f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return ret;
816384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
817384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
818f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztykastatic int __add_target(struct nft_rule_expr *e, struct xt_entry_target *t)
819384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
8205eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso	void *info;
821384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
822384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_TG_NAME, t->u.user.name,
823384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  strlen(t->u.user.name));
824384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(e, NFT_EXPR_TG_REV, t->u.user.revision);
825384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
8265eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso	info = calloc(1, t->u.target_size);
8275eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso	if (info == NULL)
8285eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso		return -ENOMEM;
829384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
8305eed9118f2620ac07edd553599e2415f00d6f8f3Pablo Neira Ayuso	memcpy(info, t->data, t->u.target_size - sizeof(*t));
831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_TG_INFO, info, t->u.target_size - sizeof(*t));
832f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
833f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
834384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
83684909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longoint add_target(struct nft_rule *r, struct xt_entry_target *t)
837384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
839f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	int ret;
840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("target");
842384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
843f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
844384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
845f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	ret = __add_target(expr, t);
846384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
847f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
848f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return ret;
849384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
850384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
85184909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longoint add_jumpto(struct nft_rule *r, const char *name, int verdict)
852384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
853384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
854384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
855384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("immediate");
856384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
857f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
858384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
859384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT);
860384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict);
861384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_str(expr, NFT_EXPR_IMM_CHAIN, (char *)name);
862384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
863f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
864f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
865384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
866384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
86784909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longoint add_verdict(struct nft_rule *r, int verdict)
868384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
871384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("immediate");
872384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
873f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT);
876384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict);
877384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
878f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
879f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
880384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
881384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
882c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayusoint add_action(struct nft_rule *r, struct iptables_command_state *cs,
883d007e1a59e4beaddab430992302d43b122ffc801Pablo Neira Ayuso	       bool goto_set)
884c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso{
885c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       int ret = 0;
886c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso
887c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       /* If no target at all, add nothing (default to continue) */
888c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       if (cs->target != NULL) {
889c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       /* Standard target? */
890c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
891c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_verdict(r, NF_ACCEPT);
892c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
893c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_verdict(r, NF_DROP);
894c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
895c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_verdict(r, NFT_RETURN);
896c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       else
897c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_target(r, cs->target->t);
898c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       } else if (strlen(cs->jumpto) > 0) {
899c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       /* Not standard, then it's a go / jump to chain */
900d007e1a59e4beaddab430992302d43b122ffc801Pablo Neira Ayuso	       if (goto_set)
901c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_jumpto(r, cs->jumpto, NFT_GOTO);
902c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	       else
903c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso		       ret = add_jumpto(r, cs->jumpto, NFT_JUMP);
904c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       }
905c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso       return ret;
906c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso}
907c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso
908384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_rule_print_debug(struct nft_rule *r, struct nlmsghdr *nlh)
909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_snprintf(tmp, sizeof(tmp), r, 0, 0);
914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("DEBUG: rule: %s", tmp);
915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
91984909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longoint add_counters(struct nft_rule *r, uint64_t packets, uint64_t bytes)
920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("counter");
924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
925f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_BYTES, packets);
928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_PACKETS, bytes);
929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
931f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
932f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
9354ef77b6d1b52e1fe52a7fd48d38d9233f0961640Pablo Neira Ayusovoid add_compat(struct nft_rule *r, uint32_t proto, bool inv)
9362a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso{
9372a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso	nft_rule_attr_set_u32(r, NFT_RULE_ATTR_COMPAT_PROTO, proto);
9382a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso	nft_rule_attr_set_u32(r, NFT_RULE_ATTR_COMPAT_FLAGS,
9392a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso			      inv ? NFT_RULE_COMPAT_F_INV : 0);
9402a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso}
9412a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso
942cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusostatic struct nft_rule *
943cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusonft_rule_new(struct nft_handle *h, const char *chain, const char *table,
944c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	     void *data)
945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
946384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
949cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	if (r == NULL)
950cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso		return NULL;
951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
952d370c4ad803c37eedfbee5963fac6f7e9968939cTomasz Bursztyka	nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FAMILY, h->family);
953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
956c6836c19592dbe1a8be9b0ad76c0ae09abcb82e7Pablo Neira Ayuso	if (h->ops->add(r, data) < 0)
957cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso		goto err;
958cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
959cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	return r;
960cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusoerr:
961cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	nft_rule_free(r);
962cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	return NULL;
963cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso}
964cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
965d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusoenum rule_update_type {
966d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       NFT_DO_APPEND,
967d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       NFT_DO_INSERT,
968d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       NFT_DO_REPLACE,
969d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       NFT_DO_DELETE,
970d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       NFT_DO_FLUSH,
971d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       NFT_DO_COMMIT,
972d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       NFT_DO_ABORT,
973d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso};
974d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
975d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostruct rule_update {
976d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       struct list_head        head;
977d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       enum rule_update_type   type;
978d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       struct nft_rule	       *rule;
979d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso};
980d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
981d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic int rule_update_add(struct nft_handle *h, enum rule_update_type type,
982d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			  struct nft_rule *r)
983d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso{
984d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       struct rule_update *rupd;
985d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
986d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       rupd = calloc(1, sizeof(struct rule_update));
987d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       if (rupd == NULL)
988d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	       return -1;
989d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
990d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       rupd->rule = r;
991d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       rupd->type = type;
992d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       list_add_tail(&rupd->head, &h->rule_list);
993d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       h->rule_list_num++;
994d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
995d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso       return 0;
996d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso}
997d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
998cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusoint
999cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusonft_rule_append(struct nft_handle *h, const char *chain, const char *table,
1000b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		void *data, uint64_t handle, bool verbose)
1001cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso{
1002cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	struct nft_rule *r;
1003d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	int type;
1004cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1005cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
1006cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
1007cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso		nft_chain_builtin_init(h, table, chain, NF_ACCEPT);
1008cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1009cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	nft_fn = nft_rule_append;
1010cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1011b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso	r = nft_rule_new(h, chain, table, data);
1012d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (r == NULL)
1013d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return 0;
1014384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
10150a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	if (handle > 0) {
10160a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka		nft_rule_attr_set(r, NFT_RULE_ATTR_HANDLE, &handle);
1017d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		type = NFT_DO_REPLACE;
1018cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	} else
1019d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		type = NFT_DO_APPEND;
1020384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1021d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (rule_update_add(h, type, r) < 0)
1022d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		nft_rule_free(r);
1023384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1024d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return 1;
1025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
10271ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayusovoid
10288877968858a8dd6b7ae096988d57a7511c81733dGiuseppe Longonft_rule_print_save(const void *data,
1029cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka		    struct nft_rule *r, enum nft_rule_print type,
1030cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka		    unsigned int format)
1031384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
10321ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	const char *chain = nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
1033cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka	int family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
1034cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka	struct nft_family_ops *ops;
1035384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1036384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
10371ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	switch(type) {
10381ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	case NFT_RULE_APPEND:
10391ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		printf("-A %s ", chain);
10401ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		break;
10411ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	case NFT_RULE_DEL:
10421ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		printf("-D %s ", chain);
10431ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		break;
10441ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	}
1045384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1046cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka	ops = nft_family_ops_lookup(family);
1047cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka
10488877968858a8dd6b7ae096988d57a7511c81733dGiuseppe Longo	if (ops->save_firewall)
10498877968858a8dd6b7ae096988d57a7511c81733dGiuseppe Longo		ops->save_firewall(data, format);
1050cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka
1051384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1052384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1053384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_chain_list_cb(const struct nlmsghdr *nlh, void *data)
1054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list = data;
1057384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1058384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
1059384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL) {
1060384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1061384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1062384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_chain_nlmsg_parse(nlh, c) < 0) {
1065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1069f77e1aca9aa8851b469f79c2db80ddb6f49253b2Pablo Neira Ayuso	nft_chain_list_add_tail(c, list);
1070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
1074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_chain_list *nft_chain_list_get(struct nft_handle *h)
1079384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1080384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1081384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1082384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_alloc();
1086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1087b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		errno = ENOMEM;
1088b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		return NULL;
1089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
10910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
1092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_chain_list_cb, list);
1095384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1096384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_chain_list_get");
1097384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1101384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostruct nft_chain_list *nft_chain_dump(struct nft_handle *h)
1102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1103384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return nft_chain_list_get(h);
1104384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1105384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic const char *policy_name[NF_ACCEPT+1] = {
1107384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_DROP] = "DROP",
1108384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_ACCEPT] = "ACCEPT",
1109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso};
1110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1111384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_save(struct nft_chain *c, bool basechain)
1112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1114384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint64_t pkts = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS);
1115384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint64_t bytes = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES);
1116384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1117384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
1118384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (basechain) {
1119384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t pol = NF_ACCEPT;
1120384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1121384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* no default chain policy? don't crash, display accept */
1122384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_POLICY))
1123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			pol = nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
1124384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11250a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		printf(":%s %s [%"PRIu64":%"PRIu64"]\n", chain, policy_name[pol],
1126384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					     pkts, bytes);
1127384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else
11280a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		printf(":%s - [%"PRIu64":%"PRIu64"]\n", chain, pkts, bytes);
1129384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1130384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1131384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_save(struct nft_handle *h, struct nft_chain_list *list,
1132384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   const char *table)
1133384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1134384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1135384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1136384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1137384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1138b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1139384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1143384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
1144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
1146384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1147384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
1148384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1149384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11507244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka		basechain = nft_chain_builtin(c);
1151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_print_save(c, basechain);
1152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1155384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1156d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_chain_list_iter_destroy(iter);
1157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1160384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1161384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_rule_list_cb(const struct nlmsghdr *nlh, void *data)
1163384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1164384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1165384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list = data;
1166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
1168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL) {
1169384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1170384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_rule_nlmsg_parse(nlh, r) < 0) {
1174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1178f77e1aca9aa8851b469f79c2db80ddb6f49253b2Pablo Neira Ayuso	nft_rule_list_add_tail(r, list);
1179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1182384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
1183137cc981906f356c971da6de13e777a419382ff4Giuseppe Longo	nft_rule_list_free(list);
1184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1187384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1188384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_rule_list *nft_rule_list_get(struct nft_handle *h)
1189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
1193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1194384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1195384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_alloc();
1196b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1197384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1198384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
1200384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_rule_list_cb, list);
1203384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1204384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_save");
1205384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_rule_list_free(list);
1206384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return NULL;
1207384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1208384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1209384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1210384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_save(struct nft_handle *h, const char *table, bool counters)
1213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1214384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
1215384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list_iter *iter;
1216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1218384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
1219b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1220384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1222384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
1223b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1225384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
1227384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
1228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
1229384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
1230cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka		struct iptables_command_state cs = {};
1231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0)
1233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1234384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1235cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka		nft_rule_to_iptables_command_state(r, &cs);
1236cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka
1237cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka		nft_rule_print_save(&cs, r, NFT_RULE_APPEND,
1238cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka				    counters ? 0 : FMT_NOCOUNTS);
1239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
1242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1244d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_rule_list_iter_destroy(iter);
1245384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_free(list);
1246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1251384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
1253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
1257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL)
1258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1259384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
1261384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
1262384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1263d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (rule_update_add(h, NFT_DO_FLUSH, r) < 0)
1264d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		nft_rule_free(r);
1265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
1268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_flush;
1275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_get(h);
1277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
1279384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1283b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1284b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
1285384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		__nft_rule_flush(h, table_name, chain_name);
1300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
130136ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
130236ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
1303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1307d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_chain_list_iter_destroy(iter);
1308384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1311384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1312384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table)
1316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1320384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1322e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
13238b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
13248b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
1325e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
1326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
1327b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (c == NULL)
1328b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		return 0;
1329384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
1331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain);
1332384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
13330391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
1334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
1335384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
1336384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
1337384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1339384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1340384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
1341384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:nft_chain_add");
1342384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1343384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1344384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1347384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int __nft_chain_del(struct nft_handle *h, struct nft_chain *c)
1349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1350384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1352384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
13540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, h->family,
1355384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
1357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST && errno != ENOENT)
1361384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:__nft_chain_del");
1362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1364384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1365384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1366384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table)
1368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
1373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int deleted_ctr = 0;
1374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_get(h);
1376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1380b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1381b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
1382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* don't delete built-in chain */
1391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_builtin(c))
1392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_del(h, c);
1401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (ret < 0)
1402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		deleted_ctr++;
140536ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo
140636ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
140736ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
1408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1412d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_chain_list_iter_destroy(iter);
1413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* chain not found */
1417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0 && deleted_ctr == 0)
1418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
1419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14240aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusostruct nft_chain *
1425e127d223d01aaa0886c7f279110ac36651b9a057Tomasz Bursztykanft_chain_list_find(struct nft_chain_list *list,
14260aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		    const char *table, const char *chain)
14279c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso{
14289c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
14299c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	struct nft_chain *c;
14309c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14319c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1432b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
14339c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return NULL;
14349c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14359c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
14369c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	while (c != NULL) {
14379c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		const char *table_name =
14389c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
14399c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		const char *chain_name =
14409c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
14419c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14429c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
14439c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			goto next;
14449c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14459c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		if (strcmp(chain, chain_name) != 0)
14469c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			goto next;
14479c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14480aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		nft_chain_list_iter_destroy(iter);
14499c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return c;
14509c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayusonext:
14519c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
14529c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	}
14530aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	nft_chain_list_iter_destroy(iter);
14549c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	return NULL;
14559c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso}
14569c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14570aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusostatic struct nft_chain *
14580aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonft_chain_find(struct nft_handle *h, const char *table, const char *chain)
14590aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{
14600aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain_list *list;
14610aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
14620aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	list = nft_chain_list_get(h);
1463b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
14640aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		return NULL;
14650aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1466e127d223d01aaa0886c7f279110ac36651b9a057Tomasz Bursztyka	return nft_chain_list_find(list, table, chain);
14670aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso}
14680aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1469384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_rename(struct nft_handle *h,const char *chain,
1470384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  const char *table, const char *newname)
1471384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
14724493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	char buf[MNL_SOCKET_BUFFER_SIZE];
14734493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	struct nlmsghdr *nlh;
14744493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	struct nft_chain *c;
14759c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	uint64_t handle;
1476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14784493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	/* If built-in chains don't exist for this table, create them */
14798b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
14808b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
14814493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
14829c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	/* Find the old chain to be renamed */
14839c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	c = nft_chain_find(h, table, chain);
14849c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	if (c == NULL) {
14859c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		errno = ENOENT;
14869c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return -1;
14879c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	}
14889c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	handle = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_HANDLE);
14899c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14909c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	/* Now prepare the new name for the chain */
14914493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	c = nft_chain_alloc();
1492b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (c == NULL)
14934493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka		return -1;
14944493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
14954493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
14969c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)newname);
14979c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_HANDLE, handle);
1498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
15009c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
15014493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_nlmsg_build_payload(nlh, c);
15024493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_free(c);
15034493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
15044493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	ret = mnl_talk(h, nlh, NULL, NULL);
15054493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	if (ret < 0) {
15064493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka		if (errno != EEXIST)
15074493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka			perror("mnl_talk:nft_chain_rename");
15084493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	}
15094493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
15104493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	/* the core expects 1 for success and 0 for error */
15114493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	return ret == 0 ? 1 : 0;
1512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_table_list_cb(const struct nlmsghdr *nlh, void *data)
1515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list = data;
1518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_alloc();
1520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (t == NULL) {
1521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_table_nlmsg_parse(nlh, t) < 0) {
1526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1530f77e1aca9aa8851b469f79c2db80ddb6f49253b2Pablo Neira Ayuso	nft_table_list_add_tail(t, list);
1531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_free(t);
1535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_table_list *nft_table_list_get(struct nft_handle *h)
1540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_alloc();
1547b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
15500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
1551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_table_list_cb, list);
1554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_table_list_get");
1556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusobool nft_table_find(struct nft_handle *h, const char *tablename)
1561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list_iter *iter;
1564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool ret = false;
1566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_get(h);
1568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_table_list_iter_create(list);
1572b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_list_iter_next(iter);
1576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
1577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *this_tablename =
1578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_table_attr_get(t, NFT_TABLE_ATTR_NAME);
1579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(tablename, this_tablename) == 0)
1581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return true;
1582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		t = nft_table_list_iter_next(iter);
1584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_free(list);
1587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_for_each_table(struct nft_handle *h,
1593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       int (*func)(struct nft_handle *h, const char *tablename, bool counters),
1594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       bool counters)
1595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 1;
1597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list_iter *iter;
1599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_get(h);
1602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
1604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_table_list_iter_create(list);
1608b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_list_iter_next(iter);
1612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
1613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *tablename =
1614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_table_attr_get(t, NFT_TABLE_ATTR_NAME);
1615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		func(h, tablename, counters);
1617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		t = nft_table_list_iter_next(iter);
1619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_free(list);
1622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
16280aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusoint nft_table_purge_chains(struct nft_handle *h, const char *this_table,
16290aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			   struct nft_chain_list *chain_list)
16300aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{
16310aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain_list_iter *iter;
16320aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain *chain_obj;
16330aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16340aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	iter = nft_chain_list_iter_create(chain_list);
1635b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
16360aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		return 0;
16370aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16380aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	chain_obj = nft_chain_list_iter_next(iter);
16390aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	while (chain_obj != NULL) {
16400aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		const char *table =
16410aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			nft_chain_attr_get_str(chain_obj, NFT_CHAIN_ATTR_TABLE);
16420aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16430aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if (strcmp(this_table, table) != 0)
16440aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			goto next;
16450aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16460aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if (nft_chain_builtin(chain_obj))
16470aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			goto next;
16480aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16490aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if ( __nft_chain_del(h, chain_obj) < 0) {
16500aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			if (errno != EBUSY)
16510aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso				return -1;
16520aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		}
16530aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonext:
16540aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		chain_obj = nft_chain_list_iter_next(iter);
16550aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	}
16560aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	nft_chain_list_iter_destroy(iter);
16570aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16580aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	return 0;
16590aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso}
16600aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1661d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic int __nft_rule_del(struct nft_handle *h, struct nft_rule_list *list,
1662d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			  struct nft_rule *r)
1663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1666d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	nft_rule_list_del(r);
1667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1668d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	ret = rule_update_add(h, NFT_DO_DELETE, r);
1669d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (ret < 0) {
1670d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		nft_rule_free(r);
1671d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return -1;
1672d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	}
1673d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return 1;
1674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
167684909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longostruct nft_rule_list *nft_rule_list_create(struct nft_handle *h)
1677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1678b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	return nft_rule_list_get(h);
16793aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso}
16803aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
168184909d171585d77fe769f03e2b1b96eab0aa0213Giuseppe Longovoid nft_rule_list_destroy(struct nft_rule_list *list)
16823aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso{
16833aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_free(list);
16843aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso}
16853aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
16863aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic struct nft_rule *
1687e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayusonft_rule_find(struct nft_handle *h, struct nft_rule_list *list,
1688e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso	      const char *chain, const char *table, void *data, int rulenum)
16893aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso{
16903aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
16913aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list_iter *iter;
16923aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int rule_ctr = 0;
16933aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	bool found = false;
16943aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
1696b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
1700384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
1701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
1702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
1703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
1704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
1705384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1706384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
1707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0) {
1708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different chain / table\n");
1709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (rulenum >= 0) {
1713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Delete by rule number case */
17144acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			if (rule_ctr != rulenum)
1715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
17164acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			found = true;
17174acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			break;
1718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
1719e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso			found = h->ops->rule_find(h->ops, r, data);
1720e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso			if (found)
1721e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso				break;
1722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
17244acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka		rule_ctr++;
1725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
1726384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_iter_destroy(iter);
1729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
17303aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return found ? r : NULL;
1731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_check(struct nft_handle *h, const char *chain,
1734b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		   const char *table, void *data, bool verbose)
1735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
17363aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
17373aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret;
17383aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_check;
1740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
17413aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
1742b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
17433aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
17443aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1745b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso	ret = nft_rule_find(h, list, chain, table, data, -1) ? 1 : 0;
17463aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (ret == 0)
17473aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
17483aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
17493aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
17503aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
17513aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
1752384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1753384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1754384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete(struct nft_handle *h, const char *chain,
1755b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		    const char *table, void *data, bool verbose)
1756384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
17573aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
17583aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
17593aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
17603aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1761384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete;
1762384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
17633aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
1764b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
17653aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
17663aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1767b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso	r = nft_rule_find(h, list, chain, table, data, -1);
17683aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
1769d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		ret =__nft_rule_del(h, list, r);
1770d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		if (ret < 0)
1771d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			errno = ENOMEM;
17723aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
17733aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
17743aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
17753aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
17763aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
17773aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
1778384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1779384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1780cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusostatic int
1781cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusonft_rule_add(struct nft_handle *h, const char *chain,
1782cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	     const char *table, struct iptables_command_state *cs,
1783cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	     uint64_t handle, bool verbose)
1784cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso{
1785cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	struct nft_rule *r;
1786cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1787cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	r = nft_rule_new(h, chain, table, cs);
1788d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (r == NULL)
1789d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return 0;
1790d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
179166a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso	if (handle > 0)
179266a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		nft_rule_attr_set_u64(r, NFT_RULE_ATTR_POSITION, handle);
1793cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1794d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (rule_update_add(h, NFT_DO_INSERT, r) < 0) {
1795d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		nft_rule_free(r);
1796d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		return 0;
1797cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	}
1798cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1799d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return 1;
1800cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso}
1801cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1802cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusoint nft_rule_insert(struct nft_handle *h, const char *chain,
1803b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		    const char *table, void *data, int rulenum, bool verbose)
1804cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso{
1805cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	struct nft_rule_list *list;
1806cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	struct nft_rule *r;
180766a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso	uint64_t handle = 0;
1808cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1809cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
1810cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
1811cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso		nft_chain_builtin_init(h, table, chain, NF_ACCEPT);
1812cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1813cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	nft_fn = nft_rule_insert;
1814cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
181566a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso	if (rulenum > 0) {
181666a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		list = nft_rule_list_create(h);
181766a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		if (list == NULL)
181866a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso			goto err;
1819cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1820b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		r = nft_rule_find(h, list, chain, table, data, rulenum);
182166a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		if (r == NULL) {
182266a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso			errno = ENOENT;
182366a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso			goto err;
182466a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		}
1825cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
182666a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		handle = nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE);
182766a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		DEBUGP("adding after rule handle %"PRIu64"\n", handle);
1828cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
182966a5399b6a4383ea4081d99ae852eebc1d65f265Pablo Neira Ayuso		nft_rule_list_destroy(list);
1830cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	}
1831cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1832b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso	return nft_rule_add(h, chain, table, data, handle, verbose);
1833cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayusoerr:
1834cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	nft_rule_list_destroy(list);
1835cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso	return 0;
1836cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso}
1837cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso
1838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete_num(struct nft_handle *h, const char *chain,
18393aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso			const char *table, int rulenum, bool verbose)
1840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
18413aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
18423aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
18433aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
18443aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1845384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete_num;
1846384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
18473aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
1848b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
18493aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
18503aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1851e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso	r = nft_rule_find(h, list, chain, table, NULL, rulenum);
18523aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
18533aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		ret = 1;
18543aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
18553aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("deleting rule by number %d\n", rulenum);
1856d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		ret = __nft_rule_del(h, list, r);
1857d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		if (ret < 0)
1858d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			errno = ENOMEM;
18593aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
18603aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
18613aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
18623aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
18633aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
18643aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
1865384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1866384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1867384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_replace(struct nft_handle *h, const char *chain,
1868b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		     const char *table, void *data, int rulenum, bool verbose)
1869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
18703aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
18713aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
18723aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
1873384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_replace;
1875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
18763aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
1877b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
18783aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
18793aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1880b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso	r = nft_rule_find(h, list, chain, table, data, rulenum);
18813aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
18821298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso		DEBUGP("replacing rule with handle=%llu\n",
18831298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso			(unsigned long long)
18841298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso			nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE));
1885384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1886b756cf08d6eff885d808504c674bd7eb5ebabfbbPablo Neira Ayuso		ret = nft_rule_append(h, chain, table, data,
1887cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso				      nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE),
1888cf95f347e52ca8badc6a7149045d9c09f4fa666dPablo Neira Ayuso				      verbose);
18893aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
18903aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
18913aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
18923aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
18933aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
18943aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
1895384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1896384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1897384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1898384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_header(unsigned int format, const char *chain, const char *pol,
1899384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	     const struct xt_counters *counters, bool basechain, uint32_t refs)
1900384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1901384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("Chain %s", chain);
1902384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (basechain) {
1903384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(" (policy %s", pol);
1904384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (!(format & FMT_NOCOUNTS)) {
1905384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputc(' ', stdout);
190636cba824e1689c6255d4e33b7fa82541a774609bPablo Neira Ayuso			xtables_print_num(counters->pcnt, (format|FMT_NOTABLE));
1907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("packets, ", stdout);
190836cba824e1689c6255d4e33b7fa82541a774609bPablo Neira Ayuso			xtables_print_num(counters->bcnt, (format|FMT_NOTABLE));
1909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("bytes", stdout);
1910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(")\n");
1912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else {
1913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(" (%u references)\n", refs);
1914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_LINENUMBERS)
1917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-4s ", "%s "), "num");
1918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOCOUNTS)) {
1919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (format & FMT_KILOMEGAGIGA) {
1920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5s ","%s "), "pkts");
1921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5s ","%s "), "bytes");
1922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
1923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%8s ","%s "), "pkts");
1924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%10s ","%s "), "bytes");
1925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOTARGET))
1928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-9s ","%s "), "target");
1929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	fputs(" prot ", stdout);
1930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_OPTIONS)
1931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputs("opt", stdout);
1932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_VIA) {
1933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT(" %-6s ","%s "), "in");
1934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-6s ","%s "), "out");
1935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(FMT(" %-19s ","%s "), "source");
1937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(FMT(" %-19s "," %s "), "destination");
1938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("\n");
1939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
1942b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka__nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
1943384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int rulenum, unsigned int format,
19448aa384a7d54734fd830840a2593cd4f07749976fTomasz Bursztyka		void (*cb)(struct nft_rule *r, unsigned int num,
1945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			   unsigned int format))
1946384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
1948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list_iter *iter;
1949384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1950384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int rule_ctr = 0, ret = 0;
1951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
1953b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
1957b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1958b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
1959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
1961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
1962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
1963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
1964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
1965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
1966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		rule_ctr++;
1968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
1970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0)
1971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
19730b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		if (rulenum > 0 && rule_ctr != rulenum) {
1974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* List by rule number case */
19750b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			goto next;
19760b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		}
1977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
19788aa384a7d54734fd830840a2593cd4f07749976fTomasz Bursztyka		cb(r, rule_ctr, format);
19790b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		if (rulenum > 0 && rule_ctr == rulenum) {
19800b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			ret = 1;
19810b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			break;
1982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
19830b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo
1984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1985384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
1986384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1987384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1988384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_iter_destroy(iter);
1989b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
1990384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_free(list);
1991384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1992384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == 0)
1993384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
1994384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1996384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1997384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1998384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
1999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  int rulenum, unsigned int format)
2000384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2001e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka	const struct nft_family_ops *ops;
2002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
2003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
20050a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo	bool found = false;
2006384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2007aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka	/* If built-in chains don't exist for this table, create them */
2008aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
2009aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka		nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
2010aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka
2011e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka	ops = nft_family_ops_lookup(h->family);
2012e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka
2013b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka	if (chain && rulenum) {
2014b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka		__nft_rule_list(h, chain, table,
2015e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka				rulenum, format, ops->print_firewall);
2016b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka		return 1;
2017b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka	}
2018b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka
2019384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
2020384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2021384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2022b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2023b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2024384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2027384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2028384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2029384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2030384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2031384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
2032384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
2033384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t refs =
2034384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_USE);
2035384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct xt_counters ctrs = {
2036384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			.pcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS),
2037384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			.bcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES),
2038384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		};
2039384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
2040384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2041384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM))
2042384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			basechain = true;
2043384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2044384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2045384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2046384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
2047384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2048384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
20490a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		if (found)
20500a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo			printf("\n");
20510a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
20527a1026f59c101a67233c65dd5ef9b0ae15945ca5Tomasz Bursztyka		print_header(format, chain_name, policy_name[policy],
20530b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo				     &ctrs, basechain, refs);
20547a1026f59c101a67233c65dd5ef9b0ae15945ca5Tomasz Bursztyka
2055b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka		__nft_rule_list(h, chain_name, table,
2056e23e66f9d1a25c75df684850b7cd99053708c4d0Tomasz Bursztyka				rulenum, format, ops->print_firewall);
20570a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
2058da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso		/* we printed the chain we wanted, stop processing. */
2059da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso		if (chain)
2060da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso			break;
2061da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso
20620a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		found = true;
20630a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
2064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
206834c59adfae98515468ec50c644c30115fee0b97eGiuseppe Longo	nft_chain_list_iter_destroy(iter);
2069b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
2070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
2071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
20768aa384a7d54734fd830840a2593cd4f07749976fTomasz Bursztykalist_save(struct nft_rule *r, unsigned int num, unsigned int format)
2077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2078cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka	struct iptables_command_state cs = {};
2079cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka
2080cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka	nft_rule_to_iptables_command_state(r, &cs);
2081cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka
2082cdc78b1d6bd7b48ec05d78fc6e6cd98473f40357Tomasz Bursztyka	nft_rule_print_save(&cs, r, NFT_RULE_APPEND, !(format & FMT_NOCOUNTS));
2083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
20868dd2627afc462a2591c2f621743cae1a6b98d771Pablo Neira Ayusonft_rule_list_chain_save(struct nft_handle *h, const char *chain,
20878dd2627afc462a2591c2f621743cae1a6b98d771Pablo Neira Ayuso			 const char *table, struct nft_chain_list *list,
20888dd2627afc462a2591c2f621743cae1a6b98d771Pablo Neira Ayuso			 int counters)
2089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2091384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
2092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2094b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2095384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2096384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2097384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2101384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2103384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
2104384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
2105384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
21068dd2627afc462a2591c2f621743cae1a6b98d771Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0 ||
21078dd2627afc462a2591c2f621743cae1a6b98d771Pablo Neira Ayuso		    (chain && strcmp(chain, chain_name) != 0))
2108384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* this is a base chain */
21117244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka		if (nft_chain_builtin(c)) {
2112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-P %s %s", chain_name, policy_name[policy]);
2113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2114384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (counters) {
21150a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo				printf(" -c %"PRIu64" %"PRIu64"\n",
2116384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS),
2117384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES));
2118384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			} else
2119384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				printf("\n");
2120384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2121384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-N %s\n", chain_name);
2122384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2124384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2125384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2126384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2127e9a0ef8f1e27f5ef13a27f6cc984e8f2e05afd72Tomasz Bursztyka	nft_chain_list_iter_destroy(iter);
2128e9a0ef8f1e27f5ef13a27f6cc984e8f2e05afd72Tomasz Bursztyka
2129384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2130384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2131384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2132384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list_save(struct nft_handle *h, const char *chain,
2133384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       const char *table, int rulenum, int counters)
2134384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2135384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
2136384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2137384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
213810f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso	int ret = 1;
2139384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
2141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Dump policies and custom chains first */
214310f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso	if (!rulenum)
21448dd2627afc462a2591c2f621743cae1a6b98d771Pablo Neira Ayuso		nft_rule_list_chain_save(h, chain, table, list, counters);
2145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2146384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Now dump out rules in this table */
2147384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2148b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2149b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2150384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2155384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2160384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
2161384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2163b08836a33bac28860400e1e34c8244249f651a6fTomasz Bursztyka		ret = __nft_rule_list(h, chain_name, table, rulenum,
216410f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso				      counters ? 0 : FMT_NOCOUNTS, list_save);
2165da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso
2166da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso		/* we printed the chain we wanted, stop processing. */
2167da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso		if (chain)
2168da07c930b9e2aaf8df24022a175b1774aa0bdd8bPablo Neira Ayuso			break;
2169384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2170384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2172e9a0ef8f1e27f5ef13a27f6cc984e8f2e05afd72Tomasz Bursztyka
2173e9a0ef8f1e27f5ef13a27f6cc984e8f2e05afd72Tomasz Bursztyka	nft_chain_list_iter_destroy(iter);
2174b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
2175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
2176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
217710f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso	return ret;
2178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2180a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztykaint nft_rule_zero_counters(struct nft_handle *h, const char *chain,
2181a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka			   const char *table, int rulenum)
2182a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka{
2183a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	struct iptables_command_state cs = {};
2184a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	struct nft_rule_list *list;
2185a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	struct nft_rule *r;
2186a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	int ret = 0;
2187a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2188a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	nft_fn = nft_rule_delete;
2189a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2190a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	list = nft_rule_list_create(h);
2191a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	if (list == NULL)
2192a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka		return 0;
2193a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2194e2a2c72277b49ac611809b3978365ab3010e1597Pablo Neira Ayuso	r = nft_rule_find(h, list, chain, table, NULL, rulenum);
2195a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	if (r == NULL) {
2196a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka		errno = ENOENT;
2197a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka		ret = 1;
2198a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka		goto error;
2199a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	}
2200a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2201a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	nft_rule_to_iptables_command_state(r, &cs);
2202a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2203a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	cs.counters.pcnt = cs.counters.bcnt = 0;
2204a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2205a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	ret =  nft_rule_append(h, chain, table, &cs,
2206a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka			       nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE),
2207a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka			       false);
2208a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2209a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztykaerror:
2210a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	nft_rule_list_destroy(list);
2211a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2212a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka	return ret;
2213a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka}
2214a69cc575295eedb44f0fa33cd5fcf1cc0114133aTomasz Bursztyka
2215d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayusostatic int nft_action(struct nft_handle *h, int action)
22169e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
2217d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	int flags = NLM_F_CREATE, type;
2218d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	struct rule_update *n, *tmp;
22199e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	struct nlmsghdr *nlh;
2220d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	uint32_t seq = 1;
22219e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	int ret;
22229e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
2223d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	mnl_nft_batch_begin(h->batch, seq++);
22249e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
2225d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	list_for_each_entry_safe(n, tmp, &h->rule_list, head) {
2226d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		switch (n->type) {
2227d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		case NFT_DO_APPEND:
2228d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			type = NFT_MSG_NEWRULE;
2229d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			flags |= NLM_F_APPEND;
2230d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			break;
2231d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		case NFT_DO_INSERT:
2232d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			type = NFT_MSG_NEWRULE;
2233d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			break;
2234d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		case NFT_DO_REPLACE:
2235d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			type = NFT_MSG_NEWRULE;
2236d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			flags |= NLM_F_REPLACE;
2237d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			break;
2238d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		case NFT_DO_DELETE:
2239d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		case NFT_DO_FLUSH:
2240d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			type = NFT_MSG_DELRULE;
2241d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			break;
2242d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		default:
2243d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			return 0;
2244d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		}
22459e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
2246d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(h->batch),
2247d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso					       type, h->family, flags, seq++);
2248d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		nft_rule_nlmsg_build_payload(nlh, n->rule);
2249d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		nft_rule_print_debug(n->rule, nlh);
2250d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2251d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		h->rule_list_num--;
2252d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		list_del(&n->head);
2253d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		nft_rule_free(n->rule);
2254d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		free(n);
2255d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2256d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		if (!mnl_nlmsg_batch_next(h->batch))
2257d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso			h->batch = mnl_nft_batch_page_add(h->batch);
2258d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	}
2259d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2260d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	switch (action) {
2261d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	case NFT_DO_COMMIT:
2262d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		mnl_nft_batch_end(h->batch, seq++);
2263d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		break;
2264d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	case NFT_DO_ABORT:
2265d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		break;
22669e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	}
2267d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2268d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (!mnl_nlmsg_batch_is_empty(h->batch))
2269d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		h->batch = mnl_nft_batch_page_add(h->batch);
2270d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2271d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	ret = mnl_nft_batch_talk(h);
2272d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	if (ret < 0)
2273d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso		perror("mnl_nft_batch_talk:");
2274d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2275d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	mnl_nlmsg_batch_reset(h->batch);
2276d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso
2277f041efe3c26e3059df1ac8f1775f77423d4be5f6Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
22789e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
22799e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
22809e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_commit(struct nft_handle *h)
22819e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
2282d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return nft_action(h, NFT_DO_COMMIT);
22839e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
22849e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
22859e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_abort(struct nft_handle *h)
22869e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
2287d6a127cd5710f8c60e95bfd0378ca352c07140a9Pablo Neira Ayuso	return nft_action(h, NFT_DO_ABORT);
22889e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
22899e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
2290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_compatible_revision(const char *name, uint8_t rev, int opt)
2291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct mnl_socket *nl;
2293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
2294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
2295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t portid, seq, type;
2296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
2297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
229885512f09680a798ebe92e96ad62eeae863fbc791Pablo Neira Ayuso	if (opt == IPT_SO_GET_REVISION_MATCH ||
229985512f09680a798ebe92e96ad62eeae863fbc791Pablo Neira Ayuso	    opt == IP6T_SO_GET_REVISION_MATCH)
2300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 0;
2301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
2302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 1;
2303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = mnl_nlmsg_put_header(buf);
2305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_type = (NFNL_SUBSYS_NFT_COMPAT << 8) | NFNL_MSG_COMPAT_GET;
2306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
2307384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_seq = seq = time(NULL);
2308384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
2310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->nfgen_family = AF_INET;
2311384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->version = NFNETLINK_V0;
2312384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->res_id = 0;
2313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_strz(nlh, NFTA_COMPAT_NAME, name);
2315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_REV, htonl(rev));
2316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_TYPE, htonl(type));
2317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	DEBUGP("requesting `%s' rev=%d type=%d via nft_compat\n",
2319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		name, rev, type);
2320384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nl = mnl_socket_open(NETLINK_NETFILTER);
2322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nl == NULL) {
2323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_open");
2324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2325384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
2328384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_bind");
2329384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	portid = mnl_socket_get_portid(nl);
2332384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2333384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
2334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_send");
2335384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2336384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2337384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
2339384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
2340384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_recvfrom");
2341384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2342384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2343384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2344384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
2345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
2346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_cb_run");
2347384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2350384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
2351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(nl);
2352384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret < 0 ? 0 : 1;
2354384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2355384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/* Translates errno numbers into more human-readable form than strerror. */
2357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoconst char *nft_strerror(int err)
2358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
2360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	static struct table_struct {
2361384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		void *fn;
2362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int err;
2363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *message;
2364384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} table[] =
2365384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  {
2366384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, ENOTEMPTY, "Chain is not empty" },
2367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EINVAL, "Can't delete built-in chain" },
2368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EMLINK,
2369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Can't delete chain with references left" },
2370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_add, EEXIST, "Chain already exists" },
2371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, E2BIG, "Index of insertion too big" },
2372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_replace, E2BIG, "Index of replacement too big" },
2373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete_num, E2BIG, "Index of deletion too big" },
2374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/*	    { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
2375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, */
2376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, ELOOP, "Loop found in table" },
2377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, EINVAL, "Target problem" },
2378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    /* ENOENT for DELETE probably means no matching rule */
2379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete, ENOENT,
2380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Bad rule (does a matching rule exist in that chain?)" },
2381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, ENOENT, "Bad built-in chain name" },
2382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, EINVAL, "Bad policy name" },
2383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, EPERM, "Permission denied (you must be root)" },
2384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, 0, "Incompatible with this kernel" },
2385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
2386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOSYS, "Will be implemented real soon.  I promise ;)" },
2387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOMEM, "Memory allocation problem" },
2388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOENT, "No chain/target/match by that name" },
2389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  };
2390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
2392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if ((!table[i].fn || table[i].fn == nft_fn)
2393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    && table[i].err == err)
2394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return table[i].message;
2395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return strerror(err);
2398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
23998b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
24008b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayusostatic void xtables_config_perror(uint32_t flags, const char *fmt, ...)
24018b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso{
24028b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_list args;
24038b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
24048b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_start(args, fmt);
24058b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
24068b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (flags & NFT_LOAD_VERBOSE)
24078b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		vfprintf(stderr, fmt, args);
24088b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
24098b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_end(args);
24108b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso}
24118b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
24128b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayusoint nft_xtables_config_load(struct nft_handle *h, const char *filename,
24138b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			    uint32_t flags)
24148b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso{
24158b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_table_list *table_list = nft_table_list_alloc();
24168b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_chain_list *chain_list = nft_chain_list_alloc();
24176a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey	struct nft_table_list_iter *titer = NULL;
24186a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey	struct nft_chain_list_iter *citer = NULL;
24198b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_table *table;
24208b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_chain *chain;
2421cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo	uint32_t table_family, chain_family;
2422cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo	bool found = false;
24238b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
2424e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka	if (h->restore)
2425e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka		return 0;
2426e6b8e172fca48f5d80699afe80947b0fc1f23fd6Tomasz Bursztyka
24278b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (xtables_config_parse(filename, table_list, chain_list) < 0) {
24288b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		if (errno == ENOENT) {
24298b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			xtables_config_perror(flags,
24308b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				"configuration file `%s' does not exists\n",
24318b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				filename);
24328b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		} else {
24338b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			xtables_config_perror(flags,
24348b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				"Fatal error parsing config file: %s\n",
24358b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				 strerror(errno));
24368b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
24376a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey		goto err;
24388b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
24398b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
24408b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	/* Stage 1) create tables */
24418b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	titer = nft_table_list_iter_create(table_list);
24428b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	while ((table = nft_table_list_iter_next(titer)) != NULL) {
2443cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo		table_family = nft_table_attr_get_u32(table,
2444cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo						      NFT_TABLE_ATTR_FAMILY);
2445cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo		if (h->family != table_family)
2446cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo			continue;
2447cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo
2448cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo		found = true;
2449cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo
24508b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		if (nft_table_add(h, table) < 0) {
24518b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			if (errno == EEXIST) {
24528b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
24538b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"table `%s' already exists, skipping\n",
24548b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_table_attr_get(table, NFT_TABLE_ATTR_NAME));
24558b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			} else {
24568b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
24578b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"table `%s' cannot be create, reason `%s'. Exitting\n",
24588b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_table_attr_get(table, NFT_TABLE_ATTR_NAME),
24598b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					strerror(errno));
24606a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey				goto err;
24618b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			}
24628b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			continue;
24638b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
24648b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		xtables_config_perror(flags, "table `%s' has been created\n",
24658b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			(char *)nft_table_attr_get(table, NFT_TABLE_ATTR_NAME));
24668b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
24672c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_table_list_iter_destroy(titer);
24682c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_table_list_free(table_list);
24698b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
2470cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo	if (!found)
24716a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey		goto err;
2472cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo
24738b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	/* Stage 2) create chains */
24748b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	citer = nft_chain_list_iter_create(chain_list);
24758b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	while ((chain = nft_chain_list_iter_next(citer)) != NULL) {
2476cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo		chain_family = nft_chain_attr_get_u32(chain,
2477cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo						      NFT_CHAIN_ATTR_TABLE);
2478cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo		if (h->family != chain_family)
2479cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo			continue;
2480cea310bd1d078618e87b83410f8c6f75b34de450Giuseppe Longo
24818b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		if (nft_chain_add(h, chain) < 0) {
24828b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			if (errno == EEXIST) {
24838b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
24848b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"chain `%s' already exists in table `%s', skipping\n",
24858b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_NAME),
24868b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_TABLE));
24878b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			} else {
24888b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
24898b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"chain `%s' cannot be create, reason `%s'. Exitting\n",
24908b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_NAME),
24918b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					strerror(errno));
24926a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey				goto err;
24938b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			}
24948b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			continue;
24958b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
24968b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
24978b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		xtables_config_perror(flags,
24988b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			"chain `%s' in table `%s' has been created\n",
24998b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_NAME),
25008b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_TABLE));
25018b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
25022c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_chain_list_iter_destroy(citer);
25032c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_chain_list_free(chain_list);
25042c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso
25058b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	return 0;
25066a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey
25076a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Reyerr:
25086a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey	nft_table_list_free(table_list);
25096a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey	nft_chain_list_free(chain_list);
25106a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey
25116a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey	if (titer != NULL)
25126a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey		nft_table_list_iter_destroy(titer);
25136a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey	if (citer != NULL)
2514504119fe14bffde5800a631da89b80ed6043cecbPablo Neira Ayuso		nft_chain_list_iter_destroy(citer);
25156a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey
25166a4033b70dfdcc2df66f4ea51c901786a2b6131cAna Rey	return -1;
25178b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso}
2518b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2519b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longoint nft_chain_zero_counters(struct nft_handle *h, const char *chain,
2520b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			    const char *table)
2521b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo{
2522b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nft_chain_list *list;
2523b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nft_chain_list_iter *iter;
2524b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nft_chain *c;
2525b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nlmsghdr *nlh;
2526b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	char buf[MNL_SOCKET_BUFFER_SIZE];
2527b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	int ret = 0;
2528b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2529b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	list = nft_chain_list_get(h);
2530b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	if (list == NULL)
2531b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		goto err;
2532b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2533b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	iter = nft_chain_list_iter_create(list);
2534b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2535b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2536b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2537b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	c = nft_chain_list_iter_next(iter);
2538b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	while (c != NULL) {
2539b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		const char *chain_name =
2540b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			nft_chain_attr_get(c, NFT_CHAIN_ATTR_NAME);
2541b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		const char *chain_table =
2542b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			nft_chain_attr_get(c, NFT_CHAIN_ATTR_TABLE);
2543b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2544b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		if (strcmp(table, chain_table) != 0)
2545b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			goto next;
2546b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2547b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		if (chain != NULL && strcmp(chain, chain_name) != 0)
2548b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			goto next;
2549b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2550b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_PACKETS, 0);
2551b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES, 0);
2552b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2553b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_attr_unset(c, NFT_CHAIN_ATTR_HANDLE);
2554b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2555b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
2556b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo						h->family, NLM_F_ACK, h->seq);
2557b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2558b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_nlmsg_build_payload(nlh, c);
2559b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2560b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		ret = mnl_talk(h, nlh, NULL, NULL);
2561b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		if (ret < 0)
2562b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			perror("mnl_talk:nft_chain_zero_counters");
2563b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
256436ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
256536ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
2566b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longonext:
2567b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		c = nft_chain_list_iter_next(iter);
2568b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	}
2569b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2570b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	nft_chain_list_iter_destroy(iter);
2571b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2572b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longoerr:
2573b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	nft_chain_list_free(list);
2574b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2575b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	/* the core expects 1 for success and 0 for error */
2576b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	return ret == 0 ? 1 : 0;
2577b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo}
2578