nft.c revision 0b3bafcedff19b69ff5a51855da28e8e83c05b71
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
384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_init(struct nft_handle *h)
385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->nl = mnl_socket_open(NETLINK_NETFILTER);
387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (h->nl == NULL) {
388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_open");
389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_bind");
394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->portid = mnl_socket_get_portid(h->nl);
397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusovoid nft_fini(struct nft_handle *h)
402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(h->nl);
404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_table_add(struct nft_handle *h, const struct nft_table *t)
407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
4110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_add(struct nft_handle *h, const struct nft_chain *c)
419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
4230391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
4305705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoint nft_table_set_dormant(struct nft_handle *h, const char *table)
4315705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso{
4325705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	int ret = 0, i;
4335705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct builtin_table *t;
4345705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4355705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	t = nft_table_builtin_find(table);
4365705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (t == NULL) {
4375705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		ret = -1;
4385705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		goto out;
4395705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	}
4405705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	/* Add this table as dormant */
4415705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (nft_table_builtin_add(h, t, true) < 0) {
4425705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		/* Built-in table already initialized, skip. */
4435705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		if (errno == EEXIST)
4445705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso			goto out;
4455705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	}
4465705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	for (i=0; t->chains[i].name != NULL && i<NF_INET_NUMHOOKS; i++)
4475705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		__nft_chain_builtin_init(h, t, t->chains[i].name, NF_ACCEPT);
4485705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoout:
4495705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	return ret;
4505705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso}
4515705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4525705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoint nft_table_wake_dormant(struct nft_handle *h, const char *table)
4535705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso{
4545705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
4555705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct nlmsghdr *nlh;
4565705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct nft_table *t;
4575705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4585705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	t = nft_table_alloc();
4595705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (t == NULL)
4605705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		return -1;
4615705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4625705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)table);
4635705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS, 0);
4645705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
4665705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso					NLM_F_ACK, h->seq);
4675705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
4685705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_free(t);
4695705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4705705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
4715705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso}
4725705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
473384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_debug(struct nft_chain *c, struct nlmsghdr *nlh)
474384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
475384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_snprintf(tmp, sizeof(tmp), c, 0, 0);
479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("DEBUG: chain: %s", tmp);
480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_chain_set(struct nft_handle *h, const char *table,
486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain, int policy,
487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const struct xt_counters *counters)
488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
492c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_table *_t;
493c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_chain *_c;
494e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int ret;
495c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
496c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	_t = nft_table_builtin_find(table);
497c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	/* if this built-in table does not exists, create it */
498c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_t != NULL)
4995705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		nft_table_builtin_add(h, _t, false);
500c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
501e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	_c = nft_chain_builtin_find(_t, chain);
502c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_c != NULL) {
503c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		/* This is a built-in chain */
504c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		c = nft_chain_builtin_alloc(_t, _c, policy);
505c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		if (c == NULL)
506c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			return -1;
507c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	} else {
50820c156f9f4c43857a622f015a3022517601c3600Tomasz Bursztyka		errno = ENOENT;
50920c156f9f4c43857a622f015a3022517601c3600Tomasz Bursztyka		return -1;
510c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (counters) {
513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES,
514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->bcnt);
515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_PACKETS,
516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->pcnt);
517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
5190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_print_debug(c, nlh);
524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:__nft_chain_policy");
530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_set(struct nft_handle *h, const char *table,
535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const char *chain, const char *policy,
536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const struct xt_counters *counters)
537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = -1;
539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_chain_set;
541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(policy, "DROP") == 0)
543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_set(h, table, chain, NF_DROP, counters);
544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else if (strcmp(policy, "ACCEPT") == 0)
545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_set(h, table, chain, NF_ACCEPT, counters);
546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void __add_match(struct nft_rule_expr *e, struct xt_entry_match *m)
552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	void *info;
554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_MT_NAME, m->u.user.name, strlen(m->u.user.name));
556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(e, NFT_EXPR_MT_REV, m->u.user.revision);
557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	info = calloc(1, m->u.match_size);
559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (info == NULL)
560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(info, m->data, m->u.match_size);
563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_MT_INFO, info, m->u.match_size - sizeof(*m));
564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_match(struct nft_rule *r, struct xt_entry_match *m)
567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("match");
571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	__add_match(expr, m);
575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void __add_target(struct nft_rule_expr *e, struct xt_entry_target *t)
579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	void *info = NULL;
581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_TG_NAME, t->u.user.name,
583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  strlen(t->u.user.name));
584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(e, NFT_EXPR_TG_REV, t->u.user.revision);
585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (info == NULL) {
587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		info = calloc(1, t->u.target_size);
588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (info == NULL)
589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return;
590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(info, t->data, t->u.target_size);
592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_TG_INFO, info, t->u.target_size - sizeof(*t));
595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_target(struct nft_rule *r, struct xt_entry_target *t)
598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("target");
602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	__add_target(expr, t);
606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_jumpto(struct nft_rule *r, const char *name, int verdict)
610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("immediate");
614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT);
618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict);
619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_str(expr, NFT_EXPR_IMM_CHAIN, (char *)name);
620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_verdict(struct nft_rule *r, int verdict)
624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("immediate");
628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT);
632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict);
633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_rule_print_debug(struct nft_rule *r, struct nlmsghdr *nlh)
637384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
639384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_snprintf(tmp, sizeof(tmp), r, 0, 0);
642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("DEBUG: rule: %s", tmp);
643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_counters(struct nft_rule *r, uint64_t packets, uint64_t bytes)
648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("counter");
652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_BYTES, packets);
656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_PACKETS, bytes);
657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
6614ef77b6d1b52e1fe52a7fd48d38d9233f0961640Pablo Neira Ayusovoid add_compat(struct nft_rule *r, uint32_t proto, bool inv)
6622a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso{
6632a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso	nft_rule_attr_set_u32(r, NFT_RULE_ATTR_COMPAT_PROTO, proto);
6642a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso	nft_rule_attr_set_u32(r, NFT_RULE_ATTR_COMPAT_FLAGS,
6652a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso			      inv ? NFT_RULE_COMPAT_F_INV : 0);
6662a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso}
6672a87a024e1f77407e332086a4fa664e048280195Pablo Neira Ayuso
668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint
669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_add(struct nft_handle *h, const char *chain, const char *table,
6700a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	     struct iptables_command_state *cs,
6711298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso	     bool append, uint64_t handle, bool verbose)
672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 1;
678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int flags = append ? NLM_F_APPEND : 0;
6790391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	int ip_flags = 0;
680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
681e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
6828b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
6838b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		nft_chain_builtin_init(h, table, chain, NF_ACCEPT);
684c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_add;
686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL) {
689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
691384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
694384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
696077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	ip_flags = h->ops->add(r, cs);
697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (matchp = cs->matches; matchp; matchp = matchp->next)
699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		add_match(r, matchp->match->m);
700384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Counters need to me added before the target, otherwise they are
702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 * increased for each rule because of the way nf_tables works.
703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 */
704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	add_counters(r, cs->counters.pcnt, cs->counters.bcnt);
705384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
706384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* If no target at all, add nothing (default to continue) */
707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (cs->target != NULL) {
708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* Standard target? */
709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_verdict(r, NF_ACCEPT);
711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_verdict(r, NF_DROP);
713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_verdict(r, NFT_RETURN);
715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_target(r, cs->target->t);
717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else if (strlen(cs->jumpto) > 0) {
718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* Not standard, then it's a go / jump to chain */
7190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (ip_flags & IPT_F_GOTO)
720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_jumpto(r, cs->jumpto, NFT_GOTO);
721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_jumpto(r, cs->jumpto, NFT_JUMP);
723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* NLM_F_CREATE autoloads the built-in table if it does not exists */
7260a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	flags |= NLM_F_ACK|NLM_F_CREATE;
7270a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka
7280a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	if (handle > 0) {
7290a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka		nft_rule_attr_set(r, NFT_RULE_ATTR_HANDLE, &handle);
7300a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka		flags |= NLM_F_REPLACE;
7310a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	}
7320a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka
7339e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	if (h->commit) {
7349e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
7359e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso				      NFT_RULE_F_COMMIT);
7369e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	}
7370a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE,
7380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				       h->family, flags, h->seq);
7390a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka
740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_print_debug(r, nlh);
743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
746384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
747384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_add");
749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
750384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
751384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
752384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
753384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
754384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
755384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_match_save(struct nft_rule_expr *expr)
756384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
757384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
758384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_match *match;
759384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_match *emu;
760384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *mtinfo;
761384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
762384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
763384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
764384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	match = xtables_find_match(name, XTF_TRY_LOAD, NULL);
766384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match == NULL)
767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
769384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mtinfo = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len);
770384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mtinfo == NULL)
771384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
772384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
773384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	emu = calloc(1, sizeof(struct xt_entry_match) + len);
774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (emu == NULL)
775384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
776384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
777384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(&emu->data, mtinfo, len);
778384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
779384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match->alias)
780384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-m %s", match->alias(emu));
781384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-m %s", match->name);
783384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
784384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* FIXME missing parameter */
785c51b85f995caebd41e6d063c8bcab513b305bcaaPablo Neira Ayuso	if (match->save)
786c51b85f995caebd41e6d063c8bcab513b305bcaaPablo Neira Ayuso		match->save(NULL, emu);
787384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
788384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(" ");
789384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
790384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(emu);
791384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
792384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
793384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_target_save(struct nft_rule_expr *expr)
794384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
795384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
796384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_target *target;
797384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_target *emu;
798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *tginfo;
799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
800384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
802384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
803384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Standard target not supported, we use native immediate expression */
804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "") == 0) {
805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("ERROR: standard target seen, should not happen\n");
806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	target = xtables_find_target(name, XTF_TRY_LOAD);
810384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target == NULL)
811384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
812384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
813384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	tginfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len);
814384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (tginfo == NULL)
815384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
816384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
817384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	emu = calloc(1, sizeof(struct xt_entry_match) + len);
818384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (emu == NULL)
819384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
820384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
821384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(emu->data, tginfo, len);
822384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
823384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target->alias)
824384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s", target->alias(emu));
825384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
826384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s", target->name);
827384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
828384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* FIXME missing parameter */
829c51b85f995caebd41e6d063c8bcab513b305bcaaPablo Neira Ayuso	if (target->save)
830c51b85f995caebd41e6d063c8bcab513b305bcaaPablo Neira Ayuso		target->save(NULL, emu);
831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
832384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(emu);
833384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
834384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_immediate_save(struct nft_rule_expr *expr)
836384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
837384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t verdict;
838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
839384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(verdict) {
842384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_ACCEPT:
843384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j ACCEPT");
844384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
845384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_DROP:
846384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j DROP");
847384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
848384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_RETURN:
849384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j RETURN");
850384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
851384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_GOTO:
852384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-g %s",
853384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN));
854384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
855384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_JUMP:
856384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s",
857384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN));
858384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
859384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
860384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
861384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
862384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
863384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_print_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
864384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
865384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
866384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t value;
867384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
868384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char ifname[IFNAMSIZ];
869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *ifname_ptr;
870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
871384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
872384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
873384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (e == NULL)
874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
876384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
877384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* meta should be followed by cmp */
878384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "cmp") != 0) {
879384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("skipping no cmp after meta\n");
880384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
881384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
882384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
883384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(key) {
884384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIF:
885384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
886384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if_indextoname(value, ifname);
887384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
888384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
889384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
890384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-i %s ", ifname);
891384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
892384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
893384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -i %s ", ifname);
894384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
895384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
896384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
897384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIF:
898384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
899384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if_indextoname(value, ifname);
900384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
901384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
902384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
903384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-o %s ", ifname);
904384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
905384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
906384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -o %s ", ifname);
907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
908384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIFNAME:
911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(ifname, ifname_ptr, len);
913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname[len] = '\0';
914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* if this is zero, then assume this is a interface mask */
916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (if_nametoindex(ifname) == 0) {
917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len] = '+';
918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len+1] = '\0';
919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-i %s ", ifname);
924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -i %s ", ifname);
927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIFNAME:
931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(ifname, ifname_ptr, len);
933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname[len] = '\0';
934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* if this is zero, then assume this is a interface mask */
936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (if_nametoindex(ifname) == 0) {
937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len] = '+';
938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len+1] = '\0';
939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
942384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
943384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-o %s ", ifname);
944384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
946384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -o %s ", ifname);
947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
949384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
950384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	default:
951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("unknown meta key %d\n", key);
952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_print_counters(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   bool counters)
959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (counters) {
9610a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		printf("-c %"PRIu64" %"PRIu64" ",
962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS),
963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES));
964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
9671ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayusovoid
9681ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayusonft_rule_print_save(struct nft_rule *r, enum nft_rule_print type, bool counters)
969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
9721ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	const char *chain = nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
9751ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	switch(type) {
9761ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	case NFT_RULE_APPEND:
9771ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		printf("-A %s ", chain);
9781ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		break;
9791ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	case NFT_RULE_DEL:
9801ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		printf("-D %s ", chain);
9811ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		break;
9821ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	}
983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
985384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL)
986384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
987384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
988384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
989384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
990384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
991384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
992384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
993384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "counter") == 0) {
994384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_print_counters(expr, iter, counters);
995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "payload") == 0) {
996077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka			struct nft_family_ops *ops = nft_family_ops_lookup(
997077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka				nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY));
998077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka			ops->print_payload(expr, iter);
999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "meta") == 0) {
1000384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_print_meta(expr, iter);
1001384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "match") == 0) {
1002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_match_save(expr);
1003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "target") == 0) {
1004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_target_save(expr);
1005384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
1006384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_immediate_save(expr);
1007384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1008384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1009384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1010384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1011384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1012384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("\n");
1013384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1014384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1015384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_chain_list_cb(const struct nlmsghdr *nlh, void *data)
1016384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1017384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1018384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list = data;
1019384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1020384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
1021384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL) {
1022384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1023384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1024384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_chain_nlmsg_parse(nlh, c) < 0) {
1027384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1028384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1029384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1030384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1031384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_add(c, list);
1032384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1033384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1034384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1035384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
1036384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1037384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1038384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1039384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1040384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_chain_list *nft_chain_list_get(struct nft_handle *h)
1041384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1042384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1043384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1044384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1045384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1046384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1047384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_alloc();
1048384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1049b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		errno = ENOMEM;
1050b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		return NULL;
1051384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1052384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
10530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
1054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_chain_list_cb, list);
1057384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1058384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_chain_list_get");
1059384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1060384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1061384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1062384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostruct nft_chain_list *nft_chain_dump(struct nft_handle *h)
1064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return nft_chain_list_get(h);
1066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic const char *policy_name[NF_ACCEPT+1] = {
1069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_DROP] = "DROP",
1070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_ACCEPT] = "ACCEPT",
1071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso};
1072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_save(struct nft_chain *c, bool basechain)
1074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint64_t pkts = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS);
1077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint64_t bytes = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES);
1078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1079384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
1080384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (basechain) {
1081384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t pol = NF_ACCEPT;
1082384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* no default chain policy? don't crash, display accept */
1084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_POLICY))
1085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			pol = nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
1086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
10870a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		printf(":%s %s [%"PRIu64":%"PRIu64"]\n", chain, policy_name[pol],
1088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					     pkts, bytes);
1089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else
10900a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		printf(":%s - [%"PRIu64":%"PRIu64"]\n", chain, pkts, bytes);
1091384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_save(struct nft_handle *h, struct nft_chain_list *list,
1094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   const char *table)
1095384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1096384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1097384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1100b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1101384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1103384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1104384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1105384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
1106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1107384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
1108384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
1110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1111384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM))
1113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			basechain = true;
1114384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1115384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_print_save(c, basechain);
1116384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1117384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1118384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1119384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1120d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_chain_list_iter_destroy(iter);
1121384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1122384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1124384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1125384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1126384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_rule_list_cb(const struct nlmsghdr *nlh, void *data)
1127384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1128384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1129384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list = data;
1130384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1131384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
1132384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL) {
1133384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1134384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1135384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1136384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1137384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_rule_nlmsg_parse(nlh, r) < 0) {
1138384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1139384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_add(r, list);
1143384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1146384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
1147137cc981906f356c971da6de13e777a419382ff4Giuseppe Longo	nft_rule_list_free(list);
1148384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1149384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1150384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_rule_list *nft_rule_list_get(struct nft_handle *h)
1153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1155384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
1157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_alloc();
1160b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1161384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11630391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
1164384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1165384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_rule_list_cb, list);
1167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_save");
1169384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_rule_list_free(list);
1170384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return NULL;
1171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_save(struct nft_handle *h, const char *table, bool counters)
1177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
1179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list_iter *iter;
1180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1182384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
1183b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
1187b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1188384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
1191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
1192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
1193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
1194384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1195384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0)
1196384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1197384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11981ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso		nft_rule_print_save(r, NFT_RULE_APPEND, counters);
1199384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1200384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
1202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1203384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1204d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_rule_list_iter_destroy(iter);
1205384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_free(list);
1206384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1207384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1208384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1209384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1210384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
1213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1214384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1215384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1218384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
1219384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL)
1220384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1222384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
1223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
1224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
12259e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	if (h->commit) {
12269e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
12279e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso					 NFT_RULE_F_COMMIT);
12289e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	}
12299e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
1230384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Delete all rules in this table + chain */
12310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, h->family,
1232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
1234384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
1235384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1236384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_talk(h, nlh, NULL, NULL) < 0) {
1237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
1238384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:__nft_rule_flush");
1239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
1243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1245384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_flush;
1250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1251384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_get(h);
1252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
1254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1258b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1259b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
1260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1261384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1262384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		__nft_rule_flush(h, table_name, chain_name);
1275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
127636ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
127736ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
1278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1279384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1282d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_chain_list_iter_destroy(iter);
1283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1285384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table)
1291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1297e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
12988b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
12998b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
1300e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
1301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
1302b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (c == NULL)
1303b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		return 0;
1304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
1306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain);
1307384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
13080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
1309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
1310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
1311384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
1312384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
1316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:nft_chain_add");
1317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1320384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int __nft_chain_del(struct nft_handle *h, struct nft_chain *c)
1324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1325384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1328384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
13290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, h->family,
1330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
1332384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1333384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1335384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST && errno != ENOENT)
1336384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:__nft_chain_del");
1337384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1339384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1340384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1341384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1342384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool nft_chain_builtin(struct nft_chain *c)
1343384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1344384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Check if this chain has hook number, in that case is built-in.
1345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 * Should we better export the flags to user-space via nf_tables?
1346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 */
1347384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM) != NULL;
1348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1350384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table)
1351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1352384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1354384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1355384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
1356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int deleted_ctr = 0;
1357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_get(h);
1359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1361384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1363b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1364b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
1365384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1366384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* don't delete built-in chain */
1374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_builtin(c))
1375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_del(h, c);
1384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (ret < 0)
1385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		deleted_ctr++;
138836ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo
138936ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
139036ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
1391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1395d01b2c28c8101f0d24e1db3f146fd845c2a634e8Giuseppe Longo	nft_chain_list_iter_destroy(iter);
1396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* chain not found */
1400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0 && deleted_ctr == 0)
1401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
1402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14070aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusostruct nft_chain *
14080aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonft_chain_list_find(struct nft_handle *h, struct nft_chain_list *list,
14090aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		    const char *table, const char *chain)
14109c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso{
14119c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
14129c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	struct nft_chain *c;
14139c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14149c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1415b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
14169c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return NULL;
14179c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14189c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
14199c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	while (c != NULL) {
14209c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		const char *table_name =
14219c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
14229c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		const char *chain_name =
14239c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
14249c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14259c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
14269c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			goto next;
14279c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14289c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		if (strcmp(chain, chain_name) != 0)
14299c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			goto next;
14309c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14310aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		nft_chain_list_iter_destroy(iter);
14329c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return c;
14339c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayusonext:
14349c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
14359c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	}
14360aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	nft_chain_list_iter_destroy(iter);
14379c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	return NULL;
14389c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso}
14399c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14400aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusostatic struct nft_chain *
14410aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonft_chain_find(struct nft_handle *h, const char *table, const char *chain)
14420aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{
14430aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain_list *list;
14440aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
14450aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	list = nft_chain_list_get(h);
1446b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
14470aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		return NULL;
14480aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
14490aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	return nft_chain_list_find(h, list, table, chain);
14500aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso}
14510aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_rename(struct nft_handle *h,const char *chain,
1453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  const char *table, const char *newname)
1454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
14554493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	char buf[MNL_SOCKET_BUFFER_SIZE];
14564493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	struct nlmsghdr *nlh;
14574493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	struct nft_chain *c;
14589c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	uint64_t handle;
1459384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14614493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	/* If built-in chains don't exist for this table, create them */
14628b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
14638b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
14644493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
14659c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	/* Find the old chain to be renamed */
14669c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	c = nft_chain_find(h, table, chain);
14679c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	if (c == NULL) {
14689c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		errno = ENOENT;
14699c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return -1;
14709c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	}
14719c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	handle = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_HANDLE);
14729c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
14739c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	/* Now prepare the new name for the chain */
14744493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	c = nft_chain_alloc();
1475b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (c == NULL)
14764493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka		return -1;
14774493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
14784493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
14799c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)newname);
14809c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_HANDLE, handle);
1481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14820391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
14839c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
14844493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_nlmsg_build_payload(nlh, c);
14854493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_free(c);
14864493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
14874493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	ret = mnl_talk(h, nlh, NULL, NULL);
14884493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	if (ret < 0) {
14894493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka		if (errno != EEXIST)
14904493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka			perror("mnl_talk:nft_chain_rename");
14914493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	}
14924493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
14934493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	/* the core expects 1 for success and 0 for error */
14944493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	return ret == 0 ? 1 : 0;
1495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_table_list_cb(const struct nlmsghdr *nlh, void *data)
1498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list = data;
1501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_alloc();
1503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (t == NULL) {
1504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1505384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_table_nlmsg_parse(nlh, t) < 0) {
1509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_add(t, list);
1514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_free(t);
1518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_table_list *nft_table_list_get(struct nft_handle *h)
1523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_alloc();
1530b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
1531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
15330391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
1534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_table_list_cb, list);
1537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_table_list_get");
1539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusobool nft_table_find(struct nft_handle *h, const char *tablename)
1544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list_iter *iter;
1547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool ret = false;
1549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_get(h);
1551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_table_list_iter_create(list);
1555b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_list_iter_next(iter);
1559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
1560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *this_tablename =
1561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_table_attr_get(t, NFT_TABLE_ATTR_NAME);
1562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(tablename, this_tablename) == 0)
1564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return true;
1565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		t = nft_table_list_iter_next(iter);
1567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_free(list);
1570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_for_each_table(struct nft_handle *h,
1576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       int (*func)(struct nft_handle *h, const char *tablename, bool counters),
1577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       bool counters)
1578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 1;
1580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list_iter *iter;
1582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_get(h);
1585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
1587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_table_list_iter_create(list);
1591b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_list_iter_next(iter);
1595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
1596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *tablename =
1597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_table_attr_get(t, NFT_TABLE_ATTR_NAME);
1598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		func(h, tablename, counters);
1600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		t = nft_table_list_iter_next(iter);
1602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_free(list);
1605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
16110aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusoint nft_table_purge_chains(struct nft_handle *h, const char *this_table,
16120aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			   struct nft_chain_list *chain_list)
16130aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{
16140aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain_list_iter *iter;
16150aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain *chain_obj;
16160aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16170aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	iter = nft_chain_list_iter_create(chain_list);
1618b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
16190aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		return 0;
16200aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16210aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	chain_obj = nft_chain_list_iter_next(iter);
16220aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	while (chain_obj != NULL) {
16230aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		const char *table =
16240aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			nft_chain_attr_get_str(chain_obj, NFT_CHAIN_ATTR_TABLE);
16250aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16260aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if (strcmp(this_table, table) != 0)
16270aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			goto next;
16280aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16290aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if (nft_chain_builtin(chain_obj))
16300aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			goto next;
16310aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16320aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if ( __nft_chain_del(h, chain_obj) < 0) {
16330aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			if (errno != EBUSY)
16340aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso				return -1;
16350aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		}
16360aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonext:
16370aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		chain_obj = nft_chain_list_iter_next(iter);
16380aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	}
16390aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	nft_chain_list_iter_destroy(iter);
16400aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
16410aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	return 0;
16420aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso}
16430aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic inline int
1645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusomatch_different(const struct xt_entry_match *a,
1646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const unsigned char *a_elems,
1647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const unsigned char *b_elems,
1648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		unsigned char **maskptr)
1649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xt_entry_match *b;
1651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
1652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Offset of b is the same as a. */
1654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	b = (void *)b_elems + ((unsigned char *)a - a_elems);
1655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (a->u.match_size != b->u.match_size)
1657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 1;
1658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(a->u.user.name, b->u.user.name) != 0)
1660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 1;
1661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	*maskptr += XT_ALIGN(sizeof(*a));
1663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < a->u.match_size - XT_ALIGN(sizeof(*a)); i++)
1665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0)
1666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return 1;
1667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	*maskptr += i;
1668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
1669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1670384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
16730391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	       int family, struct iptables_command_state *cs)
1674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
1676077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	struct nft_family_ops *ops = nft_family_ops_lookup(family);
1677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
1678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
1680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (e == NULL)
1681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
1684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "cmp") != 0) {
1685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("skipping no cmp after meta\n");
1686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1689077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	ops->parse_meta(e, key, cs);
16900391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
16910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
16920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void
16930391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_parse_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
16940391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		  int family, struct iptables_command_state *cs)
16950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{
1696077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	struct nft_family_ops *ops = nft_family_ops_lookup(family);
16970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint32_t offset;
16980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
16990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
17000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
1701077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	ops->parse_payload(iter, cs, offset);
17020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
17030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
17040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void
1705384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_counter(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
1706384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  struct xt_counters *counters)
1707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	counters->pcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS);
1709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	counters->bcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES);
1710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_immediate(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
17140391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    int family, struct iptables_command_state *cs)
1715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int verdict = nft_rule_expr_get_u32(e, NFT_EXPR_IMM_VERDICT);
1717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_rule_expr_get_str(e, NFT_EXPR_IMM_CHAIN);
1718077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	struct nft_family_ops *ops;
1719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Standard target? */
1721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(verdict) {
1722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_ACCEPT:
1723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "ACCEPT";
1724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_DROP:
1726384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "DROP";
1727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_RETURN:
1729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "RETURN";
1730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_GOTO:
1732077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka		ops = nft_family_ops_lookup(family);
1733077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka		ops->parse_immediate(cs);
1734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_JUMP:
1735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = chain;
1736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1737384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1738384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_to_iptables_command_state(struct nft_rule *r,
1742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				   struct iptables_command_state *cs)
1743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
17460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	int family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
1747384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL)
1750384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1751384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1752384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1753384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1754384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1755384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1756384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1757384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "counter") == 0) {
1758384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_parse_counter(expr, iter, &cs->counters);
1759384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "payload") == 0) {
17600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			nft_parse_payload(expr, iter, family, cs);
1761384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "meta") == 0) {
17620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			nft_parse_meta(expr, iter, family, cs);
1763384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
17640391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			nft_parse_immediate(expr, iter, family, cs);
1765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1766384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1769384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1770384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
1771384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1772384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1773384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int matches_howmany(struct xtables_rule_match *matches)
1774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1775384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
1776384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int matches_ctr = 0;
1777384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1778384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (matchp = matches; matchp; matchp = matchp->next)
1779384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		matches_ctr++;
1780384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1781384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return matches_ctr;
1782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1783384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1784384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
1785384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__find_match(struct nft_rule_expr *expr, struct xtables_rule_match *matches)
1786384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1787384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *matchname = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
1788384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Netlink aligns this match info, don't trust this length variable */
1789384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *data = nft_rule_expr_get_str(expr, NFT_EXPR_MT_INFO);
1790384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
1791384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool found = false;
1792384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1793384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (matchp = matches; matchp; matchp = matchp->next) {
1794384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct xt_entry_match *m = matchp->match->m;
1795384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1796384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(m->u.user.name, matchname) != 0) {
1797384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("mismatching match name\n");
1798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			continue;
1799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1800384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (memcmp(data, m->data, m->u.user.match_size - sizeof(*m)) != 0) {
1802384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("mismatch match data\n");
1803384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			continue;
1804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		found = true;
1806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return found;
1810384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1811384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1812384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool find_matches(struct xtables_rule_match *matches, struct nft_rule *r)
1813384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1814384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1815384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
1816384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int kernel_matches = 0;
1817384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1818384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1819b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1820384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1821384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1822384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1823384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1824384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1825384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1826384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1827384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "match") == 0) {
1828384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!__find_match(expr, matches))
1829384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
1830384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			kernel_matches++;
1832384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1833384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1834384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
1836384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1837384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* same number of matches? */
1838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (matches_howmany(matches) != kernel_matches)
1839384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
1842384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1843384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1844384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool __find_target(struct nft_rule_expr *expr, struct xt_entry_target *t)
1845384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1846384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
1847384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *tgname = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
1848384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Netlink aligns this target info, don't trust this length variable */
1849384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *data = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len);
1850384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1851384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(t->u.user.name, tgname) != 0) {
1852384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("mismatching target name\n");
1853384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1854384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1855384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1856384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (memcmp(data, t->data,  t->u.user.target_size - sizeof(*t)) != 0)
1857384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1858384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1859384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
1860384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1861384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1862384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int targets_howmany(struct xtables_target *target)
1863384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1864384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return target != NULL ? 1 : 0;
1865384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1866384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1867384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
1868384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusofind_target(struct xtables_target *target, struct nft_rule *r)
1869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1871384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
1872384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int kernel_targets = 0;
1873384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Special case: we use native immediate expressions to emulated
1875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 * standard targets. Also, we don't want to crash with no targets.
1876384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 */
1877384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target == NULL || strcmp(target->name, "standard") == 0)
1878384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return true;
1879384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1880384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1881b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1882384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1883384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1884384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1885384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1886384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1887384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1888384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1889384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "target") == 0) {
1890384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* we may support several targets in the future */
1891384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!__find_target(expr, target->t))
1892384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
1893384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1894384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			kernel_targets++;
1895384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1896384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1897384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1898384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
1899384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1900384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* same number of targets? */
1901384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (targets_howmany(target) != kernel_targets) {
1902384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("kernel targets is %d but we passed %d\n",
1903384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		kernel_targets, targets_howmany(target));
1904384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1905384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1906384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
1908384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
1911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusofind_immediate(struct nft_rule *r, const char *jumpto)
1912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
1915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1917b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "immediate") == 0) {
1926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			int verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
1927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			const char *verdict_name = NULL;
1928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* No target specified but immediate shows up, this
1930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 * is not the rule we are looking for.
1931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 */
1932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (strlen(jumpto) == 0)
1933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
1934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			switch(verdict) {
1936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_ACCEPT:
1937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "ACCEPT";
1938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
1939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_DROP:
1940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "DROP";
1941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
1942384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_RETURN:
1943384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "RETURN";
1944384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
1945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
1946384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Standard target? */
1948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (verdict_name && strcmp(jumpto, verdict_name) != 0)
1949384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
1950384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
1954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
1956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_del(struct nft_handle *h, struct nft_rule *r)
1960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
19650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, h->family,
1966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
1968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_print_debug(r, nlh);
1970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_del");
1974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
19763aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic struct nft_rule_list *nft_rule_list_create(struct nft_handle *h)
1977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1978b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	return nft_rule_list_get(h);
19793aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso}
19803aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
19813aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic void nft_rule_list_destroy(struct nft_rule_list *list)
19823aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso{
19833aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_free(list);
19843aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso}
19853aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
19863aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic struct nft_rule *
19873aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusonft_rule_find(struct nft_rule_list *list, const char *chain, const char *table,
19883aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	      struct iptables_command_state *cs, int rulenum)
19893aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso{
19903aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
19913aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list_iter *iter;
19923aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int rule_ctr = 0;
19933aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	bool found = false;
19943aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
1995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
1996b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
1997384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1998384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
2000384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
2001384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
2002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
2003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
2004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
2005077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka		const struct nft_family_ops *ops = nft_family_ops_lookup(
2006077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka				nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY));
2007384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct iptables_command_state this = {};
2008384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2009384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
2010384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0) {
2011384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different chain / table\n");
2012384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2013384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2014384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2015384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (rulenum >= 0) {
2016384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Delete by rule number case */
20174acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			if (rule_ctr != rulenum)
2018384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
20194acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			found = true;
20204acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			break;
2021384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2022384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Delete by matching rule case */
2023384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("comparing with... ");
2024384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef DEBUG_DEL
20251ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso			nft_rule_print_save(r, NFT_RULE_APPEND, 0);
2026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
2027384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2028384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_to_iptables_command_state(r, &this);
2029384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2030077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka			if (!ops->is_same(cs, &this))
2031384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2032384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2033384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_matches(cs->matches, r)) {
2034384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("matches not found\n");
2035384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2036384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2037384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2038384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_target(cs->target, r)) {
2039384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("target not found\n");
2040384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2041384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2042384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2043384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_immediate(r, cs->jumpto)) {
2044384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("immediate not found\n");
2045384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2046384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2047384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2048384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			found = true;
2049384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
2050384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2051384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
20524acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka		rule_ctr++;
2053384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
2054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_iter_destroy(iter);
2057384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
20583aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return found ? r : NULL;
2059384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2060384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2061384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_check(struct nft_handle *h, const char *chain,
2062384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   const char *table, struct iptables_command_state *e,
2063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   bool verbose)
2064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
20653aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
20663aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret;
20673aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_check;
2069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
20703aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
2071b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
20723aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
20733aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
20743aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	ret = nft_rule_find(list, chain, table, e, -1) ? 1 : 0;
20753aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (ret == 0)
20763aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
20773aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
20783aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
20793aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
20803aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2081384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2082384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete(struct nft_handle *h, const char *chain,
20843aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		    const char *table, struct iptables_command_state *cs,
2085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    bool verbose)
2086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
20873aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
20883aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
20893aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
20903aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2091384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete;
2092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
20933aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
2094b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
20953aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
20963aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
20973aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	r = nft_rule_find(list, chain, table, cs, -1);
20983aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
20993aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		ret = 1;
21003aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21019e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (h->commit) {
21029e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
21039e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso						 NFT_RULE_F_COMMIT);
21049e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		}
21053aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("deleting rule\n");
21063aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		__nft_rule_del(h, r);
21073aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
21083aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
21093aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21103aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
21113aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21123aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2114384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2115384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete_num(struct nft_handle *h, const char *chain,
21163aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso			const char *table, int rulenum, bool verbose)
2117384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
21183aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
21193aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
21203aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
21213aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2122384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete_num;
2123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
21243aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
2125b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
21263aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
21273aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21283aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	r = nft_rule_find(list, chain, table, NULL, rulenum);
21293aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
21303aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		ret = 1;
21313aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21329e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (h->commit) {
21339e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
21349e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso						 NFT_RULE_F_COMMIT);
21359e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		}
21363aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("deleting rule by number %d\n", rulenum);
21373aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		__nft_rule_del(h, r);
21383aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
21393aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
21403aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21413aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
21423aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21433aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2146384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_replace(struct nft_handle *h, const char *chain,
2147384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		     const char *table, struct iptables_command_state *cs,
2148384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		     int rulenum, bool verbose)
2149384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
21503aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
21513aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
21523aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
2153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_replace;
2155384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
21563aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
2157b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
21583aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
21593aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21603aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	r = nft_rule_find(list, chain, table, cs, rulenum);
21613aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
21621298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso		DEBUGP("replacing rule with handle=%llu\n",
21631298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso			(unsigned long long)
21641298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso			nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE));
2165384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
21669e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (h->commit) {
21679e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
21689e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso						 NFT_RULE_F_COMMIT);
21699e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		}
21703aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		ret = nft_rule_add(h, chain, table, cs, true,
21711298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso				   nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE),
21723aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso				   verbose);
21733aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
21743aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
21753aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21763aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
21773aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
21783aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2182384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_header(unsigned int format, const char *chain, const char *pol,
2183384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	     const struct xt_counters *counters, bool basechain, uint32_t refs)
2184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("Chain %s", chain);
2186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (basechain) {
2187384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(" (policy %s", pol);
2188384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (!(format & FMT_NOCOUNTS)) {
2189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputc(' ', stdout);
2190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_num(counters->pcnt, (format|FMT_NOTABLE));
2191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("packets, ", stdout);
2192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_num(counters->bcnt, (format|FMT_NOTABLE));
2193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("bytes", stdout);
2194384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2195384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(")\n");
2196384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else {
2197384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(" (%u references)\n", refs);
2198384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2199384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2200384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_LINENUMBERS)
2201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-4s ", "%s "), "num");
2202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOCOUNTS)) {
2203384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (format & FMT_KILOMEGAGIGA) {
2204384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5s ","%s "), "pkts");
2205384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5s ","%s "), "bytes");
2206384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2207384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%8s ","%s "), "pkts");
2208384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%10s ","%s "), "bytes");
2209384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2210384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOTARGET))
2212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-9s ","%s "), "target");
2213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	fputs(" prot ", stdout);
2214384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_OPTIONS)
2215384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputs("opt", stdout);
2216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_VIA) {
2217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT(" %-6s ","%s "), "in");
2218384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-6s ","%s "), "out");
2219384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2220384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(FMT(" %-19s ","%s "), "source");
2221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(FMT(" %-19s "," %s "), "destination");
2222384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("\n");
2223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2225384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_match(struct nft_rule_expr *expr, int numeric)
2227384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
2229384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *match_name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
2230384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *match_info = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len);
2231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_match *match =
2232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		xtables_find_match(match_name, XTF_TRY_LOAD, NULL);
2233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_match *m =
2234384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		calloc(1, sizeof(struct xt_entry_match) + len);
2235384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2236384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* emulate struct xt_entry_match since ->print needs it */
2237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy((void *)&m->data, match_info, len);
2238384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match) {
2240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (match->print)
2241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* FIXME missing first parameter */
2242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			match->print(NULL, m, numeric);
2243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
2244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("%s ", match_name);
2245384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else {
2246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (match_name[0])
2247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("UNKNOWN match `%s' ", match_name);
2248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(m);
2251384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_firewall(const struct iptables_command_state *cs, struct nft_rule *r,
2255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	       unsigned int num, unsigned int format)
2256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_target *target = NULL;
2258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *targname = NULL;
2259384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *targinfo = NULL;
22600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	int family;
2261077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	struct nft_family_ops *ops;
22620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint8_t flags = 0;
2263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
2264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
2265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_target *t;
2266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t target_len = 0;
2267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
2269b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
2273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
2274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
2275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
2276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "target") == 0) {
22780391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			targname = nft_rule_expr_get_str(expr,
22790391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka							 NFT_EXPR_TG_NAME);
22800391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			targinfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO,
22810391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka						     &target_len);
2282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
2283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
2284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			uint32_t verdict =
2285384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
2286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			switch(verdict) {
2288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_ACCEPT:
2289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "ACCEPT";
2290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_DROP:
2292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "DROP";
2293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_RETURN:
2295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "RETURN";
2296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_GOTO:
22980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				targname = nft_rule_expr_get_str(expr,
22990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka							NFT_EXPR_IMM_CHAIN);
2300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_JUMP:
23020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				targname = nft_rule_expr_get_str(expr,
23030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka							NFT_EXPR_IMM_CHAIN);
2304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
2305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2307384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2308384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
23110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
2312077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	ops = nft_family_ops_lookup(family);
23130391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
2314077785df023ad8947d44d19769bc6d91e3917633Tomasz Bursztyka	flags = ops->print_firewall(cs, targname, num, format);
2315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_NOTABLE)
2317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputs("  ", stdout);
2318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef IPT_F_GOTO
23200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if(flags & IPT_F_GOTO)
2321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("[goto] ");
2322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
2323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
2325b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2328384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
2329384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
2330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
2331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
2332384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2333384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "match") == 0)
2334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_match(expr, format & FMT_NUMERIC);
2335384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2336384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2337384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2339384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2340384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = calloc(1, sizeof(struct xt_entry_target) + target_len);
2341384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (t == NULL)
2342384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2343384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2344384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* emulate struct xt_entry_match since ->print needs it */
2345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy((void *)&t->data, targinfo, target_len);
2346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2347384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (targname) {
2348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		target = xtables_find_target(targname, XTF_TRY_LOAD);
2349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (target) {
2350384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (target->print)
2351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				/* FIXME missing first parameter */
2352384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				target->print(NULL, t, format & FMT_NUMERIC);
2353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else
2354384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("[%ld bytes of unknown target data] ",
2355384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				target_len);
2356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(t);
2358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NONEWLINE))
2360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputc('\n', stdout);
2361384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
2364384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_list(struct nft_handle *h, struct nft_chain *c, const char *table,
2365384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int rulenum, unsigned int format,
2366384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		void (*cb)(const struct iptables_command_state *cs,
2367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			   struct nft_rule *r, unsigned int num,
2368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			   unsigned int format))
2369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
2371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list_iter *iter;
2372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
2373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int rule_ctr = 0, ret = 0;
2374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
2377b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (list == NULL)
2378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
2381b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2382b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
2385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
2386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
2387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
2388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
2389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
2390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		rule_ctr++;
2392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
2394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0)
2395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
23970b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		if (rulenum > 0 && rule_ctr != rulenum) {
2398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* List by rule number case */
23990b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			goto next;
24000b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		}
2401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
24020b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		struct iptables_command_state cs = {};
24030b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		/* Show all rules case */
24040b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		nft_rule_to_iptables_command_state(r, &cs);
24050b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo
24060b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		cb(&cs, r, rule_ctr, format);
24070b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		if (rulenum > 0 && rule_ctr == rulenum) {
24080b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			ret = 1;
24090b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			break;
2410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
24110b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo
2412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
2414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_iter_destroy(iter);
2417b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
2418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_free(list);
2419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == 0)
2421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
2422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
2424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
2427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  int rulenum, unsigned int format)
2428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
2430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
24320a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo	bool found = false;
2433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2434aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka	/* If built-in chains don't exist for this table, create them */
2435aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka	if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0)
2436aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka		nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
2437aa1601423175c90c37c3e6a3d6975d3e2eb74d1eTomasz Bursztyka
2438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
2439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2441b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2442b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
2451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
2452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t refs =
2453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_USE);
2454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct xt_counters ctrs = {
2455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			.pcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS),
2456384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			.bcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES),
2457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		};
2458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
2459384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM))
2461384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			basechain = true;
2462384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2463384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2464384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2465384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
2466384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2467384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
24680a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		if (found)
24690a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo			printf("\n");
24700a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
24710b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		if (!rulenum) {
24720b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo			print_header(format, chain_name, policy_name[policy],
24730b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo				     &ctrs, basechain, refs);
24740b3bafcedff19b69ff5a51855da28e8e83c05b71Giuseppe Longo		}
247506fc595fa99ab0036d87b259b0d20e4916522969Pablo Neira Ayuso		__nft_rule_list(h, c, table, rulenum, format, print_firewall);
24760a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
24770a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo		found = true;
24780a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo
2479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
248334c59adfae98515468ec50c644c30115fee0b97eGiuseppe Longo	nft_chain_list_iter_destroy(iter);
2484b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
2485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
2486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusolist_save(const struct iptables_command_state *cs, struct nft_rule *r,
2492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  unsigned int num, unsigned int format)
2493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
24941ff21a68502d67e056100da7e0da074467bc08edPablo Neira Ayuso	nft_rule_print_save(r, NFT_RULE_APPEND, !(format & FMT_NOCOUNTS));
2495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
2498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_list_chain_save(struct nft_handle *h, const char *table,
2499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 struct nft_chain_list *list, int counters)
2500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
2503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2505b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
2515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
2516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* this is a base chain */
2521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM)) {
2522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-P %s %s", chain_name, policy_name[policy]);
2523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (counters) {
25250a5f6c302f2f596f6e6aa0241a7772cf441b026fGiuseppe Longo				printf(" -c %"PRIu64" %"PRIu64"\n",
2526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS),
2527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES));
2528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			} else
2529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				printf("\n");
2530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-N %s\n", chain_name);
2532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list_save(struct nft_handle *h, const char *chain,
2541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       const char *table, int rulenum, int counters)
2542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
2544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
2546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
2548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Dump policies and custom chains first */
2550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_chain_save(h, table, list, counters);
2551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Now dump out rules in this table */
2553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2554b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2555b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
2567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		__nft_rule_list(h, c, table, rulenum,
2570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				counters ? 0 : FMT_NOCOUNTS, list_save);
2571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2574b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayusoerr:
2575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
2576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
25809e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusostatic int nft_action(struct nft_handle *h, int type)
25819e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
25829e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
25839e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	struct nlmsghdr *nlh;
25849e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	uint32_t seq;
25859e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	int ret;
25869e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
25879e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh = mnl_nlmsg_put_header(buf);
25889e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh->nlmsg_type = (NFNL_SUBSYS_NFTABLES<< 8) | type;
25899e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
25909e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh->nlmsg_seq = seq = time(NULL);
25919e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
25929e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
25933f7877e6be987bb94897c03a45945725389a6f5cPablo Neira Ayuso	nfg->nfgen_family = h->family;
25949e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nfg->version = NFNETLINK_V0;
25959e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nfg->res_id = 0;
25969e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
25979e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
25989e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	if (ret < 0) {
25999e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (errno != EEXIST)
26009e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			perror("mnl-talk:nft_commit");
26019e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	}
2602f041efe3c26e3059df1ac8f1775f77423d4be5f6Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
26039e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
26049e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
26059e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_commit(struct nft_handle *h)
26069e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
26079e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	return nft_action(h, NFT_MSG_COMMIT);
26089e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
26099e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
26109e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_abort(struct nft_handle *h)
26119e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
26129e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	return nft_action(h, NFT_MSG_ABORT);
26139e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
26149e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
2615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_compatible_revision(const char *name, uint8_t rev, int opt)
2616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct mnl_socket *nl;
2618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
2619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
2620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t portid, seq, type;
2621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
2622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (opt == IPT_SO_GET_REVISION_MATCH)
2624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 0;
2625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
2626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 1;
2627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = mnl_nlmsg_put_header(buf);
2629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_type = (NFNL_SUBSYS_NFT_COMPAT << 8) | NFNL_MSG_COMPAT_GET;
2630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
2631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_seq = seq = time(NULL);
2632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
2634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->nfgen_family = AF_INET;
2635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->version = NFNETLINK_V0;
2636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->res_id = 0;
2637384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_strz(nlh, NFTA_COMPAT_NAME, name);
2639384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_REV, htonl(rev));
2640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_TYPE, htonl(type));
2641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	DEBUGP("requesting `%s' rev=%d type=%d via nft_compat\n",
2643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		name, rev, type);
2644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nl = mnl_socket_open(NETLINK_NETFILTER);
2646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nl == NULL) {
2647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_open");
2648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
2652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_bind");
2653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	portid = mnl_socket_get_portid(nl);
2656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
2658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_send");
2659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
2663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
2664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_recvfrom");
2665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
2669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
2670384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_cb_run");
2671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
2675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(nl);
2676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret < 0 ? 0 : 1;
2678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/* Translates errno numbers into more human-readable form than strerror. */
2681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoconst char *nft_strerror(int err)
2682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
2684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	static struct table_struct {
2685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		void *fn;
2686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int err;
2687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *message;
2688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} table[] =
2689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  {
2690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, ENOTEMPTY, "Chain is not empty" },
2691384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EINVAL, "Can't delete built-in chain" },
2692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EMLINK,
2693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Can't delete chain with references left" },
2694384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_add, EEXIST, "Chain already exists" },
2695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, E2BIG, "Index of insertion too big" },
2696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_replace, E2BIG, "Index of replacement too big" },
2697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete_num, E2BIG, "Index of deletion too big" },
2698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/*	    { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
2699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, */
2700384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, ELOOP, "Loop found in table" },
2701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, EINVAL, "Target problem" },
2702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    /* ENOENT for DELETE probably means no matching rule */
2703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete, ENOENT,
2704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Bad rule (does a matching rule exist in that chain?)" },
2705384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, ENOENT, "Bad built-in chain name" },
2706384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, EINVAL, "Bad policy name" },
2707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, EPERM, "Permission denied (you must be root)" },
2708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, 0, "Incompatible with this kernel" },
2709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
2710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOSYS, "Will be implemented real soon.  I promise ;)" },
2711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOMEM, "Memory allocation problem" },
2712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOENT, "No chain/target/match by that name" },
2713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  };
2714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
2716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if ((!table[i].fn || table[i].fn == nft_fn)
2717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    && table[i].err == err)
2718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return table[i].message;
2719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return strerror(err);
2722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
27238b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27248b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayusostatic void xtables_config_perror(uint32_t flags, const char *fmt, ...)
27258b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso{
27268b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_list args;
27278b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27288b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_start(args, fmt);
27298b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27308b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (flags & NFT_LOAD_VERBOSE)
27318b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		vfprintf(stderr, fmt, args);
27328b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27338b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	va_end(args);
27348b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso}
27358b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27368b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayusoint nft_xtables_config_load(struct nft_handle *h, const char *filename,
27378b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			    uint32_t flags)
27388b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso{
27398b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_table_list *table_list = nft_table_list_alloc();
27408b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_chain_list *chain_list = nft_chain_list_alloc();
27418b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_table_list_iter *titer;
27428b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_chain_list_iter *citer;
27438b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_table *table;
27448b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	struct nft_chain *chain;
27458b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27468b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	if (xtables_config_parse(filename, table_list, chain_list) < 0) {
27478b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		if (errno == ENOENT) {
27488b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			xtables_config_perror(flags,
27498b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				"configuration file `%s' does not exists\n",
27508b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				filename);
27518b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		} else {
27528b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			xtables_config_perror(flags,
27538b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				"Fatal error parsing config file: %s\n",
27548b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				 strerror(errno));
27558b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
27568b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		return -1;
27578b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
27588b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27598b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	/* Stage 1) create tables */
27608b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	titer = nft_table_list_iter_create(table_list);
27618b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	while ((table = nft_table_list_iter_next(titer)) != NULL) {
27628b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		if (nft_table_add(h, table) < 0) {
27638b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			if (errno == EEXIST) {
27648b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
27658b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"table `%s' already exists, skipping\n",
27668b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_table_attr_get(table, NFT_TABLE_ATTR_NAME));
27678b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			} else {
27688b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
27698b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"table `%s' cannot be create, reason `%s'. Exitting\n",
27708b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_table_attr_get(table, NFT_TABLE_ATTR_NAME),
27718b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					strerror(errno));
27722c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso				nft_table_list_iter_destroy(titer);
27732c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso				nft_table_list_free(table_list);
27748b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				return -1;
27758b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			}
27768b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			continue;
27778b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
27788b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		xtables_config_perror(flags, "table `%s' has been created\n",
27798b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			(char *)nft_table_attr_get(table, NFT_TABLE_ATTR_NAME));
27808b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
27812c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_table_list_iter_destroy(titer);
27822c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_table_list_free(table_list);
27838b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
27848b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	/* Stage 2) create chains */
27858b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	citer = nft_chain_list_iter_create(chain_list);
27868b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	while ((chain = nft_chain_list_iter_next(citer)) != NULL) {
27878b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		if (nft_chain_add(h, chain) < 0) {
27888b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			if (errno == EEXIST) {
27898b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
27908b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"chain `%s' already exists in table `%s', skipping\n",
27918b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_NAME),
27928b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_TABLE));
27938b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			} else {
27948b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				xtables_config_perror(flags,
27958b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					"chain `%s' cannot be create, reason `%s'. Exitting\n",
27968b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_NAME),
27978b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso					strerror(errno));
27982c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso				nft_chain_list_iter_destroy(citer);
27992c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso				nft_chain_list_free(chain_list);
28008b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso				return -1;
28018b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			}
28028b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			continue;
28038b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		}
28048b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso
28058b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso		xtables_config_perror(flags,
28068b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			"chain `%s' in table `%s' has been created\n",
28078b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_NAME),
28088b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso			(char *)nft_chain_attr_get(chain, NFT_CHAIN_ATTR_TABLE));
28098b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	}
28102c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_chain_list_iter_destroy(citer);
28112c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso	nft_chain_list_free(chain_list);
28122c5850147937cd3da104adf654cc7b2d1f0c0a0bPablo Neira Ayuso
28138b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso	return 0;
28148b9ea2e3f8d685a6b940691cabf5e82c96254747Pablo Neira Ayuso}
2815b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2816b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longoint nft_chain_zero_counters(struct nft_handle *h, const char *chain,
2817b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			    const char *table)
2818b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo{
2819b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nft_chain_list *list;
2820b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nft_chain_list_iter *iter;
2821b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nft_chain *c;
2822b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	struct nlmsghdr *nlh;
2823b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	char buf[MNL_SOCKET_BUFFER_SIZE];
2824b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	int ret = 0;
2825b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2826b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	list = nft_chain_list_get(h);
2827b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	if (list == NULL)
2828b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		goto err;
2829b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2830b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	iter = nft_chain_list_iter_create(list);
2831b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso	if (iter == NULL)
2832b6d90619891e9a2f804af6af9860da8f95878abfPablo Neira Ayuso		goto err;
2833b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2834b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	c = nft_chain_list_iter_next(iter);
2835b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	while (c != NULL) {
2836b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		const char *chain_name =
2837b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			nft_chain_attr_get(c, NFT_CHAIN_ATTR_NAME);
2838b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		const char *chain_table =
2839b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			nft_chain_attr_get(c, NFT_CHAIN_ATTR_TABLE);
2840b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2841b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		if (strcmp(table, chain_table) != 0)
2842b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			goto next;
2843b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2844b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		if (chain != NULL && strcmp(chain, chain_name) != 0)
2845b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			goto next;
2846b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2847b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_PACKETS, 0);
2848b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES, 0);
2849b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2850b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_attr_unset(c, NFT_CHAIN_ATTR_HANDLE);
2851b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2852b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN,
2853b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo						h->family, NLM_F_ACK, h->seq);
2854b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2855b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		nft_chain_nlmsg_build_payload(nlh, c);
2856b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2857b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		ret = mnl_talk(h, nlh, NULL, NULL);
2858b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		if (ret < 0)
2859b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo			perror("mnl_talk:nft_chain_zero_counters");
2860b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
286136ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo		if (chain != NULL)
286236ca9bdb288f7ba528307b7695ab94f7fa8e9a2dGiuseppe Longo			break;
2863b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longonext:
2864b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo		c = nft_chain_list_iter_next(iter);
2865b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	}
2866b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2867b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	nft_chain_list_iter_destroy(iter);
2868b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2869b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longoerr:
2870b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	nft_chain_list_free(list);
2871b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2872b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	/* the core expects 1 for success and 0 for error */
2873b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo	return ret == 0 ? 1 : 0;
2874b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo}
2875b48126ca92cc44e88aa024e6da7ff245914d6a53Giuseppe Longo
2876