nft.c revision 7244bef43f350ab31ef54db8a81905f6c68acac0
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>
41384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/table.h>
42384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/chain.h>
43384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/rule.h>
44384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/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
56384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
57384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    int (*cb)(const struct nlmsghdr *nlh, void *data),
58384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    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
83384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FILTER		0
84384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define MANGLE		1
85384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define RAW		2
86384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define SECURITY	3
87890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso#define NAT		4
88890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso#define TABLES_MAX	5
89384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
90e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusostruct builtin_chain {
91e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	const char *name;
92890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	const char *type;
935b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	uint32_t prio;
94e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	uint32_t hook;
95e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso};
96e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
97c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_table {
98384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
99e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	struct builtin_chain chains[NF_INET_NUMHOOKS];
100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} tables[TABLES_MAX] = {
101384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[RAW] = {
102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "raw",
103e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
104e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
105e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "PREROUTING",
106890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1075b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -300,	/* NF_IP_PRI_RAW */
108e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
109e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
110e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
111e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
112890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1135b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -300,	/* NF_IP_PRI_RAW */
114e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
115e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
116e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
117384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
118384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[MANGLE] = {
119384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "mangle",
120e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
121e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
122e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "PREROUTING",
123890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1245b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
125e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
126e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
127e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
128e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
129890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1305b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
131e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
132e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
133e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
134e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
135890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1365b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
137e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
138e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
139e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
140e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
141890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "route",
1425b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
143e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
144e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
145e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
146e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "POSTROUTING",
147890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1485b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
149e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_POST_ROUTING,
150e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
151e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[FILTER] = {
154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "filter",
155e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
156e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
157e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
158890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1595b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
160e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
161e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
162e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
163e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
164890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1655b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
166e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
167e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
168e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
169e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
170890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1715b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
172e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
173e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
174e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[SECURITY] = {
177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "security",
178e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
179e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
180e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
181890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1825b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
183e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
184e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
185e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
186e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
187890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1885b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
189e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
190e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
191e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
192e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
193890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1945b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
195e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
196e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
197384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		},
198384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
199890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	[NAT] = {
200890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		.name	= "nat",
201890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		.chains = {
202890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
203890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "OUTPUT",
204890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
205890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= -100, /* NF_IP_PRI_NAT_DST */
206890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
207890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
208890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
209890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "INPUT",
210890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
211890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= 100, /* NF_IP_PRI_NAT_SRC */
212890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
213890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
214890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
215890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "PREROUTING",
216890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
217890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= -100, /* NF_IP_PRI_NAT_DST */
218890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
219890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
220890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
221890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "POSTROUTING",
222890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
223890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= 100, /* NF_IP_PRI_NAT_SRC */
224890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_POST_ROUTING,
225890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
226890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		},
227890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	},
228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso};
229384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2305705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusostatic int
2315705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusonft_table_builtin_add(struct nft_handle *h, struct builtin_table *_t,
2325705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso			bool dormant)
2335b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso{
2345b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
2355b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	struct nlmsghdr *nlh;
2365b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	struct nft_table *t;
2375b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	int ret;
2385b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
2395b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	t = nft_table_alloc();
2405b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	if (t == NULL)
2415b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso		return -1;
2425b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
2435b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)_t->name);
2445705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (dormant) {
2455705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS,
2465705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso					NFT_TABLE_F_DORMANT);
2475705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	}
2485b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
2490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
2505b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
2515b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
2525b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_table_free(t);
2535b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
2545b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
2555b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	if (ret < 0) {
2565b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso		if (errno != EEXIST)
2575b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso			perror("mnl-talk:nft_table_init_one");
2585b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	}
2595b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	return ret;
2605b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso}
2615b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
262c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct nft_chain *
263c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_alloc(struct builtin_table *table,
264c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			struct builtin_chain *chain, int policy)
265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL)
270c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		return NULL;
271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table->name);
273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain->name);
274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_HOOKNUM, chain->hook);
2755b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_PRIO, chain->prio);
276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy);
277890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TYPE, (char *)chain->type);
278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
279c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return c;
280c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
281c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
282c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic void
283c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table,
284c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		      struct builtin_chain *chain, int policy)
285c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
286c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
287c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct nlmsghdr *nlh;
288c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct nft_chain *c;
289c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
290c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	c = nft_chain_builtin_alloc(table, chain, policy);
291c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (c == NULL)
292c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		return;
293c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
294890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	/* NLM_F_CREATE requests module autoloading */
2950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
296890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE,
297890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso					h->seq);
298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_talk(h, nlh, NULL, NULL) < 0) {
302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
303c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			perror("mnl_talk:nft_chain_builtin_add");
304c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
305c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
306c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
307c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in table already exists */
308c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_table *nft_table_builtin_find(const char *table)
309c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
310c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	int i;
311c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	bool found = false;
312c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
313c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	for (i=0; i<TABLES_MAX; i++) {
314c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		if (strcmp(tables[i].name, table) != 0)
315c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			continue;
316c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
317c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		found = true;
318c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		break;
319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
320c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
321c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return found ? &tables[i] : NULL;
322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
324c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in chain already exists */
325c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_chain *
326e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusonft_chain_builtin_find(struct builtin_table *t, const char *chain)
327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
328e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int i;
329c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	bool found = false;
330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
331e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	for (i=0; i<NF_IP_NUMHOOKS && t->chains[i].name != NULL; i++) {
332e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (strcmp(t->chains[i].name, chain) != 0)
333e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			continue;
334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
335e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		found = true;
336e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		break;
337e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	}
338e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	return found ? &t->chains[i] : NULL;
339e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso}
340e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
341e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusostatic void
342e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso__nft_chain_builtin_init(struct nft_handle *h,
343e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			 struct builtin_table *table, const char *chain,
344e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			 int policy)
345e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso{
346e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int i, default_policy;
347e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
348e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* Initialize all built-in chains. Exception, for e one received as
349e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	 * parameter, set the default policy as requested.
350e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	 */
351e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	for (i=0; i<NF_IP_NUMHOOKS && table->chains[i].name != NULL; i++) {
352e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (chain && strcmp(table->chains[i].name, chain) == 0)
353e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			default_policy = policy;
354e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		else
355e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			default_policy = NF_ACCEPT;
356e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
357e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		nft_chain_builtin_add(h, table, &table->chains[i],
358e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso					default_policy);
359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
360c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
361c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
362c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic int
363c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_init(struct nft_handle *h, const char *table,
364c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		       const char *chain, int policy)
365c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
366c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	int ret = 0;
367c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_table *t;
368c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
369c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	t = nft_table_builtin_find(table);
370c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (t == NULL) {
371c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		ret = -1;
372c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		goto out;
373c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
3745705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (nft_table_builtin_add(h, t, false) < 0) {
375e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		/* Built-in table already initialized, skip. */
376e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (errno == EEXIST)
377e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			goto out;
378c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
379e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	__nft_chain_builtin_init(h, t, chain, policy);
380c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusoout:
381c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return ret;
382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3847244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztykastatic bool nft_chain_builtin(struct nft_chain *c)
3857244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka{
3867244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka	/* Check if this chain has hook number, in that case is built-in.
3877244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka	 * Should we better export the flags to user-space via nf_tables?
3887244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka	 */
3897244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka	return nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM) != NULL;
3907244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka}
3917244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka
392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_init(struct nft_handle *h)
393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->nl = mnl_socket_open(NETLINK_NETFILTER);
395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (h->nl == NULL) {
396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_open");
397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_bind");
402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->portid = mnl_socket_get_portid(h->nl);
405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusovoid nft_fini(struct nft_handle *h)
410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(h->nl);
412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_table_add(struct nft_handle *h, const struct nft_table *t)
415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
4190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_add(struct nft_handle *h, const struct nft_chain *c)
427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
4310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
434384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
436384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
4385705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoint nft_table_set_dormant(struct nft_handle *h, const char *table)
4395705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso{
4405705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	int ret = 0, i;
4415705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct builtin_table *t;
4425705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4435705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	t = nft_table_builtin_find(table);
4445705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (t == NULL) {
4455705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		ret = -1;
4465705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		goto out;
4475705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	}
4485705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	/* Add this table as dormant */
4495705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (nft_table_builtin_add(h, t, true) < 0) {
4505705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		/* Built-in table already initialized, skip. */
4515705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		if (errno == EEXIST)
4525705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso			goto out;
4535705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	}
4545705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	for (i=0; t->chains[i].name != NULL && i<NF_INET_NUMHOOKS; i++)
4555705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		__nft_chain_builtin_init(h, t, t->chains[i].name, NF_ACCEPT);
4565705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoout:
4575705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	return ret;
4585705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso}
4595705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4605705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoint nft_table_wake_dormant(struct nft_handle *h, const char *table)
4615705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso{
4625705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
4635705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct nlmsghdr *nlh;
4645705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct nft_table *t;
4655705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4665705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	t = nft_table_alloc();
4675705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (t == NULL)
4685705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		return -1;
4695705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4705705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)table);
4715705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS, 0);
4725705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4730391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
4745705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso					NLM_F_ACK, h->seq);
4755705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
4765705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_free(t);
4775705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4785705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
4795705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso}
4805705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_debug(struct nft_chain *c, struct nlmsghdr *nlh)
482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_snprintf(tmp, sizeof(tmp), c, 0, 0);
487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("DEBUG: chain: %s", tmp);
488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_chain_set(struct nft_handle *h, const char *table,
494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain, int policy,
495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const struct xt_counters *counters)
496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
500c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_table *_t;
501c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_chain *_c;
502e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int ret;
503c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
504c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	_t = nft_table_builtin_find(table);
505c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	/* if this built-in table does not exists, create it */
506c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_t != NULL)
5075705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		nft_table_builtin_add(h, _t, false);
508c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
509e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	_c = nft_chain_builtin_find(_t, chain);
510c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_c != NULL) {
511c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		/* This is a built-in chain */
512c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		c = nft_chain_builtin_alloc(_t, _c, policy);
513c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		if (c == NULL)
514c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			return -1;
515c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	} else {
51620c156f9f4c43857a622f015a3022517601c3600Tomasz Bursztyka		errno = ENOENT;
51720c156f9f4c43857a622f015a3022517601c3600Tomasz Bursztyka		return -1;
518c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (counters) {
521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES,
522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->bcnt);
523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_PACKETS,
524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->pcnt);
525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
5270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_print_debug(c, nlh);
532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:__nft_chain_policy");
538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_set(struct nft_handle *h, const char *table,
543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const char *chain, const char *policy,
544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const struct xt_counters *counters)
545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = -1;
547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_chain_set;
549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(policy, "DROP") == 0)
551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_set(h, table, chain, NF_DROP, counters);
552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else if (strcmp(policy, "ACCEPT") == 0)
553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_set(h, table, chain, NF_ACCEPT, counters);
554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
559f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztykastatic int __add_match(struct nft_rule_expr *e, struct xt_entry_match *m)
560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	void *info;
562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_MT_NAME, m->u.user.name, strlen(m->u.user.name));
564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(e, NFT_EXPR_MT_REV, m->u.user.revision);
565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	info = calloc(1, m->u.match_size);
567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (info == NULL)
568f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(info, m->data, m->u.match_size);
571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_MT_INFO, info, m->u.match_size - sizeof(*m));
572f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
573f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
576f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztykastatic int add_match(struct nft_rule *r, struct xt_entry_match *m)
577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
579f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	int ret;
580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("match");
582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
583f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
585f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	ret = __add_match(expr, m);
586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
587f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
588f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return ret;
589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
591f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztykastatic int __add_target(struct nft_rule_expr *e, struct xt_entry_target *t)
592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	void *info = NULL;
594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_TG_NAME, t->u.user.name,
596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  strlen(t->u.user.name));
597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(e, NFT_EXPR_TG_REV, t->u.user.revision);
598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (info == NULL) {
600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		info = calloc(1, t->u.target_size);
601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (info == NULL)
602f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka			return -ENOMEM;
603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(info, t->data, t->u.target_size);
605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_TG_INFO, info, t->u.target_size - sizeof(*t));
608f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
609f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
612f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztykastatic int add_target(struct nft_rule *r, struct xt_entry_target *t)
613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
615f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	int ret;
616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("target");
618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
619f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
621f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	ret = __add_target(expr, t);
622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
623f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
624f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return ret;
625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
627f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztykastatic int add_jumpto(struct nft_rule *r, const char *name, int verdict)
628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("immediate");
632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
633f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT);
636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict);
637384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_str(expr, NFT_EXPR_IMM_CHAIN, (char *)name);
638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
639f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
640f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
643f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztykastatic int add_verdict(struct nft_rule *r, int verdict)
644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("immediate");
648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
649f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT);
652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict);
653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
654f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
655f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_rule_print_debug(struct nft_rule *r, struct nlmsghdr *nlh)
659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_snprintf(tmp, sizeof(tmp), r, 0, 0);
664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("DEBUG: rule: %s", tmp);
665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
669f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztykastatic int add_counters(struct nft_rule *r, uint64_t packets, uint64_t bytes)
670384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("counter");
674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
675f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		return -ENOMEM;
676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_BYTES, packets);
678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_PACKETS, bytes);
679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
681f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
682f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	return 0;
683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
6854ef77b6d1b52e1fe52a7fd48d38d9233f0961640Pablo Neira Ayusovoid add_compat(struct nft_rule *r, uint32_t proto, bool inv)
6862a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso{
6872a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso	nft_rule_attr_set_u32(r, NFT_RULE_ATTR_COMPAT_PROTO, proto);
6882a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso	nft_rule_attr_set_u32(r, NFT_RULE_ATTR_COMPAT_FLAGS,
6892a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso			      inv ? NFT_RULE_COMPAT_F_INV : 0);
6902a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso}
6912a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso
692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint
693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_add(struct nft_handle *h, const char *chain, const char *table,
6940a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	     struct iptables_command_state *cs,
6951298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso	     bool append, uint64_t handle, bool verbose)
696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
700384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 1;
702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int flags = append ? NLM_F_APPEND : 0;
7030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	int ip_flags = 0;
704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
705e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
7068b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
7078b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		nft_chain_builtin_init(h, table, chain, NF_ACCEPT);
708c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_add;
710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL) {
713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
717d370c4ad803c37eedfbee5963fac6f7e9968939cTomasz Bursztyka	nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FAMILY, h->family);
718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
721077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	ip_flags = h->ops->add(r, cs);
722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
723f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	for (matchp = cs->matches; matchp; matchp = matchp->next) {
724f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		if (add_match(r, matchp->match->m) < 0) {
725f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka			ret = 0;
726f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka			goto err;
727f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		}
728f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	}
729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Counters need to me added before the target, otherwise they are
731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 * increased for each rule because of the way nf_tables works.
732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 */
733f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	if (add_counters(r, cs->counters.pcnt, cs->counters.bcnt) < 0) {
734f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		ret = 0;
735f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		goto err;
736f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	}
737384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
738384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* If no target at all, add nothing (default to continue) */
739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (cs->target != NULL) {
740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* Standard target? */
741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
742f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka			ret = add_verdict(r, NF_ACCEPT);
743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
744f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka			ret = add_verdict(r, NF_DROP);
745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
746f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka			ret = add_verdict(r, NFT_RETURN);
747384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
748f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka			ret = add_target(r, cs->target->t);
749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else if (strlen(cs->jumpto) > 0) {
750384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* Not standard, then it's a go / jump to chain */
7510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (ip_flags & IPT_F_GOTO)
752f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka			ret = add_jumpto(r, cs->jumpto, NFT_GOTO);
753384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
754f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka			ret = add_jumpto(r, cs->jumpto, NFT_JUMP);
755f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	}
756f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka
757f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka	if (ret < 0) {
758f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		ret = 0;
759f6b30db46e5e3d32c76b186361853b5a5ecaf99fTomasz Bursztyka		goto err;
760384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
761384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
762384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* NLM_F_CREATE autoloads the built-in table if it does not exists */
7630a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	flags |= NLM_F_ACK|NLM_F_CREATE;
7640a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka
7650a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	if (handle > 0) {
7660a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka		nft_rule_attr_set(r, NFT_RULE_ATTR_HANDLE, &handle);
7670a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka		flags |= NLM_F_REPLACE;
7680a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	}
7690a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka
7709e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	if (h->commit) {
7719e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
7729e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso				      NFT_RULE_F_COMMIT);
7739e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	}
7740a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE,
7750391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				       h->family, flags, h->seq);
7760a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka
777384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
778384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
779384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_print_debug(r, nlh);
780384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
781384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
783384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
784384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
785384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_add");
786384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
787384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
788384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
789384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
790384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
791384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
792384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_match_save(struct nft_rule_expr *expr)
793384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
794384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
795384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_match *match;
796384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_match *emu;
797384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *mtinfo;
798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
800384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
802384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	match = xtables_find_match(name, XTF_TRY_LOAD, NULL);
803384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match == NULL)
804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mtinfo = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len);
807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mtinfo == NULL)
808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
810384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	emu = calloc(1, sizeof(struct xt_entry_match) + len);
811384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (emu == NULL)
812384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
813384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
814384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(&emu->data, mtinfo, len);
815384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
816384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match->alias)
817384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-m %s", match->alias(emu));
818384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
819384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-m %s", match->name);
820384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
821384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* FIXME missing parameter */
822c51b85f995caebd41e6d063c8bcab513b305bcaaPablo Neira Ayuso	if (match->save)
823c51b85f995caebd41e6d063c8bcab513b305bcaaPablo Neira Ayuso		match->save(NULL, emu);
824384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
825384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(" ");
826384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
827384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(emu);
828384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
829384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
830384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_target_save(struct nft_rule_expr *expr)
831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
832384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
833384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_target *target;
834384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_target *emu;
835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *tginfo;
836384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
837384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
839384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Standard target not supported, we use native immediate expression */
841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "") == 0) {
842384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("ERROR: standard target seen, should not happen\n");
843384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
844384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
845384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
846384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	target = xtables_find_target(name, XTF_TRY_LOAD);
847384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target == NULL)
848384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
849384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
850384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	tginfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len);
851384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (tginfo == NULL)
852384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
853384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
854384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	emu = calloc(1, sizeof(struct xt_entry_match) + len);
855384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (emu == NULL)
856384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
857384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
858384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(emu->data, tginfo, len);
859384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
860384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target->alias)
861384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s", target->alias(emu));
862384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
863384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s", target->name);
864384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
865384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* FIXME missing parameter */
866c51b85f995caebd41e6d063c8bcab513b305bcaaPablo Neira Ayuso	if (target->save)
867c51b85f995caebd41e6d063c8bcab513b305bcaaPablo Neira Ayuso		target->save(NULL, emu);
868384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(emu);
870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
871384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
872384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_immediate_save(struct nft_rule_expr *expr)
873384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t verdict;
875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
876384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
877384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
878384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(verdict) {
879384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_ACCEPT:
880384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j ACCEPT");
881384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
882384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_DROP:
883384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j DROP");
884384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
885384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_RETURN:
886384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j RETURN");
887384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
888384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_GOTO:
889384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-g %s",
890384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN));
891384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
892384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_JUMP:
893384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s",
894384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN));
895384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
896384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
897384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
898384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
899384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
900384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_print_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
901384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
902384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
903384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t value;
904384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
905384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char ifname[IFNAMSIZ];
906384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *ifname_ptr;
907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
908384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (e == NULL)
911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* meta should be followed by cmp */
915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "cmp") != 0) {
916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("skipping no cmp after meta\n");
917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(key) {
921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIF:
922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if_indextoname(value, ifname);
924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-i %s ", ifname);
928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -i %s ", ifname);
931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIF:
935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if_indextoname(value, ifname);
937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-o %s ", ifname);
941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
942384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
943384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -o %s ", ifname);
944384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
946384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIFNAME:
948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
949384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(ifname, ifname_ptr, len);
950384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname[len] = '\0';
951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* if this is zero, then assume this is a interface mask */
953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (if_nametoindex(ifname) == 0) {
954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len] = '+';
955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len+1] = '\0';
956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-i %s ", ifname);
961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -i %s ", ifname);
964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIFNAME:
968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(ifname, ifname_ptr, len);
970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname[len] = '\0';
971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* if this is zero, then assume this is a interface mask */
973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (if_nametoindex(ifname) == 0) {
974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len] = '+';
975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len+1] = '\0';
976384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
978384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
979384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
980384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-o %s ", ifname);
981384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -o %s ", ifname);
984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
985384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
986384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
987384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	default:
988384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("unknown meta key %d\n", key);
989384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
990384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
991384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
992384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
993384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
994384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_print_counters(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   bool counters)
996384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
997384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (counters) {
9980a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		printf("-c %"PRIu64" %"PRIu64" ",
999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS),
1000384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES));
1001384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
10041ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayusovoid
10051ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayusonft_rule_print_save(struct nft_rule *r, enum nft_rule_print type, bool counters)
1006384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1007384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1008384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
10091ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	const char *chain = nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
1010384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1011384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
10121ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	switch(type) {
10131ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	case NFT_RULE_APPEND:
10141ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		printf("-A %s ", chain);
10151ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		break;
10161ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	case NFT_RULE_DEL:
10171ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		printf("-D %s ", chain);
10181ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		break;
10191ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	}
1020384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1021384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1022384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL)
1023384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1024384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1027384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1028384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1029384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1030384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "counter") == 0) {
1031384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_print_counters(expr, iter, counters);
1032384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "payload") == 0) {
1033077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka			struct nft_family_ops *ops = nft_family_ops_lookup(
1034077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka				nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY));
1035077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka			ops->print_payload(expr, iter);
1036384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "meta") == 0) {
1037384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_print_meta(expr, iter);
1038384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "match") == 0) {
1039384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_match_save(expr);
1040384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "target") == 0) {
1041384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_target_save(expr);
1042384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
1043384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_immediate_save(expr);
1044384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1045384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1046384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1047384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1048384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1049384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("\n");
1050384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1051384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1052384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_chain_list_cb(const struct nlmsghdr *nlh, void *data)
1053384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list = data;
1056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1057384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
1058384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL) {
1059384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1060384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1061384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1062384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_chain_nlmsg_parse(nlh, c) < 0) {
1064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_add(c, list);
1069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
1073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_chain_list *nft_chain_list_get(struct nft_handle *h)
1078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1079384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1080384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1081384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1082384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_alloc();
1085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1086b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		errno = ENOMEM;
1087b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		return NULL;
1088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
10900391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
1091384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_chain_list_cb, list);
1094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1095384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_chain_list_get");
1096384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1097384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostruct nft_chain_list *nft_chain_dump(struct nft_handle *h)
1101384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return nft_chain_list_get(h);
1103384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1104384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1105384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic const char *policy_name[NF_ACCEPT+1] = {
1106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_DROP] = "DROP",
1107384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_ACCEPT] = "ACCEPT",
1108384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso};
1109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_save(struct nft_chain *c, bool basechain)
1111384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint64_t pkts = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS);
1114384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint64_t bytes = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES);
1115384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1116384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
1117384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (basechain) {
1118384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t pol = NF_ACCEPT;
1119384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1120384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* no default chain policy? don't crash, display accept */
1121384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_POLICY))
1122384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			pol = nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
1123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11240a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		printf(":%s %s [%"PRIu64":%"PRIu64"]\n", chain, policy_name[pol],
1125384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					     pkts, bytes);
1126384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else
11270a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		printf(":%s - [%"PRIu64":%"PRIu64"]\n", chain, pkts, bytes);
1128384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1129384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1130384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_save(struct nft_handle *h, struct nft_chain_list *list,
1131384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   const char *table)
1132384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1133384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1134384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1135384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1136384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1137b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1138384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1139384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
1143384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
1145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1146384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
1147384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1148384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11497244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka		basechain = nft_chain_builtin(c);
1150384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_print_save(c, basechain);
1151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1155d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_chain_list_iter_destroy(iter);
1156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1160384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1161384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_rule_list_cb(const struct nlmsghdr *nlh, void *data)
1162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1163384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1164384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list = data;
1165384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
1167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL) {
1168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1169384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1170384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_rule_nlmsg_parse(nlh, r) < 0) {
1173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_add(r, list);
1178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
1182137cc981906f356c971da6de13e777a419382ff4Giuseppe Longo	nft_rule_list_free(list);
1183384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1187384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_rule_list *nft_rule_list_get(struct nft_handle *h)
1188384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
1192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1194384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_alloc();
1195b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1196384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1197384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
1199384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1200384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_rule_list_cb, list);
1202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1203384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_save");
1204384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_rule_list_free(list);
1205384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return NULL;
1206384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1207384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1208384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1209384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1210384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_save(struct nft_handle *h, const char *table, bool counters)
1212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
1214384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list_iter *iter;
1215384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
1218b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1219384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1220384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
1222b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1225384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
1226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
1227384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
1228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
1229384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1230384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0)
1231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
12331ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		nft_rule_print_save(r, NFT_RULE_APPEND, counters);
1234384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1235384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1236384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
1237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1238384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1239d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_rule_list_iter_destroy(iter);
1240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_free(list);
1241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1245384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
1248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1251384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
1254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL)
1255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
1258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
1259384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
12609e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	if (h->commit) {
12619e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
12629e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso					 NFT_RULE_F_COMMIT);
12639e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	}
12649e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
1265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Delete all rules in this table + chain */
12660391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, h->family,
1267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
1269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
1270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_talk(h, nlh, NULL, NULL) < 0) {
1272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
1273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:__nft_rule_flush");
1274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
1278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1279384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_flush;
1285384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_get(h);
1287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
1289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1293b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1294b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
1295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1307384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1308384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		__nft_rule_flush(h, table_name, chain_name);
1310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
131136ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
131236ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
1313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1317d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_chain_list_iter_destroy(iter);
1318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1320384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1325384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table)
1326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1328384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1329384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1332e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
13338b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
13348b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
1335e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
1336384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
1337b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (c == NULL)
1338b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		return 0;
1339384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1340384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
1341384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain);
1342384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
13430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
1344384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
1345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
1346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
1347384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1350384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
1351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:nft_chain_add");
1352384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1354384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1355384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int __nft_chain_del(struct nft_handle *h, struct nft_chain *c)
1359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1361384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
13640391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, h->family,
1365384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1366384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
1367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST && errno != ENOENT)
1371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:__nft_chain_del");
1372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table)
1378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
1383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int deleted_ctr = 0;
1384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_get(h);
1386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1390b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1391b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
1392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* don't delete built-in chain */
1401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_builtin(c))
1402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_del(h, c);
1411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (ret < 0)
1412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		deleted_ctr++;
141536ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo
141636ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
141736ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
1418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1422d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_chain_list_iter_destroy(iter);
1423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* chain not found */
1427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0 && deleted_ctr == 0)
1428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
1429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14340aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusostruct nft_chain *
1435e127d223d01aaa0886c7f279110ac36651b9a057Tomasz Bursztykanft_chain_list_find(struct nft_chain_list *list,
14360aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		    const char *table, const char *chain)
14379c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso{
14389c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
14399c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	struct nft_chain *c;
14409c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14419c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1442b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
14439c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return NULL;
14449c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14459c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
14469c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	while (c != NULL) {
14479c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		const char *table_name =
14489c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
14499c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		const char *chain_name =
14509c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
14519c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14529c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
14539c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			goto next;
14549c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14559c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		if (strcmp(chain, chain_name) != 0)
14569c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			goto next;
14579c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14580aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		nft_chain_list_iter_destroy(iter);
14599c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return c;
14609c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayusonext:
14619c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
14629c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	}
14630aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	nft_chain_list_iter_destroy(iter);
14649c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	return NULL;
14659c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso}
14669c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14670aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusostatic struct nft_chain *
14680aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonft_chain_find(struct nft_handle *h, const char *table, const char *chain)
14690aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{
14700aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain_list *list;
14710aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
14720aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	list = nft_chain_list_get(h);
1473b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
14740aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		return NULL;
14750aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1476e127d223d01aaa0886c7f279110ac36651b9a057Tomasz Bursztyka	return nft_chain_list_find(list, table, chain);
14770aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso}
14780aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_rename(struct nft_handle *h,const char *chain,
1480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  const char *table, const char *newname)
1481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
14824493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	char buf[MNL_SOCKET_BUFFER_SIZE];
14834493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	struct nlmsghdr *nlh;
14844493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	struct nft_chain *c;
14859c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	uint64_t handle;
1486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14884493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	/* If built-in chains don't exist for this table, create them */
14898b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
14908b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
14914493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
14929c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	/* Find the old chain to be renamed */
14939c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	c = nft_chain_find(h, table, chain);
14949c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	if (c == NULL) {
14959c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		errno = ENOENT;
14969c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return -1;
14979c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	}
14989c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	handle = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_HANDLE);
14999c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
15009c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	/* Now prepare the new name for the chain */
15014493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	c = nft_chain_alloc();
1502b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (c == NULL)
15034493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka		return -1;
15044493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
15054493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
15069c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)newname);
15079c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_HANDLE, handle);
1508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
15090391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
15109c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
15114493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_nlmsg_build_payload(nlh, c);
15124493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_free(c);
15134493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
15144493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	ret = mnl_talk(h, nlh, NULL, NULL);
15154493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	if (ret < 0) {
15164493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka		if (errno != EEXIST)
15174493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka			perror("mnl_talk:nft_chain_rename");
15184493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	}
15194493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
15204493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	/* the core expects 1 for success and 0 for error */
15214493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	return ret == 0 ? 1 : 0;
1522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_table_list_cb(const struct nlmsghdr *nlh, void *data)
1525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list = data;
1528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_alloc();
1530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (t == NULL) {
1531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_table_nlmsg_parse(nlh, t) < 0) {
1536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_add(t, list);
1541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_free(t);
1545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_table_list *nft_table_list_get(struct nft_handle *h)
1550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_alloc();
1557b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
15600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
1561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_table_list_cb, list);
1564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_table_list_get");
1566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusobool nft_table_find(struct nft_handle *h, const char *tablename)
1571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list_iter *iter;
1574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool ret = false;
1576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_get(h);
1578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_table_list_iter_create(list);
1582b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_list_iter_next(iter);
1586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
1587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *this_tablename =
1588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_table_attr_get(t, NFT_TABLE_ATTR_NAME);
1589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(tablename, this_tablename) == 0)
1591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return true;
1592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		t = nft_table_list_iter_next(iter);
1594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_free(list);
1597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_for_each_table(struct nft_handle *h,
1603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       int (*func)(struct nft_handle *h, const char *tablename, bool counters),
1604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       bool counters)
1605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 1;
1607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list_iter *iter;
1609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_get(h);
1612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
1614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_table_list_iter_create(list);
1618b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_list_iter_next(iter);
1622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
1623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *tablename =
1624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_table_attr_get(t, NFT_TABLE_ATTR_NAME);
1625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		func(h, tablename, counters);
1627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		t = nft_table_list_iter_next(iter);
1629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_free(list);
1632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1637384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
16380aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusoint nft_table_purge_chains(struct nft_handle *h, const char *this_table,
16390aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			   struct nft_chain_list *chain_list)
16400aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{
16410aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain_list_iter *iter;
16420aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain *chain_obj;
16430aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16440aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	iter = nft_chain_list_iter_create(chain_list);
1645b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
16460aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		return 0;
16470aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16480aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	chain_obj = nft_chain_list_iter_next(iter);
16490aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	while (chain_obj != NULL) {
16500aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		const char *table =
16510aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			nft_chain_attr_get_str(chain_obj, NFT_CHAIN_ATTR_TABLE);
16520aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16530aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if (strcmp(this_table, table) != 0)
16540aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			goto next;
16550aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16560aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if (nft_chain_builtin(chain_obj))
16570aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			goto next;
16580aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16590aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if ( __nft_chain_del(h, chain_obj) < 0) {
16600aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			if (errno != EBUSY)
16610aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso				return -1;
16620aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		}
16630aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonext:
16640aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		chain_obj = nft_chain_list_iter_next(iter);
16650aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	}
16660aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	nft_chain_list_iter_destroy(iter);
16670aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16680aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	return 0;
16690aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso}
16700aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic inline int
1672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusomatch_different(const struct xt_entry_match *a,
1673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const unsigned char *a_elems,
1674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const unsigned char *b_elems,
1675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		unsigned char **maskptr)
1676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xt_entry_match *b;
1678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
1679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Offset of b is the same as a. */
1681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	b = (void *)b_elems + ((unsigned char *)a - a_elems);
1682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (a->u.match_size != b->u.match_size)
1684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 1;
1685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(a->u.user.name, b->u.user.name) != 0)
1687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 1;
1688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	*maskptr += XT_ALIGN(sizeof(*a));
1690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1691384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < a->u.match_size - XT_ALIGN(sizeof(*a)); i++)
1692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0)
1693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return 1;
1694384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	*maskptr += i;
1695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
1696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
17000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	       int family, struct iptables_command_state *cs)
1701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
1703077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	struct nft_family_ops *ops = nft_family_ops_lookup(family);
1704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
1705384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1706384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
1707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (e == NULL)
1708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
1711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "cmp") != 0) {
1712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("skipping no cmp after meta\n");
1713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1716077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	ops->parse_meta(e, key, cs);
17170391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
17180391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
17190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void
17200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_parse_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
17210391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		  int family, struct iptables_command_state *cs)
17220391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{
1723077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	struct nft_family_ops *ops = nft_family_ops_lookup(family);
17240391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint32_t offset;
17250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
17260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
17270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
1728077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	ops->parse_payload(iter, cs, offset);
17290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
17300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
17310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void
1732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_counter(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
1733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  struct xt_counters *counters)
1734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	counters->pcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS);
1736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	counters->bcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES);
1737384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1738384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_immediate(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
17410391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    int family, struct iptables_command_state *cs)
1742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int verdict = nft_rule_expr_get_u32(e, NFT_EXPR_IMM_VERDICT);
1744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_rule_expr_get_str(e, NFT_EXPR_IMM_CHAIN);
1745077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	struct nft_family_ops *ops;
1746384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1747384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Standard target? */
1748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(verdict) {
1749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_ACCEPT:
1750384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "ACCEPT";
1751384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1752384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_DROP:
1753384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "DROP";
1754384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1755384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_RETURN:
1756384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "RETURN";
1757384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1758384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_GOTO:
1759077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka		ops = nft_family_ops_lookup(family);
1760077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka		ops->parse_immediate(cs);
1761384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_JUMP:
1762384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = chain;
1763384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1764384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1766384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_to_iptables_command_state(struct nft_rule *r,
1769384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				   struct iptables_command_state *cs)
1770384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1771384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1772384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
17730391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	int family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
1774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1775384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1776384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL)
1777384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1778384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1779384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1780384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1781384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1783384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1784384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "counter") == 0) {
1785384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_parse_counter(expr, iter, &cs->counters);
1786384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "payload") == 0) {
17870391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			nft_parse_payload(expr, iter, family, cs);
1788384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "meta") == 0) {
17890391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			nft_parse_meta(expr, iter, family, cs);
1790384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
17910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			nft_parse_immediate(expr, iter, family, cs);
1792384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1793384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1794384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1795384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1796384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1797384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
1798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1800384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int matches_howmany(struct xtables_rule_match *matches)
1801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1802384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
1803384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int matches_ctr = 0;
1804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (matchp = matches; matchp; matchp = matchp->next)
1806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		matches_ctr++;
1807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return matches_ctr;
1809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1810384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1811384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
1812384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__find_match(struct nft_rule_expr *expr, struct xtables_rule_match *matches)
1813384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1814384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *matchname = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
1815384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Netlink aligns this match info, don't trust this length variable */
1816384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *data = nft_rule_expr_get_str(expr, NFT_EXPR_MT_INFO);
1817384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
1818384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool found = false;
1819384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1820384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (matchp = matches; matchp; matchp = matchp->next) {
1821384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct xt_entry_match *m = matchp->match->m;
1822384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1823384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(m->u.user.name, matchname) != 0) {
1824384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("mismatching match name\n");
1825384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			continue;
1826384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1827384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1828384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (memcmp(data, m->data, m->u.user.match_size - sizeof(*m)) != 0) {
1829384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("mismatch match data\n");
1830384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			continue;
1831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1832384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		found = true;
1833384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1834384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1836384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return found;
1837384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1839384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool find_matches(struct xtables_rule_match *matches, struct nft_rule *r)
1840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1842384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
1843384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int kernel_matches = 0;
1844384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1845384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1846b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1847384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1848384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1849384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1850384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1851384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1852384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1853384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1854384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "match") == 0) {
1855384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!__find_match(expr, matches))
1856384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
1857384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1858384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			kernel_matches++;
1859384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1860384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1861384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1862384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
1863384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1864384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* same number of matches? */
1865384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (matches_howmany(matches) != kernel_matches)
1866384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1867384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1868384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
1869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1871384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool __find_target(struct nft_rule_expr *expr, struct xt_entry_target *t)
1872384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1873384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
1874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *tgname = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
1875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Netlink aligns this target info, don't trust this length variable */
1876384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *data = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len);
1877384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1878384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(t->u.user.name, tgname) != 0) {
1879384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("mismatching target name\n");
1880384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1881384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1882384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1883384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (memcmp(data, t->data,  t->u.user.target_size - sizeof(*t)) != 0)
1884384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1885384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1886384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
1887384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1888384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1889384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int targets_howmany(struct xtables_target *target)
1890384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1891384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return target != NULL ? 1 : 0;
1892384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1893384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1894384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
1895384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusofind_target(struct xtables_target *target, struct nft_rule *r)
1896384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1897384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1898384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
1899384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int kernel_targets = 0;
1900384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1901384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Special case: we use native immediate expressions to emulated
1902384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 * standard targets. Also, we don't want to crash with no targets.
1903384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 */
1904384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target == NULL || strcmp(target->name, "standard") == 0)
1905384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return true;
1906384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1908b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "target") == 0) {
1917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* we may support several targets in the future */
1918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!__find_target(expr, target->t))
1919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
1920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			kernel_targets++;
1922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
1926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* same number of targets? */
1928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (targets_howmany(target) != kernel_targets) {
1929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("kernel targets is %d but we passed %d\n",
1930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		kernel_targets, targets_howmany(target));
1931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
1935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
1938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusofind_immediate(struct nft_rule *r, const char *jumpto)
1939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
1942384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1943384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1944b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1946384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1949384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1950384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "immediate") == 0) {
1953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			int verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
1954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			const char *verdict_name = NULL;
1955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* No target specified but immediate shows up, this
1957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 * is not the rule we are looking for.
1958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 */
1959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (strlen(jumpto) == 0)
1960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
1961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			switch(verdict) {
1963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_ACCEPT:
1964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "ACCEPT";
1965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
1966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_DROP:
1967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "DROP";
1968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
1969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_RETURN:
1970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "RETURN";
1971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
1972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
1973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Standard target? */
1975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (verdict_name && strcmp(jumpto, verdict_name) != 0)
1976384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
1977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1978384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1979384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1980384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
1981384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
1983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1985384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1986384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_del(struct nft_handle *h, struct nft_rule *r)
1987384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1988384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1989384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1990384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1991384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
19920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, h->family,
1993384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1994384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
1995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1996384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_print_debug(r, nlh);
1997384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1998384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
2000384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_del");
2001384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
20033aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic struct nft_rule_list *nft_rule_list_create(struct nft_handle *h)
2004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2005b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	return nft_rule_list_get(h);
20063aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso}
20073aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
20083aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic void nft_rule_list_destroy(struct nft_rule_list *list)
20093aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso{
20103aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_free(list);
20113aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso}
20123aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
20133aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic struct nft_rule *
20143aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusonft_rule_find(struct nft_rule_list *list, const char *chain, const char *table,
20153aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	      struct iptables_command_state *cs, int rulenum)
20163aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso{
20173aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
20183aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list_iter *iter;
20193aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int rule_ctr = 0;
20203aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	bool found = false;
20213aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2022384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
2023b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2024384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
2027384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
2028384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
2029384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
2030384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
2031384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
2032077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka		const struct nft_family_ops *ops = nft_family_ops_lookup(
2033077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka				nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY));
2034384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct iptables_command_state this = {};
2035384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2036384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
2037384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0) {
2038384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different chain / table\n");
2039384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2040384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2041384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2042384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (rulenum >= 0) {
2043384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Delete by rule number case */
20444acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			if (rule_ctr != rulenum)
2045384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
20464acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			found = true;
20474acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			break;
2048384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2049384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Delete by matching rule case */
2050384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("comparing with... ");
2051384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef DEBUG_DEL
20521ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso			nft_rule_print_save(r, NFT_RULE_APPEND, 0);
2053384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
2054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_to_iptables_command_state(r, &this);
2056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2057077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka			if (!ops->is_same(cs, &this))
2058384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2059384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2060384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_matches(cs->matches, r)) {
2061384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("matches not found\n");
2062384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_target(cs->target, r)) {
2066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("target not found\n");
2067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_immediate(r, cs->jumpto)) {
2071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("immediate not found\n");
2072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			found = true;
2076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
2077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
20794acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka		rule_ctr++;
2080384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
2081384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2082384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_iter_destroy(iter);
2084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
20853aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return found ? r : NULL;
2086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2087384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_check(struct nft_handle *h, const char *chain,
2089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   const char *table, struct iptables_command_state *e,
2090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   bool verbose)
2091384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
20923aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
20933aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret;
20943aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2095384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_check;
2096384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
20973aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
2098b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
20993aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
21003aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21013aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	ret = nft_rule_find(list, chain, table, e, -1) ? 1 : 0;
21023aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (ret == 0)
21033aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
21043aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21053aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
21063aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21073aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2108384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete(struct nft_handle *h, const char *chain,
21113aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		    const char *table, struct iptables_command_state *cs,
2112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    bool verbose)
2113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
21143aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
21153aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
21163aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
21173aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2118384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete;
2119384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
21203aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
2121b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
21223aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
21233aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21243aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	r = nft_rule_find(list, chain, table, cs, -1);
21253aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
21263aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		ret = 1;
21273aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21289e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (h->commit) {
21299e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
21309e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso						 NFT_RULE_F_COMMIT);
21319e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		}
21323aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("deleting rule\n");
21333aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		__nft_rule_del(h, r);
21343aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
21353aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
21363aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21373aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
21383aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21393aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete_num(struct nft_handle *h, const char *chain,
21433aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso			const char *table, int rulenum, bool verbose)
2144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
21453aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
21463aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
21473aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
21483aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2149384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete_num;
2150384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
21513aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
2152b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
21533aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
21543aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21553aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	r = nft_rule_find(list, chain, table, NULL, rulenum);
21563aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
21573aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		ret = 1;
21583aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21599e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (h->commit) {
21609e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
21619e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso						 NFT_RULE_F_COMMIT);
21629e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		}
21633aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("deleting rule by number %d\n", rulenum);
21643aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		__nft_rule_del(h, r);
21653aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
21663aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
21673aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21683aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
21693aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21703aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_replace(struct nft_handle *h, const char *chain,
2174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		     const char *table, struct iptables_command_state *cs,
2175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		     int rulenum, bool verbose)
2176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
21773aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
21783aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
21793aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
2180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_replace;
2182384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
21833aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
2184b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
21853aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
21863aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21873aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	r = nft_rule_find(list, chain, table, cs, rulenum);
21883aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
21891298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso		DEBUGP("replacing rule with handle=%llu\n",
21901298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso			(unsigned long long)
21911298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso			nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE));
2192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
21939e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (h->commit) {
21949e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
21959e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso						 NFT_RULE_F_COMMIT);
21969e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		}
21973aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		ret = nft_rule_add(h, chain, table, cs, true,
21981298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso				   nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE),
21993aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso				   verbose);
22003aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
22013aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
22023aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
22033aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
22043aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
22053aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2206384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2207384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2208384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2209384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_header(unsigned int format, const char *chain, const char *pol,
2210384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	     const struct xt_counters *counters, bool basechain, uint32_t refs)
2211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("Chain %s", chain);
2213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (basechain) {
2214384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(" (policy %s", pol);
2215384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (!(format & FMT_NOCOUNTS)) {
2216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputc(' ', stdout);
2217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_num(counters->pcnt, (format|FMT_NOTABLE));
2218384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("packets, ", stdout);
2219384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_num(counters->bcnt, (format|FMT_NOTABLE));
2220384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("bytes", stdout);
2221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2222384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(")\n");
2223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else {
2224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(" (%u references)\n", refs);
2225384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2227384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_LINENUMBERS)
2228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-4s ", "%s "), "num");
2229384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOCOUNTS)) {
2230384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (format & FMT_KILOMEGAGIGA) {
2231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5s ","%s "), "pkts");
2232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5s ","%s "), "bytes");
2233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2234384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%8s ","%s "), "pkts");
2235384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%10s ","%s "), "bytes");
2236384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2238384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOTARGET))
2239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-9s ","%s "), "target");
2240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	fputs(" prot ", stdout);
2241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_OPTIONS)
2242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputs("opt", stdout);
2243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_VIA) {
2244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT(" %-6s ","%s "), "in");
2245384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-6s ","%s "), "out");
2246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(FMT(" %-19s ","%s "), "source");
2248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(FMT(" %-19s "," %s "), "destination");
2249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("\n");
2250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2251384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_match(struct nft_rule_expr *expr, int numeric)
2254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
2256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *match_name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
2257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *match_info = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len);
2258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_match *match =
2259384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		xtables_find_match(match_name, XTF_TRY_LOAD, NULL);
2260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_match *m =
2261384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		calloc(1, sizeof(struct xt_entry_match) + len);
2262384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* emulate struct xt_entry_match since ->print needs it */
2264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy((void *)&m->data, match_info, len);
2265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match) {
2267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (match->print)
2268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* FIXME missing first parameter */
2269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			match->print(NULL, m, numeric);
2270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
2271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("%s ", match_name);
2272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else {
2273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (match_name[0])
2274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("UNKNOWN match `%s' ", match_name);
2275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(m);
2278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2279384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_firewall(const struct iptables_command_state *cs, struct nft_rule *r,
2282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	       unsigned int num, unsigned int format)
2283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_target *target = NULL;
2285384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *targname = NULL;
2286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *targinfo = NULL;
22870391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	int family;
2288077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	struct nft_family_ops *ops;
22890391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint8_t flags = 0;
2290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
2291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
2292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_target *t;
2293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t target_len = 0;
2294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
2296b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
2300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
2301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
2302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
2303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "target") == 0) {
23050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			targname = nft_rule_expr_get_str(expr,
23060391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka							 NFT_EXPR_TG_NAME);
23070391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			targinfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO,
23080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka						     &target_len);
2309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
2310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
2311384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			uint32_t verdict =
2312384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
2313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			switch(verdict) {
2315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_ACCEPT:
2316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "ACCEPT";
2317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_DROP:
2319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "DROP";
2320384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_RETURN:
2322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "RETURN";
2323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_GOTO:
23250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				targname = nft_rule_expr_get_str(expr,
23260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka							NFT_EXPR_IMM_CHAIN);
2327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2328384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_JUMP:
23290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				targname = nft_rule_expr_get_str(expr,
23300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka							NFT_EXPR_IMM_CHAIN);
2331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
2332384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2333384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2335384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2336384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2337384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
23380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
2339077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	ops = nft_family_ops_lookup(family);
23400391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
2341077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	flags = ops->print_firewall(cs, targname, num, format);
2342384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2343384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_NOTABLE)
2344384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputs("  ", stdout);
2345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef IPT_F_GOTO
23470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if(flags & IPT_F_GOTO)
2348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("[goto] ");
2349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
2350384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
2352b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2354384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2355384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
2356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
2357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
2358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
2359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "match") == 0)
2361384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_match(expr, format & FMT_NUMERIC);
2362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2364384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2365384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2366384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = calloc(1, sizeof(struct xt_entry_target) + target_len);
2368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (t == NULL)
2369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* emulate struct xt_entry_match since ->print needs it */
2372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy((void *)&t->data, targinfo, target_len);
2373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (targname) {
2375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		target = xtables_find_target(targname, XTF_TRY_LOAD);
2376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (target) {
2377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (target->print)
2378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				/* FIXME missing first parameter */
2379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				target->print(NULL, t, format & FMT_NUMERIC);
2380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else
2381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("[%ld bytes of unknown target data] ",
2382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				target_len);
2383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(t);
2385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NONEWLINE))
2387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputc('\n', stdout);
2388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
2391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_list(struct nft_handle *h, struct nft_chain *c, const char *table,
2392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int rulenum, unsigned int format,
2393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		void (*cb)(const struct iptables_command_state *cs,
2394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			   struct nft_rule *r, unsigned int num,
2395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			   unsigned int format))
2396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
2398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list_iter *iter;
2399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
2400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int rule_ctr = 0, ret = 0;
2401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
2404b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
2405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
2408b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2409b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
2412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
2413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
2414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
2415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
2416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
2417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		rule_ctr++;
2419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
2421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0)
2422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
24240b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		if (rulenum > 0 && rule_ctr != rulenum) {
2425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* List by rule number case */
24260b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			goto next;
24270b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		}
2428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
24290b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		struct iptables_command_state cs = {};
24300b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		/* Show all rules case */
24310b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		nft_rule_to_iptables_command_state(r, &cs);
24320b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo
24330b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		cb(&cs, r, rule_ctr, format);
24340b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		if (rulenum > 0 && rule_ctr == rulenum) {
24350b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			ret = 1;
24360b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			break;
2437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
24380b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo
2439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
2441384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2442384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_iter_destroy(iter);
2444b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
2445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_free(list);
2446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == 0)
2448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
2449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
2451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
2454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  int rulenum, unsigned int format)
2455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2456384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
2457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
24590a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo	bool found = false;
2460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2461aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka	/* If built-in chains don't exist for this table, create them */
2462aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
2463aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka		nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
2464aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka
2465384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
2466384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2467384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2468b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2469b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2470384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2471384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2472384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2473384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2474384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2475384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
2478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
2479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t refs =
2480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_USE);
2481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct xt_counters ctrs = {
2482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			.pcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS),
2483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			.bcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES),
2484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		};
2485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
2486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM))
2488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			basechain = true;
2489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
2493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
24950a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		if (found)
24960a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo			printf("\n");
24970a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
24980b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		if (!rulenum) {
24990b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			print_header(format, chain_name, policy_name[policy],
25000b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo				     &ctrs, basechain, refs);
25010b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		}
250206fc595fa99ab0036d87b259b0d20e4916522969Pablo Neira Ayuso		__nft_rule_list(h, c, table, rulenum, format, print_firewall);
25030a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
25040a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		found = true;
25050a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
2506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
251034c59adfae98515468ec50c644c30115fee0b97eGiuseppe Longo	nft_chain_list_iter_destroy(iter);
2511b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
2512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
2513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusolist_save(const struct iptables_command_state *cs, struct nft_rule *r,
2519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  unsigned int num, unsigned int format)
2520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
25211ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	nft_rule_print_save(r, NFT_RULE_APPEND, !(format & FMT_NOCOUNTS));
2522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
2525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_list_chain_save(struct nft_handle *h, const char *table,
2526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 struct nft_chain_list *list, int counters)
2527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
2530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2532b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
2542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
2543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* this is a base chain */
25487244bef43f350ab31ef54db8a81905f6c68acac0Tomasz Bursztyka		if (nft_chain_builtin(c)) {
2549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-P %s %s", chain_name, policy_name[policy]);
2550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (counters) {
25520a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo				printf(" -c %"PRIu64" %"PRIu64"\n",
2553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS),
2554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES));
2555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			} else
2556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				printf("\n");
2557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-N %s\n", chain_name);
2559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list_save(struct nft_handle *h, const char *chain,
2568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       const char *table, int rulenum, int counters)
2569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
2571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
257310f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso	int ret = 1;
2574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
2576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Dump policies and custom chains first */
257810f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso	if (!rulenum)
257910f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso		nft_rule_list_chain_save(h, table, list, counters);
2580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Now dump out rules in this table */
2582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2583b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2584b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
2596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
259810f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso		ret = __nft_rule_list(h, c, table, rulenum,
259910f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso				      counters ? 0 : FMT_NOCOUNTS, list_save);
2600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2603b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
2604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
2605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
260610f92fce0a2ea1805c8b269543b8f1738d22bf3dPablo Neira Ayuso	return ret;
2607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
26099e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusostatic int nft_action(struct nft_handle *h, int type)
26109e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
26119e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
26129e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	struct nlmsghdr *nlh;
26139e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	uint32_t seq;
26149e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	int ret;
26159e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
26169e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh = mnl_nlmsg_put_header(buf);
26179e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh->nlmsg_type = (NFNL_SUBSYS_NFTABLES<< 8) | type;
26189e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
26199e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh->nlmsg_seq = seq = time(NULL);
26209e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
26219e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
26223f7877e6be987bb94897c03a45945725389a6f5cPablo Neira Ayuso	nfg->nfgen_family = h->family;
26239e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nfg->version = NFNETLINK_V0;
26249e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nfg->res_id = 0;
26259e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
26269e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
26279e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	if (ret < 0) {
26289e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (errno != EEXIST)
26299e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			perror("mnl-talk:nft_commit");
26309e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	}
2631f041efe3c26e3059df1ac8f1775f77423d4be5f6Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
26329e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
26339e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
26349e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_commit(struct nft_handle *h)
26359e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
26369e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	return nft_action(h, NFT_MSG_COMMIT);
26379e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
26389e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
26399e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_abort(struct nft_handle *h)
26409e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
26419e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	return nft_action(h, NFT_MSG_ABORT);
26429e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
26439e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
2644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_compatible_revision(const char *name, uint8_t rev, int opt)
2645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct mnl_socket *nl;
2647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
2648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
2649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t portid, seq, type;
2650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
2651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (opt == IPT_SO_GET_REVISION_MATCH)
2653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 0;
2654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
2655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 1;
2656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = mnl_nlmsg_put_header(buf);
2658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_type = (NFNL_SUBSYS_NFT_COMPAT << 8) | NFNL_MSG_COMPAT_GET;
2659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
2660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_seq = seq = time(NULL);
2661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
2663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->nfgen_family = AF_INET;
2664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->version = NFNETLINK_V0;
2665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->res_id = 0;
2666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_strz(nlh, NFTA_COMPAT_NAME, name);
2668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_REV, htonl(rev));
2669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_TYPE, htonl(type));
2670384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	DEBUGP("requesting `%s' rev=%d type=%d via nft_compat\n",
2672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		name, rev, type);
2673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nl = mnl_socket_open(NETLINK_NETFILTER);
2675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nl == NULL) {
2676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_open");
2677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
2681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_bind");
2682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	portid = mnl_socket_get_portid(nl);
2685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
2687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_send");
2688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2691384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
2692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
2693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_recvfrom");
2694384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
2698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
2699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_cb_run");
2700384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
2704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(nl);
2705384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2706384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret < 0 ? 0 : 1;
2707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/* Translates errno numbers into more human-readable form than strerror. */
2710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoconst char *nft_strerror(int err)
2711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
2713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	static struct table_struct {
2714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		void *fn;
2715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int err;
2716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *message;
2717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} table[] =
2718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  {
2719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, ENOTEMPTY, "Chain is not empty" },
2720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EINVAL, "Can't delete built-in chain" },
2721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EMLINK,
2722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Can't delete chain with references left" },
2723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_add, EEXIST, "Chain already exists" },
2724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, E2BIG, "Index of insertion too big" },
2725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_replace, E2BIG, "Index of replacement too big" },
2726384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete_num, E2BIG, "Index of deletion too big" },
2727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/*	    { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
2728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, */
2729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, ELOOP, "Loop found in table" },
2730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, EINVAL, "Target problem" },
2731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    /* ENOENT for DELETE probably means no matching rule */
2732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete, ENOENT,
2733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Bad rule (does a matching rule exist in that chain?)" },
2734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, ENOENT, "Bad built-in chain name" },
2735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, EINVAL, "Bad policy name" },
2736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, EPERM, "Permission denied (you must be root)" },
2737384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, 0, "Incompatible with this kernel" },
2738384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
2739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOSYS, "Will be implemented real soon.  I promise ;)" },
2740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOMEM, "Memory allocation problem" },
2741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOENT, "No chain/target/match by that name" },
2742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  };
2743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
2745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if ((!table[i].fn || table[i].fn == nft_fn)
2746384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    && table[i].err == err)
2747384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return table[i].message;
2748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2750384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return strerror(err);
2751384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
27528b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27538b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayusostatic void xtables_config_perror(uint32_t flags, const char *fmt, ...)
27548b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso{
27558b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_list args;
27568b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27578b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_start(args, fmt);
27588b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27598b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (flags & NFT_LOAD_VERBOSE)
27608b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		vfprintf(stderr, fmt, args);
27618b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27628b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_end(args);
27638b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso}
27648b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27658b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayusoint nft_xtables_config_load(struct nft_handle *h, const char *filename,
27668b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			    uint32_t flags)
27678b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso{
27688b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_table_list *table_list = nft_table_list_alloc();
27698b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_chain_list *chain_list = nft_chain_list_alloc();
27708b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_table_list_iter *titer;
27718b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_chain_list_iter *citer;
27728b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_table *table;
27738b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_chain *chain;
27748b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27758b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (xtables_config_parse(filename, table_list, chain_list) < 0) {
27768b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		if (errno == ENOENT) {
27778b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			xtables_config_perror(flags,
27788b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				"configuration file `%s' does not exists\n",
27798b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				filename);
27808b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		} else {
27818b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			xtables_config_perror(flags,
27828b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				"Fatal error parsing config file: %s\n",
27838b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				 strerror(errno));
27848b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
27858b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		return -1;
27868b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
27878b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27888b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	/* Stage 1) create tables */
27898b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	titer = nft_table_list_iter_create(table_list);
27908b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	while ((table = nft_table_list_iter_next(titer)) != NULL) {
27918b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		if (nft_table_add(h, table) < 0) {
27928b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			if (errno == EEXIST) {
27938b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
27948b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"table `%s' already exists, skipping\n",
27958b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_table_attr_get(table, NFT_TABLE_ATTR_NAME));
27968b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			} else {
27978b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
27988b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"table `%s' cannot be create, reason `%s'. Exitting\n",
27998b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_table_attr_get(table, NFT_TABLE_ATTR_NAME),
28008b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					strerror(errno));
28012c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso				nft_table_list_iter_destroy(titer);
28022c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso				nft_table_list_free(table_list);
28038b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				return -1;
28048b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			}
28058b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			continue;
28068b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
28078b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		xtables_config_perror(flags, "table `%s' has been created\n",
28088b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			(char *)nft_table_attr_get(table, NFT_TABLE_ATTR_NAME));
28098b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
28102c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_table_list_iter_destroy(titer);
28112c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_table_list_free(table_list);
28128b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
28138b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	/* Stage 2) create chains */
28148b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	citer = nft_chain_list_iter_create(chain_list);
28158b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	while ((chain = nft_chain_list_iter_next(citer)) != NULL) {
28168b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		if (nft_chain_add(h, chain) < 0) {
28178b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			if (errno == EEXIST) {
28188b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
28198b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"chain `%s' already exists in table `%s', skipping\n",
28208b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_NAME),
28218b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_TABLE));
28228b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			} else {
28238b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
28248b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"chain `%s' cannot be create, reason `%s'. Exitting\n",
28258b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_NAME),
28268b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					strerror(errno));
28272c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso				nft_chain_list_iter_destroy(citer);
28282c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso				nft_chain_list_free(chain_list);
28298b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				return -1;
28308b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			}
28318b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			continue;
28328b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
28338b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
28348b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		xtables_config_perror(flags,
28358b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			"chain `%s' in table `%s' has been created\n",
28368b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_NAME),
28378b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_TABLE));
28388b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
28392c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_chain_list_iter_destroy(citer);
28402c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_chain_list_free(chain_list);
28412c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso
28428b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	return 0;
28438b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso}
2844b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2845b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longoint nft_chain_zero_counters(struct nft_handle *h, const char *chain,
2846b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			    const char *table)
2847b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo{
2848b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nft_chain_list *list;
2849b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nft_chain_list_iter *iter;
2850b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nft_chain *c;
2851b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nlmsghdr *nlh;
2852b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	char buf[MNL_SOCKET_BUFFER_SIZE];
2853b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	int ret = 0;
2854b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2855b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	list = nft_chain_list_get(h);
2856b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	if (list == NULL)
2857b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		goto err;
2858b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2859b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	iter = nft_chain_list_iter_create(list);
2860b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2861b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2862b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2863b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	c = nft_chain_list_iter_next(iter);
2864b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	while (c != NULL) {
2865b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		const char *chain_name =
2866b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			nft_chain_attr_get(c, NFT_CHAIN_ATTR_NAME);
2867b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		const char *chain_table =
2868b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			nft_chain_attr_get(c, NFT_CHAIN_ATTR_TABLE);
2869b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2870b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		if (strcmp(table, chain_table) != 0)
2871b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			goto next;
2872b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2873b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		if (chain != NULL && strcmp(chain, chain_name) != 0)
2874b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			goto next;
2875b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2876b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_PACKETS, 0);
2877b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES, 0);
2878b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2879b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_attr_unset(c, NFT_CHAIN_ATTR_HANDLE);
2880b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2881b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
2882b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo						h->family, NLM_F_ACK, h->seq);
2883b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2884b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_nlmsg_build_payload(nlh, c);
2885b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2886b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		ret = mnl_talk(h, nlh, NULL, NULL);
2887b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		if (ret < 0)
2888b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			perror("mnl_talk:nft_chain_zero_counters");
2889b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
289036ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
289136ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
2892b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longonext:
2893b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		c = nft_chain_list_iter_next(iter);
2894b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	}
2895b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2896b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	nft_chain_list_iter_destroy(iter);
2897b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2898b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longoerr:
2899b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	nft_chain_list_free(list);
2900b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2901b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	/* the core expects 1 for success and 0 for error */
2902b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	return ret == 0 ? 1 : 0;
2903b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo}
2904b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2905