nft.c revision 9e62dc8637f210cdeaed784396fecab9b6e5f043
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#if 0
13384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define DEBUGP(x, args...) fprintf(stdout, x, ## args)
14384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define NLDEBUG
15384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define DEBUG_DEL
16384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#else
17384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define DEBUGP(x, args...)
18384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
19384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
20384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <unistd.h>
21384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <fcntl.h>
22384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <sys/types.h>
23384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <sys/socket.h>
24384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <stdbool.h>
25384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <errno.h>
26384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <netdb.h>	/* getprotobynumber */
27384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <time.h>
28384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
29384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <xtables.h>
30384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libiptc/libxtc.h>
31384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libiptc/xtcshared.h>
32384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
33384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <stdlib.h>
34384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <string.h>
35384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
36384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/x_tables.h>
370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka#include <linux/netfilter_ipv4/ip_tables.h>
380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka#include <linux/netfilter_ipv6/ip6_tables.h>
390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka#include <netinet/ip6.h>
40384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
41384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netlink.h>
42384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nfnetlink.h>
43384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nf_tables.h>
44384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nf_tables_compat.h>
45384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
46384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libmnl/libmnl.h>
47384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/table.h>
48384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/chain.h>
49384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/rule.h>
50384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/expr.h>
51384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
52384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <netinet/in.h>	/* inet_ntoa */
53384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <arpa/inet.h>
54384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
55384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include "nft.h"
56384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include "xshared.h" /* proto_to_name */
57384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
58384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void *nft_fn;
59384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
60384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
61384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    int (*cb)(const struct nlmsghdr *nlh, void *data),
62384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    void *data)
63384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
64384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
65384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
66384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
67384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0) {
68384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_send");
69384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
70384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
71384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
72384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
73384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (ret > 0) {
74384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = mnl_cb_run(buf, ret, h->seq, h->portid, cb, data);
75384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (ret <= 0)
76384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
77384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
78384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
79384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
80384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
81384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
82384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
83384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
84384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
85384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
86384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
87384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FILTER		0
88384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define MANGLE		1
89384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define RAW		2
90384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define SECURITY	3
91890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso#define NAT		4
92890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso#define TABLES_MAX	5
93384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
94e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusostruct builtin_chain {
95e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	const char *name;
96890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	const char *type;
975b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	uint32_t prio;
98e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	uint32_t hook;
99e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso};
100e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
101c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_table {
102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
103e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	struct builtin_chain chains[NF_INET_NUMHOOKS];
104384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} tables[TABLES_MAX] = {
105384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[RAW] = {
106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "raw",
107e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
108e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
109e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "PREROUTING",
110890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1115b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -300,	/* NF_IP_PRI_RAW */
112e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
113e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
114e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
115e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
116890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1175b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -300,	/* NF_IP_PRI_RAW */
118e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
119e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
120e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
121384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
122384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[MANGLE] = {
123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "mangle",
124e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
125e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
126e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "PREROUTING",
127890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1285b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
129e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
130e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
131e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
132e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
133890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1345b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
135e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
136e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
137e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
138e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
139890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1405b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
141e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
142e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
143e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
144e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
145890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "route",
1465b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
147e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
148e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
149e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
150e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "POSTROUTING",
151890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1525b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= -150,	/* NF_IP_PRI_MANGLE */
153e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_POST_ROUTING,
154e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
155e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[FILTER] = {
158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "filter",
159e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
160e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
161e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
162890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1635b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
164e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
165e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
166e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
167e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
168890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1695b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
170e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
171e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
172e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
173e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
174890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1755b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 0,	/* NF_IP_PRI_FILTER */
176e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
177e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
178e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[SECURITY] = {
181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "security",
182e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
183e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
184e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
185890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1865b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
187e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
188e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
189e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
190e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
191890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1925b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
193e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
194e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
195e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
196e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
197890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "filter",
1985b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso				.prio	= 150,	/* NF_IP_PRI_SECURITY */
199e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
200e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		},
202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
203890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	[NAT] = {
204890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		.name	= "nat",
205890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		.chains = {
206890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
207890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "OUTPUT",
208890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
209890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= -100, /* NF_IP_PRI_NAT_DST */
210890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
211890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
212890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
213890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "INPUT",
214890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
215890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= 100, /* NF_IP_PRI_NAT_SRC */
216890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
217890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
218890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
219890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "PREROUTING",
220890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
221890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= -100, /* NF_IP_PRI_NAT_DST */
222890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
223890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
224890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			{
225890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.name	= "POSTROUTING",
226890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.type	= "nat",
227890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.prio	= 100, /* NF_IP_PRI_NAT_SRC */
228890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso				.hook	= NF_INET_POST_ROUTING,
229890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso			},
230890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso		},
231890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	},
232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso};
233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2345705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusostatic int
2355705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusonft_table_builtin_add(struct nft_handle *h, struct builtin_table *_t,
2365705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso			bool dormant)
2375b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso{
2385b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
2395b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	struct nlmsghdr *nlh;
2405b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	struct nft_table *t;
2415b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	int ret;
2425b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
2435b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	t = nft_table_alloc();
2445b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	if (t == NULL)
2455b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso		return -1;
2465b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
2475b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)_t->name);
2485705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (dormant) {
2495705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS,
2505705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso					NFT_TABLE_F_DORMANT);
2515705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	}
2525b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
2530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
2545b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
2555b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
2565b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_table_free(t);
2575b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
2585b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
2595b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	if (ret < 0) {
2605b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso		if (errno != EEXIST)
2615b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso			perror("mnl-talk:nft_table_init_one");
2625b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	}
2635b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	return ret;
2645b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso}
2655b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso
266c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct nft_chain *
267c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_alloc(struct builtin_table *table,
268c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			struct builtin_chain *chain, int policy)
269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL)
274c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		return NULL;
275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table->name);
277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain->name);
278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_HOOKNUM, chain->hook);
2795b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_PRIO, chain->prio);
280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy);
281890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TYPE, (char *)chain->type);
282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
283c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return c;
284c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
285c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
286c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic void
287c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table,
288c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		      struct builtin_chain *chain, int policy)
289c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
290c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
291c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct nlmsghdr *nlh;
292c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct nft_chain *c;
293c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
294c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	c = nft_chain_builtin_alloc(table, chain, policy);
295c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (c == NULL)
296c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		return;
297c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
298890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso	/* NLM_F_CREATE requests module autoloading */
2990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
300890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE,
301890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso					h->seq);
302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_talk(h, nlh, NULL, NULL) < 0) {
306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
307c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			perror("mnl_talk:nft_chain_builtin_add");
308c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
309c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
310c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
311c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in table already exists */
312c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_table *nft_table_builtin_find(const char *table)
313c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
314c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	int i;
315c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	bool found = false;
316c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
317c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	for (i=0; i<TABLES_MAX; i++) {
318c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		if (strcmp(tables[i].name, table) != 0)
319c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			continue;
320c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
321c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		found = true;
322c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		break;
323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
324c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
325c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return found ? &tables[i] : NULL;
326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
328c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in chain already exists */
329c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_chain *
330e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusonft_chain_builtin_find(struct builtin_table *t, const char *chain)
331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
332e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int i;
333c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	bool found = false;
334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
335e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	for (i=0; i<NF_IP_NUMHOOKS && t->chains[i].name != NULL; i++) {
336e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (strcmp(t->chains[i].name, chain) != 0)
337e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			continue;
338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
339e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		found = true;
340e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		break;
341e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	}
342e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	return found ? &t->chains[i] : NULL;
343e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso}
344e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
345e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusostatic void
346e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso__nft_chain_builtin_init(struct nft_handle *h,
347e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			 struct builtin_table *table, const char *chain,
348e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			 int policy)
349e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso{
350e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int i, default_policy;
351e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
352e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* Initialize all built-in chains. Exception, for e one received as
353e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	 * parameter, set the default policy as requested.
354e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	 */
355e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	for (i=0; i<NF_IP_NUMHOOKS && table->chains[i].name != NULL; i++) {
356e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (chain && strcmp(table->chains[i].name, chain) == 0)
357e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			default_policy = policy;
358e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		else
359e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			default_policy = NF_ACCEPT;
360e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
361e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		nft_chain_builtin_add(h, table, &table->chains[i],
362e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso					default_policy);
363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
364c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
365c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
366c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic int
367c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_init(struct nft_handle *h, const char *table,
368c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		       const char *chain, int policy)
369c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
370c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	int ret = 0;
371c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_table *t;
372c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
373c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	t = nft_table_builtin_find(table);
374c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (t == NULL) {
375c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		ret = -1;
376c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		goto out;
377c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
3785705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (nft_table_builtin_add(h, t, false) < 0) {
379e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		/* Built-in table already initialized, skip. */
380e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (errno == EEXIST)
381e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			goto out;
382c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
383e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	__nft_chain_builtin_init(h, t, chain, policy);
384c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusoout:
385c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return ret;
386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_init(struct nft_handle *h)
389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->nl = mnl_socket_open(NETLINK_NETFILTER);
391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (h->nl == NULL) {
392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_open");
393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_bind");
398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->portid = mnl_socket_get_portid(h->nl);
401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusovoid nft_fini(struct nft_handle *h)
406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(h->nl);
408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_table_add(struct nft_handle *h, const struct nft_table *t)
411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
4150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_add(struct nft_handle *h, const struct nft_chain *c)
423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
4270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
4345705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoint nft_table_set_dormant(struct nft_handle *h, const char *table)
4355705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso{
4365705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	int ret = 0, i;
4375705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct builtin_table *t;
4385705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4395705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	t = nft_table_builtin_find(table);
4405705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (t == NULL) {
4415705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		ret = -1;
4425705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		goto out;
4435705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	}
4445705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	/* Add this table as dormant */
4455705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (nft_table_builtin_add(h, t, true) < 0) {
4465705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		/* Built-in table already initialized, skip. */
4475705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		if (errno == EEXIST)
4485705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso			goto out;
4495705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	}
4505705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	for (i=0; t->chains[i].name != NULL && i<NF_INET_NUMHOOKS; i++)
4515705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		__nft_chain_builtin_init(h, t, t->chains[i].name, NF_ACCEPT);
4525705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoout:
4535705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	return ret;
4545705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso}
4555705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4565705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoint nft_table_wake_dormant(struct nft_handle *h, const char *table)
4575705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso{
4585705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
4595705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct nlmsghdr *nlh;
4605705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	struct nft_table *t;
4615705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4625705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	t = nft_table_alloc();
4635705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	if (t == NULL)
4645705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		return -1;
4655705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4665705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)table);
4675705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS, 0);
4685705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
4705705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso					NLM_F_ACK, h->seq);
4715705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
4725705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	nft_table_free(t);
4735705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
4745705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
4755705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso}
4765705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso
477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_debug(struct nft_chain *c, struct nlmsghdr *nlh)
478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_snprintf(tmp, sizeof(tmp), c, 0, 0);
483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("DEBUG: chain: %s", tmp);
484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_chain_set(struct nft_handle *h, const char *table,
490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain, int policy,
491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const struct xt_counters *counters)
492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
496c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_table *_t;
497c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_chain *_c;
498e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int ret;
499c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
500c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	_t = nft_table_builtin_find(table);
501c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	/* if this built-in table does not exists, create it */
502c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_t != NULL)
5035705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso		nft_table_builtin_add(h, _t, false);
504c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
505e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	_c = nft_chain_builtin_find(_t, chain);
506c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_c != NULL) {
507c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		/* This is a built-in chain */
508c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		c = nft_chain_builtin_alloc(_t, _c, policy);
509c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		if (c == NULL)
510c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			return -1;
511c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
512c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	} else {
513c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		/* This is a custom chain */
514c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		c = nft_chain_alloc();
515c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		if (c == NULL)
516c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			return -1;
517c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
518c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
519c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain);
520c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy);
521c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (counters) {
524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES,
525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->bcnt);
526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_PACKETS,
527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->pcnt);
528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
5300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_print_debug(c, nlh);
535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:__nft_chain_policy");
541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_set(struct nft_handle *h, const char *table,
546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const char *chain, const char *policy,
547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const struct xt_counters *counters)
548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = -1;
550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_chain_set;
552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(policy, "DROP") == 0)
554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_set(h, table, chain, NF_DROP, counters);
555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else if (strcmp(policy, "ACCEPT") == 0)
556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_set(h, table, chain, NF_ACCEPT, counters);
557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void __add_match(struct nft_rule_expr *e, struct xt_entry_match *m)
563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	void *info;
565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_MT_NAME, m->u.user.name, strlen(m->u.user.name));
567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(e, NFT_EXPR_MT_REV, m->u.user.revision);
568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	info = calloc(1, m->u.match_size);
570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (info == NULL)
571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(info, m->data, m->u.match_size);
574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_MT_INFO, info, m->u.match_size - sizeof(*m));
575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_match(struct nft_rule *r, struct xt_entry_match *m)
578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("match");
582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	__add_match(expr, m);
586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void __add_target(struct nft_rule_expr *e, struct xt_entry_target *t)
590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	void *info = NULL;
592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_TG_NAME, t->u.user.name,
594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  strlen(t->u.user.name));
595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(e, NFT_EXPR_TG_REV, t->u.user.revision);
596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (info == NULL) {
598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		info = calloc(1, t->u.target_size);
599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (info == NULL)
600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return;
601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(info, t->data, t->u.target_size);
603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_TG_INFO, info, t->u.target_size - sizeof(*t));
606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_target(struct nft_rule *r, struct xt_entry_target *t)
609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("target");
613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	__add_target(expr, t);
617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_jumpto(struct nft_rule *r, const char *name, int verdict)
621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("immediate");
625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT);
629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict);
630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_str(expr, NFT_EXPR_IMM_CHAIN, (char *)name);
631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_verdict(struct nft_rule *r, int verdict)
635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
637384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("immediate");
639384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT);
643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict);
644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_rule_print_debug(struct nft_rule *r, struct nlmsghdr *nlh)
648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_snprintf(tmp, sizeof(tmp), r, 0, 0);
653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("DEBUG: rule: %s", tmp);
654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_meta(struct nft_rule *r, uint32_t key)
659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("meta");
663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_META_KEY, key);
667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_META_DREG, NFT_REG_1);
668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
670384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_payload(struct nft_rule *r, int offset, int len)
673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("payload");
677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_BASE,
681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				NFT_PAYLOAD_NETWORK_HEADER);
682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_DREG, NFT_REG_1);
683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_OFFSET, offset);
684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_LEN, len);
685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
6892f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso/* bitwise operation is = sreg & mask ^ xor */
6902f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayusostatic void add_bitwise_u16(struct nft_rule *r, int mask, int xor)
6912f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso{
6922f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	struct nft_rule_expr *expr;
6932f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
6942f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	expr = nft_rule_expr_alloc("bitwise");
6952f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	if (expr == NULL)
6962f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		return;
6972f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
6982f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_SREG, NFT_REG_1);
6992f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_DREG, NFT_REG_1);
7002f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_LEN, sizeof(uint16_t));
7012f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	nft_rule_expr_set(expr, NFT_EXPR_BITWISE_MASK, &mask, sizeof(uint16_t));
7022f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	nft_rule_expr_set(expr, NFT_EXPR_BITWISE_XOR, &xor, sizeof(uint16_t));
7032f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
7042f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	nft_rule_add_expr(r, expr);
7052f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso}
7062f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_cmp_ptr(struct nft_rule *r, uint32_t op, void *data, size_t len)
708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("cmp");
712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u8(expr, NFT_EXPR_CMP_SREG, NFT_REG_1);
716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u8(expr, NFT_EXPR_CMP_OP, op);
717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(expr, NFT_EXPR_CMP_DATA, data, len);
718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
7222f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayusostatic void add_cmp_u16(struct nft_rule *r, uint16_t val, uint32_t op)
7232f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso{
7242f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	add_cmp_ptr(r, op, &val, sizeof(val));
7252f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso}
7262f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_cmp_u32(struct nft_rule *r, uint32_t val, uint32_t op)
728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	add_cmp_ptr(r, op, &val, sizeof(val));
730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_counters(struct nft_rule *r, uint64_t packets, uint64_t bytes)
733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("counter");
737384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
738384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_BYTES, packets);
741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_PACKETS, bytes);
742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
7460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void add_iniface(struct nft_rule *r, char *iface, int invflags)
7470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{
7480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	int iface_len;
7490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint32_t op;
7500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
7510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	iface_len = strlen(iface);
7520391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
7530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if (invflags & IPT_INV_VIA_IN)
7540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		op = NFT_CMP_NEQ;
7550391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	else
7560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		op = NFT_CMP_EQ;
7570391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
7580391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if (iface[iface_len - 1] == '+') {
7590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		add_meta(r, NFT_META_IIFNAME);
7600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		add_cmp_ptr(r, op, iface, iface_len - 1);
7610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	} else {
7620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		add_meta(r, NFT_META_IIF);
7630391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		add_cmp_u32(r, if_nametoindex(iface), op);
7640391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	}
7650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
7660391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
7670391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void add_outiface(struct nft_rule *r, char *iface, int invflags)
7680391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{
7690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	int iface_len;
7700391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint32_t op;
7710391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
7720391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	iface_len = strlen(iface);
7730391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
7740391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if (invflags & IPT_INV_VIA_OUT)
7750391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		op = NFT_CMP_NEQ;
7760391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	else
7770391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		op = NFT_CMP_EQ;
7780391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
7790391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if (iface[iface_len - 1] == '+') {
7800391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		add_meta(r, NFT_META_OIFNAME);
7810391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		add_cmp_ptr(r, op, iface, iface_len - 1);
7820391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	} else {
7830391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		add_meta(r, NFT_META_OIF);
7840391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		add_cmp_u32(r, if_nametoindex(iface), op);
7850391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	}
7860391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
7870391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
7880391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void add_addr(struct nft_rule *r, int offset,
7890391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			void *data, size_t len, int invflags)
7900391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{
7910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint32_t op;
7920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
7930391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	add_payload(r, offset, len);
7940391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
7950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if (invflags & IPT_INV_SRCIP || invflags & IPT_INV_DSTIP)
7960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		op = NFT_CMP_NEQ;
7970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	else
7980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		op = NFT_CMP_EQ;
7990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	add_cmp_ptr(r, op, data, len);
8010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
8020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void add_proto(struct nft_rule *r, int offset, size_t len,
8040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		      uint32_t proto, int invflags)
8050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{
8060391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint32_t op;
8070391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	add_payload(r, offset, len);
8090391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8100391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if (invflags & XT_INV_PROTO)
8110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		op = NFT_CMP_NEQ;
8120391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	else
8130391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		op = NFT_CMP_EQ;
8140391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	add_cmp_u32(r, proto, op);
8160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
8170391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
818384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint
819384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_add(struct nft_handle *h, const char *chain, const char *table,
8200a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	     struct iptables_command_state *cs,
8211298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso	     bool append, uint64_t handle, bool verbose)
822384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
823384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
824384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
825384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
826384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
827384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 1;
828384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t op;
829384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int flags = append ? NLM_F_APPEND : 0;
8300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	int ip_flags = 0;
831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
832e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
833c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	nft_chain_builtin_init(h, table, chain, NF_ACCEPT);
834c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_add;
836384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
837384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL) {
839384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
842384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
843384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
844384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
845384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
8460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	switch (h->family) {
8470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET:
8480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (cs->fw.ip.iniface[0] != '\0')
8490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_iniface(r, cs->fw.ip.iniface, cs->fw.ip.invflags);
8500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (cs->fw.ip.outiface[0] != '\0')
8520391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_outiface(r, cs->fw.ip.outiface,
8530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				     cs->fw.ip.invflags);
8540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8550391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (cs->fw.ip.src.s_addr != 0)
8560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_addr(r, offsetof(struct iphdr, saddr),
8570391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				 &cs->fw.ip.src.s_addr, 4,
8580391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				 cs->fw.ip.invflags);
8590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (cs->fw.ip.dst.s_addr != 0)
8610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_addr(r, offsetof(struct iphdr, daddr),
8620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				 &cs->fw.ip.dst.s_addr, 4,
8630391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				 cs->fw.ip.invflags);
8640391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (cs->fw.ip.proto != 0)
8660391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_proto(r, offsetof(struct iphdr, protocol), 1,
8670391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				  cs->fw.ip.proto, cs->fw.ip.invflags);
8680391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (cs->fw.ip.flags & IPT_F_FRAG) {
8700391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_payload(r, offsetof(struct iphdr, frag_off), 2);
8710391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			/* get the 13 bits that contain the fragment offset */
8720391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_bitwise_u16(r, 0x1fff, !0x1fff);
8730391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8740391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			/* if offset is non-zero, this is a fragment */
8750391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			if (cs->fw.ip.invflags & IPT_INV_FRAG)
8760391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				op = NFT_CMP_EQ;
8770391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			else
8780391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				op = NFT_CMP_NEQ;
8790391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
8800391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_cmp_u16(r, 0, op);
881384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
882384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
8830391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		ip_flags = cs->fw.ip.flags;
884384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
8850391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
8860391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET6:
8870391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (cs->fw6.ipv6.iniface[0] != '\0')
8880391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_iniface(r, cs->fw6.ipv6.iniface,
8890391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				    cs->fw6.ipv6.invflags);
890384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
8910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (cs->fw6.ipv6.outiface[0] != '\0')
8920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_outiface(r, cs->fw6.ipv6.outiface,
8930391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				    cs->fw6.ipv6.invflags);
894384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
8950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src))
8960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_addr(r, offsetof(struct ip6_hdr, ip6_src),
8970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				 &cs->fw6.ipv6.src, 16,
8980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				 cs->fw6.ipv6.invflags);
899384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
9000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst))
9010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_addr(r, offsetof(struct ip6_hdr, ip6_dst),
9020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				 &cs->fw6.ipv6.dst, 16,
9030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				 cs->fw6.ipv6.invflags);
9042f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
9050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (cs->fw6.ipv6.proto != 0)
9060391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			add_proto(r, offsetof(struct ip6_hdr, ip6_nxt), 1,
9070391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				  cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags);
9080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
9090391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		ip_flags = cs->fw6.ipv6.flags;
9102f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
9110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
9122f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	}
913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (matchp = cs->matches; matchp; matchp = matchp->next)
915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		add_match(r, matchp->match->m);
916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Counters need to me added before the target, otherwise they are
918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 * increased for each rule because of the way nf_tables works.
919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 */
920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	add_counters(r, cs->counters.pcnt, cs->counters.bcnt);
921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* If no target at all, add nothing (default to continue) */
923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (cs->target != NULL) {
924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* Standard target? */
925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_verdict(r, NF_ACCEPT);
927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_verdict(r, NF_DROP);
929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_verdict(r, NFT_RETURN);
931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_target(r, cs->target->t);
933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else if (strlen(cs->jumpto) > 0) {
934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* Not standard, then it's a go / jump to chain */
9350391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (ip_flags & IPT_F_GOTO)
936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_jumpto(r, cs->jumpto, NFT_GOTO);
937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_jumpto(r, cs->jumpto, NFT_JUMP);
939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* NLM_F_CREATE autoloads the built-in table if it does not exists */
9420a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	flags |= NLM_F_ACK|NLM_F_CREATE;
9430a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka
9440a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	if (handle > 0) {
9450a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka		nft_rule_attr_set(r, NFT_RULE_ATTR_HANDLE, &handle);
9460a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka		flags |= NLM_F_REPLACE;
9470a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	}
9480a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka
9499e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	if (h->commit) {
9509e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
9519e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso				      NFT_RULE_F_COMMIT);
9529e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	}
9530a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE,
9540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				       h->family, flags, h->seq);
9550a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka
956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_print_debug(r, nlh);
959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_add");
965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_match_save(struct nft_rule_expr *expr)
972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_match *match;
975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_match *emu;
976384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *mtinfo;
977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
978384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
979384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
980384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
981384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	match = xtables_find_match(name, XTF_TRY_LOAD, NULL);
982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match == NULL)
983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
985384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mtinfo = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len);
986384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mtinfo == NULL)
987384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
988384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
989384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	emu = calloc(1, sizeof(struct xt_entry_match) + len);
990384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (emu == NULL)
991384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
992384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
993384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(&emu->data, mtinfo, len);
994384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match->alias)
996384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-m %s", match->alias(emu));
997384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
998384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-m %s", match->name);
999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1000384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* FIXME missing parameter */
1001384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	match->save(NULL, emu);
1002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(" ");
1004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1005384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(emu);
1006384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1007384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1008384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_target_save(struct nft_rule_expr *expr)
1009384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1010384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
1011384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_target *target;
1012384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_target *emu;
1013384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *tginfo;
1014384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
1015384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1016384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
1017384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1018384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Standard target not supported, we use native immediate expression */
1019384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "") == 0) {
1020384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("ERROR: standard target seen, should not happen\n");
1021384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1022384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1023384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1024384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	target = xtables_find_target(name, XTF_TRY_LOAD);
1025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target == NULL)
1026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1027384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1028384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	tginfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len);
1029384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (tginfo == NULL)
1030384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1031384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1032384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	emu = calloc(1, sizeof(struct xt_entry_match) + len);
1033384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (emu == NULL)
1034384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1035384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1036384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(emu->data, tginfo, len);
1037384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1038384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target->alias)
1039384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s", target->alias(emu));
1040384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
1041384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s", target->name);
1042384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1043384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* FIXME missing parameter */
1044384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	target->save(NULL, emu);
1045384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1046384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(emu);
1047384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1048384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1049384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_immediate_save(struct nft_rule_expr *expr)
1050384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1051384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t verdict;
1052384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1053384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
1054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(verdict) {
1056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_ACCEPT:
1057384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j ACCEPT");
1058384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1059384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_DROP:
1060384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j DROP");
1061384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1062384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_RETURN:
1063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j RETURN");
1064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_GOTO:
1066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-g %s",
1067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN));
1068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_JUMP:
1070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s",
1071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN));
1072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_print_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
1078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1079384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
1080384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t value;
1081384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
1082384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char ifname[IFNAMSIZ];
1083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *ifname_ptr;
1084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
1085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
1087384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (e == NULL)
1088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
1091384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* meta should be followed by cmp */
1092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "cmp") != 0) {
1093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("skipping no cmp after meta\n");
1094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1095384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1096384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1097384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(key) {
1098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIF:
1099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
1100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if_indextoname(value, ifname);
1101384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
1103384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
1104384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-i %s ", ifname);
1105384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
1107384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -i %s ", ifname);
1108384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1111384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIF:
1112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
1113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if_indextoname(value, ifname);
1114384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1115384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
1116384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
1117384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-o %s ", ifname);
1118384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1119384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
1120384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -o %s ", ifname);
1121384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1122384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1124384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIFNAME:
1125384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
1126384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(ifname, ifname_ptr, len);
1127384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname[len] = '\0';
1128384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1129384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* if this is zero, then assume this is a interface mask */
1130384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (if_nametoindex(ifname) == 0) {
1131384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len] = '+';
1132384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len+1] = '\0';
1133384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1134384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1135384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
1136384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
1137384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-i %s ", ifname);
1138384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1139384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
1140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -i %s ", ifname);
1141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1143384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIFNAME:
1145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
1146384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(ifname, ifname_ptr, len);
1147384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname[len] = '\0';
1148384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1149384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* if this is zero, then assume this is a interface mask */
1150384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (if_nametoindex(ifname) == 0) {
1151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len] = '+';
1152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len+1] = '\0';
1153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1155384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
1156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
1157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-o %s ", ifname);
1158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
1160384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -o %s ", ifname);
1161384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1163384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1164384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	default:
1165384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("unknown meta key %d\n", key);
1166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1169384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1170384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoget_cmp_data(struct nft_rule_expr_iter *iter, void *data, size_t dlen, bool *inv)
1172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *e;
1174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
1175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
1176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t op;
1177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
1179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (e == NULL)
1180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1182384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
1183384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "cmp") != 0) {
1184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("skipping no cmp after meta\n");
1185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1187384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1188384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(data, nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len), dlen);
1189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	op = nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP);
1190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (op == NFT_CMP_NEQ)
1191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		*inv = true;
1192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
1193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		*inv = false;
1194384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1195384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
11962f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayusostatic void get_frag(struct nft_rule_expr_iter *iter, bool *inv)
11972f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso{
11982f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	struct nft_rule_expr *e;
11992f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	const char *name;
12002f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	uint8_t op;
12012f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
12022f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
12032f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	if (e == NULL)
12042f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		return;
12052f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
12062f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	/* we assume correct mask and xor */
12072f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
12082f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	if (strcmp(name, "bitwise") != 0) {
12092f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		DEBUGP("skipping no bitwise after payload\n");
12102f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		return;
12112f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	}
12122f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
12132f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	/* Now check for cmp */
12142f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
12152f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	if (e == NULL)
12162f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		return;
12172f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
12182f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	/* we assume correct data */
12192f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
12202f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	if (strcmp(name, "cmp") != 0) {
12212f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		DEBUGP("skipping no cmp after payload\n");
12222f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		return;
12232f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	}
12242f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
12252f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	op = nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP);
12262f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	if (op == NFT_CMP_EQ)
12272f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		*inv = true;
12282f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	else
12292f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		*inv = false;
12302f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso}
12312f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
12322f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayusostatic void print_frag(bool inv)
12332f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso{
12342f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	if (inv)
12352f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		printf("! -f ");
12362f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	else
12372f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		printf("-f ");
12382f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso}
12392f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso
1240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void print_proto(uint16_t proto, int invert)
1241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct protoent *pent = getprotobynumber(proto);
1243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (invert)
1245384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("! ");
1246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (pent) {
1248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-p %s ", pent->p_name);
1249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1251384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("-p %u ", proto);
1253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic const char *mask_to_str(uint32_t mask)
1256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	static char mask_str[sizeof("255.255.255.255")];
1258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t bits, hmask = ntohl(mask);
1259384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct in_addr mask_addr = {
1260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.s_addr = mask,
1261384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	};
1262384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int i;
1263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mask == 0xFFFFFFFFU) {
1265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		sprintf(mask_str, "32");
1266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return mask_str;
1267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	i    = 32;
1270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bits = 0xFFFFFFFEU;
1271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (--i >= 0 && hmask != bits)
1272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bits <<= 1;
1273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (i >= 0)
1274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		sprintf(mask_str, "%u", i);
1275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
1276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		sprintf(mask_str, "%s", inet_ntoa(mask_addr));
1277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mask_str;
1279384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
12820391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_print_payload_ipv4(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
1283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t offset;
1285384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool inv;
1286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
1288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(offset) {
1290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct in_addr addr;
1291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t proto;
1292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, saddr):
1294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &addr, sizeof(addr), &inv);
1295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (inv)
1296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -s %s/%s ", inet_ntoa(addr),
1297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						mask_to_str(0xffffffff));
1298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
1299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-s %s/%s ", inet_ntoa(addr),
1300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						mask_to_str(0xffffffff));
1301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, daddr):
1303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &addr, sizeof(addr), &inv);
1304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (inv)
1305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -d %s/%s ", inet_ntoa(addr),
1306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						mask_to_str(0xffffffff));
1307384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
1308384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-d %s/%s ", inet_ntoa(addr),
1309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						mask_to_str(0xffffffff));
1310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1311384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, protocol):
1312384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &proto, sizeof(proto), &inv);
1313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		print_proto(proto, inv);
1314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
13152f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	case offsetof(struct iphdr, frag_off):
13162f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		get_frag(iter, &inv);
13172f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		print_frag(inv);
13182f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		break;
1319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	default:
1320384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("unknown payload offset %d\n", offset);
1321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1325384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
13260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_print_payload_ipv6(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
13270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{
13280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint32_t offset;
13290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	bool inv;
13300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
13310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
13320391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
13330391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	switch (offset) {
13340391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	char addr_str[INET6_ADDRSTRLEN];
13350391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	struct in6_addr addr;
13360391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint8_t proto;
13370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case offsetof(struct ip6_hdr, ip6_src):
13380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		get_cmp_data(iter, &addr, sizeof(addr), &inv);
13390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		inet_ntop(AF_INET6, &addr, addr_str, INET6_ADDRSTRLEN);
13400391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
13410391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (inv)
13420391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			printf("! -s %s ", addr_str);
13430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		else
13440391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			printf("-s %s ", addr_str);
13450391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
13460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
13470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case offsetof(struct ip6_hdr, ip6_dst):
13480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		get_cmp_data(iter, &addr, sizeof(addr), &inv);
13490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		inet_ntop(AF_INET6, &addr, addr_str, INET6_ADDRSTRLEN);
13500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
13510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (inv)
13520391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			printf("! -d %s ", addr_str);
13530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		else
13540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			printf("-d %s ", addr_str);
13550391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
13560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
13570391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case offsetof(struct ip6_hdr, ip6_nxt):
13580391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		get_cmp_data(iter, &proto, sizeof(proto), &inv);
13590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		print_proto(proto, inv);
13600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
13610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	default:
13620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		DEBUGP("unknown payload offset %d\n", offset);
13630391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
13640391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	}
13650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
13660391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
13670391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void
1368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_print_counters(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
1369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   bool counters)
1370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (counters) {
1372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-c %lu %lu ",
1373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS),
1374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES));
1375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_rule_print_save(struct nft_rule *r, bool counters)
1379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
1382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
1384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("-A %s ", nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN));
1385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL)
1388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "counter") == 0) {
1396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_print_counters(expr, iter, counters);
1397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "payload") == 0) {
13980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			if (nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY) == AF_INET)
13990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				nft_print_payload_ipv4(expr, iter);
14000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			else
14010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				nft_print_payload_ipv6(expr, iter);
1402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "meta") == 0) {
1403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_print_meta(expr, iter);
1404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "match") == 0) {
1405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_match_save(expr);
1406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "target") == 0) {
1407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_target_save(expr);
1408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
1409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_immediate_save(expr);
1410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("\n");
1416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_chain_list_cb(const struct nlmsghdr *nlh, void *data)
1419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list = data;
1422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
1424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL) {
1425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_chain_nlmsg_parse(nlh, c) < 0) {
1430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1434384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_add(c, list);
1435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1436384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
1439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1441384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1442384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_chain_list *nft_chain_list_get(struct nft_handle *h)
1444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_alloc();
1451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list\n");
1453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
14560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
1457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1459384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_chain_list_cb, list);
1460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1461384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_chain_list_get");
1462384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1463384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1464384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1465384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1466384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostruct nft_chain_list *nft_chain_dump(struct nft_handle *h)
1467384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1468384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return nft_chain_list_get(h);
1469384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1470384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1471384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic const char *policy_name[NF_ACCEPT+1] = {
1472384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_DROP] = "DROP",
1473384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_ACCEPT] = "ACCEPT",
1474384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso};
1475384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_save(struct nft_chain *c, bool basechain)
1477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint64_t pkts = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS);
1480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint64_t bytes = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES);
1481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
1483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (basechain) {
1484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t pol = NF_ACCEPT;
1485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* no default chain policy? don't crash, display accept */
1487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_POLICY))
1488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			pol = nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
1489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(":%s %s [%lu:%lu]\n", chain, policy_name[pol],
1491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					     pkts, bytes);
1492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else
1493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(":%s - [%lu:%lu]\n", chain, pkts, bytes);
1494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_save(struct nft_handle *h, struct nft_chain_list *list,
1497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   const char *table)
1498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1505384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
1511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
1513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
1515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM))
1518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			basechain = true;
1519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_print_save(c, basechain);
1521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_rule_list_cb(const struct nlmsghdr *nlh, void *data)
1531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list = data;
1534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
1536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL) {
1537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_rule_nlmsg_parse(nlh, r) < 0) {
1542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_add(r, list);
1547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
1551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_rule_list *nft_rule_list_get(struct nft_handle *h)
1556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
1560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_alloc();
1563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list\n");
1565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
15680391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
1569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_rule_list_cb, list);
1572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_save");
1574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_rule_list_free(list);
1575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return NULL;
1576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_save(struct nft_handle *h, const char *table, bool counters)
1582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
1584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list_iter *iter;
1585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
1588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot retrieve rule list from kernel\n");
1590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
1594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
1600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
1601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
1602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
1603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0)
1605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_rule_print_save(r, counters);
1608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
1611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_free(list);
1614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
1621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
1627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL)
1628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
1631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
1632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
16339e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	if (h->commit) {
16349e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
16359e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso					 NFT_RULE_F_COMMIT);
16369e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	}
16379e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
1638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Delete all rules in this table + chain */
16390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, h->family,
1640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
1642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
1643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_talk(h, nlh, NULL, NULL) < 0) {
1645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
1646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:__nft_rule_flush");
1647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
1651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_flush;
1658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_get(h);
1660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
1662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1670384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		__nft_rule_flush(h, table_name, chain_name);
1685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1691384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1694384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table)
1698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1700384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1704e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
1705e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
1706e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
1707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
1708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL) {
1709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate chain\n");
1710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
1711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
1714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain);
1715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
17160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
1717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
1718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
1719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
1720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
1724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:nft_chain_add");
1725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1726384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int __nft_chain_del(struct nft_handle *h, struct nft_chain *c)
1732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
17370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, h->family,
1738384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
1740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST && errno != ENOENT)
1744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:__nft_chain_del");
1745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1746384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1747384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1750384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool nft_chain_builtin(struct nft_chain *c)
1751384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1752384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Check if this chain has hook number, in that case is built-in.
1753384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 * Should we better export the flags to user-space via nf_tables?
1754384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 */
1755384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM) != NULL;
1756384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1757384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1758384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table)
1759384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1760384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1761384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1762384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1763384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
1764384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int deleted_ctr = 0;
1765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1766384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_get(h);
1767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1769384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1770384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1771384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1772384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1773384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1775384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1776384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1777384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1778384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1779384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1780384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1781384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1783384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* don't delete built-in chain */
1784384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_builtin(c))
1785384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1786384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1787384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1788384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1789384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1790384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1791384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1792384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1793384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_del(h, c);
1794384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (ret < 0)
1795384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1796384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1797384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		deleted_ctr++;
1798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1800384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1802384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1803384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* chain not found */
1806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0 && deleted_ctr == 0)
1807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
1808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1810384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1811384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1812384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
18130aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusostruct nft_chain *
18140aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonft_chain_list_find(struct nft_handle *h, struct nft_chain_list *list,
18150aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		    const char *table, const char *chain)
18169c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso{
18179c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
18189c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	struct nft_chain *c;
18199c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
18209c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
18219c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	if (iter == NULL) {
18229c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
18239c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return NULL;
18249c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	}
18259c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
18269c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
18279c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	while (c != NULL) {
18289c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		const char *table_name =
18299c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
18309c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		const char *chain_name =
18319c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
18329c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
18339c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
18349c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			goto next;
18359c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
18369c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		if (strcmp(chain, chain_name) != 0)
18379c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso			goto next;
18389c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
18390aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		nft_chain_list_iter_destroy(iter);
18409c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return c;
18419c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayusonext:
18429c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
18439c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	}
18440aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	nft_chain_list_iter_destroy(iter);
18459c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	return NULL;
18469c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso}
18479c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
18480aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusostatic struct nft_chain *
18490aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonft_chain_find(struct nft_handle *h, const char *table, const char *chain)
18500aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{
18510aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain_list *list;
18520aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
18530aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	list = nft_chain_list_get(h);
18540aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	if (list == NULL) {
18550aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		DEBUGP("cannot allocate chain list\n");
18560aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		return NULL;
18570aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	}
18580aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
18590aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	return nft_chain_list_find(h, list, table, chain);
18600aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso}
18610aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
1862384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_rename(struct nft_handle *h,const char *chain,
1863384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  const char *table, const char *newname)
1864384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
18654493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	char buf[MNL_SOCKET_BUFFER_SIZE];
18664493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	struct nlmsghdr *nlh;
18674493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	struct nft_chain *c;
18689c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	uint64_t handle;
1869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
18714493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	/* If built-in chains don't exist for this table, create them */
18724493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
18734493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
18749c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	/* Find the old chain to be renamed */
18759c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	c = nft_chain_find(h, table, chain);
18769c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	if (c == NULL) {
18779c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		errno = ENOENT;
18789c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso		return -1;
18799c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	}
18809c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	handle = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_HANDLE);
18819c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso
18829c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	/* Now prepare the new name for the chain */
18834493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	c = nft_chain_alloc();
18844493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	if (c == NULL) {
18854493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka		DEBUGP("cannot allocate chain\n");
18864493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka		return -1;
18874493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	}
18884493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
18894493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
18909c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)newname);
18919c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso	nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_HANDLE, handle);
1892384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
18930391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
18949c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
18954493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_nlmsg_build_payload(nlh, c);
18964493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	nft_chain_free(c);
18974493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
18984493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	ret = mnl_talk(h, nlh, NULL, NULL);
18994493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	if (ret < 0) {
19004493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka		if (errno != EEXIST)
19014493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka			perror("mnl_talk:nft_chain_rename");
19024493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	}
19034493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka
19044493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	/* the core expects 1 for success and 0 for error */
19054493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka	return ret == 0 ? 1 : 0;
1906384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1908384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_table_list_cb(const struct nlmsghdr *nlh, void *data)
1909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list = data;
1912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_alloc();
1914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (t == NULL) {
1915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_table_nlmsg_parse(nlh, t) < 0) {
1920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_add(t, list);
1925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_free(t);
1929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_table_list *nft_table_list_get(struct nft_handle *h)
1934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_alloc();
1941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1942384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate table list\n");
1943384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1944384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
19460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
1947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1949384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_table_list_cb, list);
1950384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_table_list_get");
1952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusobool nft_table_find(struct nft_handle *h, const char *tablename)
1957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list_iter *iter;
1960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool ret = false;
1962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_get(h);
1964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_table_list_iter_create(list);
1968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_list_iter_next(iter);
1974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
1975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *this_tablename =
1976384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_table_attr_get(t, NFT_TABLE_ATTR_NAME);
1977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1978384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(tablename, this_tablename) == 0)
1979384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return true;
1980384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1981384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		t = nft_table_list_iter_next(iter);
1982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_free(list);
1985384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1986384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1987384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1988384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1989384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1990384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_for_each_table(struct nft_handle *h,
1991384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       int (*func)(struct nft_handle *h, const char *tablename, bool counters),
1992384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       bool counters)
1993384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1994384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 1;
1995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1996384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list_iter *iter;
1997384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1998384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_get(h);
2000384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
2001384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
2002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2005384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_table_list_iter_create(list);
2006384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2007384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2008384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2009384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2010384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2011384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_list_iter_next(iter);
2012384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
2013384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *tablename =
2014384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_table_attr_get(t, NFT_TABLE_ATTR_NAME);
2015384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2016384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		func(h, tablename, counters);
2017384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2018384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		t = nft_table_list_iter_next(iter);
2019384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2020384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2021384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_free(list);
2022384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2023384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
2024384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
2025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
2026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2027384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
20280aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusoint nft_table_purge_chains(struct nft_handle *h, const char *this_table,
20290aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			   struct nft_chain_list *chain_list)
20300aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{
20310aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain_list_iter *iter;
20320aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	struct nft_chain *chain_obj;
20330aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
20340aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	iter = nft_chain_list_iter_create(chain_list);
20350aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	if (iter == NULL) {
20360aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
20370aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		return 0;
20380aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	}
20390aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
20400aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	chain_obj = nft_chain_list_iter_next(iter);
20410aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	while (chain_obj != NULL) {
20420aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		const char *table =
20430aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			nft_chain_attr_get_str(chain_obj, NFT_CHAIN_ATTR_TABLE);
20440aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
20450aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if (strcmp(this_table, table) != 0)
20460aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			goto next;
20470aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
20480aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if (nft_chain_builtin(chain_obj))
20490aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			goto next;
20500aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
20510aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		if ( __nft_chain_del(h, chain_obj) < 0) {
20520aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso			if (errno != EBUSY)
20530aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso				return -1;
20540aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		}
20550aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonext:
20560aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso		chain_obj = nft_chain_list_iter_next(iter);
20570aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	}
20580aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	nft_chain_list_iter_destroy(iter);
20590aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
20600aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso	return 0;
20610aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso}
20620aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso
2063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic inline int
2064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusomatch_different(const struct xt_entry_match *a,
2065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const unsigned char *a_elems,
2066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const unsigned char *b_elems,
2067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		unsigned char **maskptr)
2068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xt_entry_match *b;
2070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
2071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Offset of b is the same as a. */
2073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	b = (void *)b_elems + ((unsigned char *)a - a_elems);
2074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (a->u.match_size != b->u.match_size)
2076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 1;
2077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(a->u.user.name, b->u.user.name) != 0)
2079384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 1;
2080384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2081384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	*maskptr += XT_ALIGN(sizeof(*a));
2082384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < a->u.match_size - XT_ALIGN(sizeof(*a)); i++)
2084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0)
2085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return 1;
2086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	*maskptr += i;
2087384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
2088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
20910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykais_same(int family, const struct iptables_command_state *a,
20920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	const struct iptables_command_state *b)
2093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
20950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	const char *a_outiface, *a_iniface;
20960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	unsigned const char *a_iniface_mask, *a_outiface_mask;
20970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	const char *b_outiface, *b_iniface;
20980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	unsigned const char *b_iniface_mask, *b_outiface_mask;
2099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Always compare head structures: ignore mask here. */
21010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	switch (family) {
21020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET:
21030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (a->fw.ip.src.s_addr != b->fw.ip.src.s_addr
21040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    || a->fw.ip.dst.s_addr != b->fw.ip.dst.s_addr
21050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    || a->fw.ip.smsk.s_addr != b->fw.ip.smsk.s_addr
21060391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    || a->fw.ip.dmsk.s_addr != b->fw.ip.dmsk.s_addr
21070391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    || a->fw.ip.proto != b->fw.ip.proto
21080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    || a->fw.ip.flags != b->fw.ip.flags
21090391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    || a->fw.ip.invflags != b->fw.ip.invflags) {
21100391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			DEBUGP("different src/dst/proto/flags/invflags\n");
21110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			return false;
21120391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		}
21130391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
21140391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		a_iniface_mask = a->fw.ip.iniface_mask;
21150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		a_iniface = a->fw.ip.iniface;
21160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		a_outiface_mask = a->fw.ip.outiface_mask;
21170391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		a_outiface = a->fw.ip.outiface;
21180391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
21190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		b_iniface_mask = b->fw.ip.iniface_mask;
21200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		b_iniface = b->fw.ip.iniface;
21210391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		b_outiface_mask = b->fw.ip.outiface_mask;
21220391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		b_outiface = b->fw.ip.outiface;
21230391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
21240391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
21250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET6:
21260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (memcmp(a->fw6.ipv6.src.s6_addr,
21270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			   b->fw6.ipv6.src.s6_addr,
21280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			   sizeof(struct in6_addr)) != 0	||
21290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    memcmp(a->fw6.ipv6.dst.s6_addr,
21300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			   b->fw6.ipv6.dst.s6_addr,
21310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			   sizeof(struct in6_addr)) != 0	||
21320391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    a->fw6.ipv6.proto != b->fw6.ipv6.proto	||
21330391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    a->fw6.ipv6.flags != b->fw6.ipv6.flags	||
21340391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    a->fw6.ipv6.invflags != b->fw6.ipv6.invflags) {
21350391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			DEBUGP("different src/dst/proto/flags/invflags\n");
21360391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			return false;
21370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		}
21380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
21390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		a_iniface_mask = a->fw6.ipv6.iniface_mask;
21400391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		a_iniface = a->fw6.ipv6.iniface;
21410391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		a_outiface_mask = a->fw6.ipv6.outiface_mask;
21420391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		a_outiface = a->fw6.ipv6.outiface;
21430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
21440391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		b_iniface_mask = b->fw6.ipv6.iniface_mask;
21450391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		b_iniface = b->fw6.ipv6.iniface;
21460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		b_outiface_mask = b->fw6.ipv6.outiface_mask;
21470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		b_outiface = b->fw6.ipv6.outiface;
21480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
21490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
21500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	default:
2151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
2152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < IFNAMSIZ; i++) {
21550391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (a_iniface_mask[i] != b_iniface_mask[i]) {
2156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different iniface mask %x, %x (%d)\n",
21570391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			a_iniface_mask[i] & 0xff, b_iniface_mask[i] & 0xff, i);
2158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return false;
2159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
21600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if ((a_iniface[i] & a_iniface_mask[i])
21610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    != (b_iniface[i] & b_iniface_mask[i])) {
2162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different iniface\n");
2163384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return false;
2164384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
21650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (a_outiface_mask[i] != b_outiface_mask[i]) {
2166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different outiface mask\n");
2167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return false;
2168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
21690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if ((a_outiface[i] & a_outiface_mask[i])
21700391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    != (b_outiface[i] & b_outiface_mask[i])) {
2171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different outiface\n");
2172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return false;
2173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
2177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
21810391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	       int family, struct iptables_command_state *cs)
2182384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2183384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
2184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t value;
2185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
2186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *ifname;
21870391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	char *iniface, *outiface;
21880391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	unsigned char *iniface_mask, *outiface_mask;
2189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
21900391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint8_t *invflags;
2191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
2193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (e == NULL)
2194384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2195384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2196384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
2197384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "cmp") != 0) {
2198384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("skipping no cmp after meta\n");
2199384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2200384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
22020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	switch (family) {
22030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET:
22040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		iniface = cs->fw.ip.iniface;
22050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		outiface = cs->fw.ip.outiface;
22060391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		iniface_mask = cs->fw.ip.iniface_mask;
22070391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		outiface_mask = cs->fw.ip.outiface_mask;
22080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		invflags = &cs->fw.ip.invflags;
22090391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
22100391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET6:
22110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		iniface = cs->fw6.ipv6.iniface;
22120391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		outiface = cs->fw6.ipv6.outiface;
22130391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		iniface_mask = cs->fw6.ipv6.iniface_mask;
22140391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		outiface_mask = cs->fw6.ipv6.outiface_mask;
22150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		invflags = &cs->fw6.ipv6.invflags;
22160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
22170391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	default:
22180391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		return;
22190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	}
22200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
2221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(key) {
2222384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIF:
2223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
2224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
22250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			*invflags |= IPT_INV_VIA_IN;
2226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
22270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if_indextoname(value, iniface);
2228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
22290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		memset(iniface_mask, 0xff, strlen(iniface)+1);
2230384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
2231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIF:
2232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
2233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
22340391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			*invflags |= IPT_INV_VIA_OUT;
2235384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
22360391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if_indextoname(value, outiface);
2237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
22380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		memset(outiface_mask, 0xff, strlen(outiface)+1);
2239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
2240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIFNAME:
2241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
2242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
22430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			*invflags |= IPT_INV_VIA_IN;
2244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
22450391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		memcpy(iniface, ifname, len);
22460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		iniface[len] = '\0';
2247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* If zero, then this is an interface mask */
22490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (if_nametoindex(iniface) == 0) {
22500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			iniface[len] = '+';
22510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			iniface[len+1] = '\0';
2252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
22540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		memset(iniface_mask, 0xff, len);
2255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
2256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIFNAME:
2257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
2258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
22590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			*invflags |= IPT_INV_VIA_OUT;
2260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
22610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		memcpy(outiface, ifname, len);
22620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		outiface[len] = '\0';
2263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* If zero, then this is an interface mask */
22650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (if_nametoindex(outiface) == 0) {
22660391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			outiface[len] = '+';
22670391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			outiface[len+1] = '\0';
2268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
22700391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		memset(outiface_mask, 0xff, len);
2271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
2272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	default:
2273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("unknown meta key %d\n", key);
2274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
2275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
22790391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_parse_payload_ipv4(uint32_t offset, struct nft_rule_expr_iter *iter,
22800391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		       struct iptables_command_state *cs)
2281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(offset) {
2283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct in_addr addr;
2284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t proto;
22850391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	bool inv;
2286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, saddr):
2288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &addr, sizeof(addr), &inv);
2289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.src.s_addr = addr.s_addr;
2290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.smsk.s_addr = 0xffffffff;
2291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (inv)
2292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.invflags |= IPT_INV_SRCIP;
2293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
2294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, daddr):
2295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &addr, sizeof(addr), &inv);
2296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.dst.s_addr = addr.s_addr;
2297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.dmsk.s_addr = 0xffffffff;
2298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (inv)
2299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.invflags |= IPT_INV_DSTIP;
2300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
2301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, protocol):
2302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &proto, sizeof(proto), &inv);
2303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.proto = proto;
2304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (inv)
2305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.invflags |= IPT_INV_PROTO;
2306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
23072f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso	case offsetof(struct iphdr, frag_off):
23082f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		cs->fw.ip.flags |= IPT_F_FRAG;
23092f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		get_frag(iter, &inv);
23102f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		if (inv)
23112f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso			cs->fw.ip.invflags |= IPT_INV_FRAG;
23122f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso		break;
2313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	default:
2314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("unknown payload offset %d\n", offset);
2315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
2316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
23200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_parse_payload_ipv6(uint32_t offset, struct nft_rule_expr_iter *iter,
23210391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		       struct iptables_command_state *cs)
23220391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{
23230391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	switch (offset) {
23240391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	struct in6_addr addr;
23250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint8_t proto;
23260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	bool inv;
23270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
23280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case offsetof(struct ip6_hdr, ip6_src):
23290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		get_cmp_data(iter, &addr, sizeof(addr), &inv);
23300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		memcpy(cs->fw6.ipv6.src.s6_addr, &addr, sizeof(addr));
23310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (inv)
23320391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			cs->fw6.ipv6.invflags |= IPT_INV_SRCIP;
23330391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
23340391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case offsetof(struct ip6_hdr, ip6_dst):
23350391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		get_cmp_data(iter, &addr, sizeof(addr), &inv);
23360391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		memcpy(cs->fw6.ipv6.dst.s6_addr, &addr, sizeof(addr));
23370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (inv)
23380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			cs->fw6.ipv6.invflags |= IPT_INV_DSTIP;
23390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
23400391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case offsetof(struct ip6_hdr, ip6_nxt):
23410391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		get_cmp_data(iter, &proto, sizeof(proto), &inv);
23420391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		cs->fw6.ipv6.proto = proto;
23430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (inv)
23440391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			cs->fw6.ipv6.invflags |= IPT_INV_PROTO;
23450391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	default:
23460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		DEBUGP("unknown payload offset %d\n", offset);
23470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
23480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	}
23490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
23500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
23510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void
23520391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_parse_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
23530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		  int family, struct iptables_command_state *cs)
23540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{
23550391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint32_t offset;
23560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
23570391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
23580391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
23590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	switch (family) {
23600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET:
23610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		nft_parse_payload_ipv4(offset, iter, cs);
23620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
23630391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET6:
23640391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		nft_parse_payload_ipv6(offset, iter, cs);
23650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
23660391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	}
23670391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
23680391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
23690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void
2370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_counter(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
2371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  struct xt_counters *counters)
2372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	counters->pcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS);
2374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	counters->bcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES);
2375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_immediate(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
23790391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		    int family, struct iptables_command_state *cs)
2380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int verdict = nft_rule_expr_get_u32(e, NFT_EXPR_IMM_VERDICT);
2382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_rule_expr_get_str(e, NFT_EXPR_IMM_CHAIN);
2383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Standard target? */
2385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(verdict) {
2386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_ACCEPT:
2387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "ACCEPT";
2388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_DROP:
2390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "DROP";
2391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_RETURN:
2393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "RETURN";
2394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_GOTO:
23960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (family == AF_INET)
23970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			cs->fw.ip.flags |= IPT_F_GOTO;
23980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		else
23990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			cs->fw6.ipv6.flags |= IPT_F_GOTO;
2400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_JUMP:
2401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = chain;
2402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_to_iptables_command_state(struct nft_rule *r,
2408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				   struct iptables_command_state *cs)
2409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
2411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
24120391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	int family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
2413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
2415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL)
2416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
2419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
2420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
2421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
2422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "counter") == 0) {
2424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_parse_counter(expr, iter, &cs->counters);
2425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "payload") == 0) {
24260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			nft_parse_payload(expr, iter, family, cs);
2427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "meta") == 0) {
24280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			nft_parse_meta(expr, iter, family, cs);
2429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
24300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			nft_parse_immediate(expr, iter, family, cs);
2431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2434384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2436384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int matches_howmany(struct xtables_rule_match *matches)
2440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2441384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
2442384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int matches_ctr = 0;
2443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (matchp = matches; matchp; matchp = matchp->next)
2445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		matches_ctr++;
2446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return matches_ctr;
2448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
2451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__find_match(struct nft_rule_expr *expr, struct xtables_rule_match *matches)
2452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *matchname = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
2454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Netlink aligns this match info, don't trust this length variable */
2455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *data = nft_rule_expr_get_str(expr, NFT_EXPR_MT_INFO);
2456384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
2457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool found = false;
2458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2459384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (matchp = matches; matchp; matchp = matchp->next) {
2460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct xt_entry_match *m = matchp->match->m;
2461384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2462384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(m->u.user.name, matchname) != 0) {
2463384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("mismatching match name\n");
2464384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			continue;
2465384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2466384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2467384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (memcmp(data, m->data, m->u.user.match_size - sizeof(*m)) != 0) {
2468384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("mismatch match data\n");
2469384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			continue;
2470384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2471384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		found = true;
2472384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
2473384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2474384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2475384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return found;
2476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool find_matches(struct xtables_rule_match *matches, struct nft_rule *r)
2479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
2481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
2482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int kernel_matches = 0;
2483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
2485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
2488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
2491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
2492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
2493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
2494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "match") == 0) {
2496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!__find_match(expr, matches))
2497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
2498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			kernel_matches++;
2500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2505384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* same number of matches? */
2506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (matches_howmany(matches) != kernel_matches)
2507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
2508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
2510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool __find_target(struct nft_rule_expr *expr, struct xt_entry_target *t)
2513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
2515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *tgname = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
2516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Netlink aligns this target info, don't trust this length variable */
2517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *data = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len);
2518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(t->u.user.name, tgname) != 0) {
2520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("mismatching target name\n");
2521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
2522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (memcmp(data, t->data,  t->u.user.target_size - sizeof(*t)) != 0)
2525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
2526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
2528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int targets_howmany(struct xtables_target *target)
2531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return target != NULL ? 1 : 0;
2533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
2536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusofind_target(struct xtables_target *target, struct nft_rule *r)
2537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
2539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
2540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int kernel_targets = 0;
2541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Special case: we use native immediate expressions to emulated
2543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 * standard targets. Also, we don't want to crash with no targets.
2544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 */
2545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target == NULL || strcmp(target->name, "standard") == 0)
2546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return true;
2547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
2549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
2552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
2555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
2556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
2557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
2558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "target") == 0) {
2560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* we may support several targets in the future */
2561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!__find_target(expr, target->t))
2562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
2563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			kernel_targets++;
2565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* same number of targets? */
2571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (targets_howmany(target) != kernel_targets) {
2572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("kernel targets is %d but we passed %d\n",
2573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		kernel_targets, targets_howmany(target));
2574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
2575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
2578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
2581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusofind_immediate(struct nft_rule *r, const char *jumpto)
2582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
2584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
2585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
2587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
2590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
2593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
2594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
2595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
2596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "immediate") == 0) {
2598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			int verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
2599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			const char *verdict_name = NULL;
2600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* No target specified but immediate shows up, this
2602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 * is not the rule we are looking for.
2603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 */
2604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (strlen(jumpto) == 0)
2605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
2606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			switch(verdict) {
2608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_ACCEPT:
2609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "ACCEPT";
2610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_DROP:
2612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "DROP";
2613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_RETURN:
2615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "RETURN";
2616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Standard target? */
2620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (verdict_name && strcmp(jumpto, verdict_name) != 0)
2621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
2622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
2628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_del(struct nft_handle *h, struct nft_rule *r)
2632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
2634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
2635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
2636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
26370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, h->family,
2638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
2639384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
2640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_print_debug(r, nlh);
2642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
2644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
2645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_del");
2646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
26483aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic struct nft_rule_list *nft_rule_list_create(struct nft_handle *h)
2649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
2651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
2653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
2654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot retrieve rule list from kernel\n");
26553aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return NULL;
2656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
26583aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return list;
26593aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso}
26603aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
26613aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic void nft_rule_list_destroy(struct nft_rule_list *list)
26623aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso{
26633aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_free(list);
26643aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso}
26653aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
26663aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic struct nft_rule *
26673aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusonft_rule_find(struct nft_rule_list *list, const char *chain, const char *table,
26683aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	      struct iptables_command_state *cs, int rulenum)
26693aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso{
26703aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
26713aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list_iter *iter;
26723aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int rule_ctr = 0;
26733aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	bool found = false;
26743aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
2676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
2682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
2683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
2684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
2685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
2686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
2687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct iptables_command_state this = {};
2688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
2690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0) {
2691384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different chain / table\n");
2692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2694384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (rulenum >= 0) {
2696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Delete by rule number case */
26974acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			if (rule_ctr != rulenum)
2698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
26994acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			found = true;
27004acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka			break;
2701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Delete by matching rule case */
2703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("comparing with... ");
2704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef DEBUG_DEL
2705384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_print_save(r, 0);
2706384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
2707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_to_iptables_command_state(r, &this);
2709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
27100391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			if (!is_same(nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY), cs, &this))
2711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_matches(cs->matches, r)) {
2714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("matches not found\n");
2715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_target(cs->target, r)) {
2719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("target not found\n");
2720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_immediate(r, cs->jumpto)) {
2724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("immediate not found\n");
2725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2726384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			found = true;
2729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
2730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
27324acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka		rule_ctr++;
2733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
2734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_iter_destroy(iter);
2737384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
27383aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return found ? r : NULL;
2739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_check(struct nft_handle *h, const char *chain,
2742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   const char *table, struct iptables_command_state *e,
2743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   bool verbose)
2744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
27453aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
27463aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret;
27473aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_check;
2749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
27503aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
27513aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (list == NULL) {
27523aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("cannot allocate rule list\n");
27533aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
27543aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	}
27553aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
27563aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	ret = nft_rule_find(list, chain, table, e, -1) ? 1 : 0;
27573aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (ret == 0)
27583aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
27593aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
27603aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
27613aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
27623aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2763384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2764384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete(struct nft_handle *h, const char *chain,
27663aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		    const char *table, struct iptables_command_state *cs,
2767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    bool verbose)
2768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
27693aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
27703aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
27713aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
27723aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2773384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete;
2774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
27753aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
27763aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (list == NULL) {
27773aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("cannot allocate rule list\n");
27783aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
27793aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	}
27803aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
27813aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	r = nft_rule_find(list, chain, table, cs, -1);
27823aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
27833aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		ret = 1;
27843aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
27859e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (h->commit) {
27869e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
27879e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso						 NFT_RULE_F_COMMIT);
27889e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		}
27893aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("deleting rule\n");
27903aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		__nft_rule_del(h, r);
27913aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
27923aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
27933aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
27943aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
27953aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
27963aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2797384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete_num(struct nft_handle *h, const char *chain,
28003aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso			const char *table, int rulenum, bool verbose)
2801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
28023aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
28033aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
28043aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
28053aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
2806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete_num;
2807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
28083aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
28093aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (list == NULL) {
28103aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("cannot allocate rule list\n");
28113aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
28123aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	}
28133aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
28143aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	r = nft_rule_find(list, chain, table, NULL, rulenum);
28153aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
28163aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		ret = 1;
28173aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
28189e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (h->commit) {
28199e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
28209e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso						 NFT_RULE_F_COMMIT);
28219e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		}
28223aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("deleting rule by number %d\n", rulenum);
28233aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		__nft_rule_del(h, r);
28243aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
28253aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
28263aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
28273aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
28283aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
28293aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2830384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2832384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_replace(struct nft_handle *h, const char *chain,
2833384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		     const char *table, struct iptables_command_state *cs,
2834384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		     int rulenum, bool verbose)
2835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
28363aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	int ret = 0;
28373aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule *r;
28383aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	struct nft_rule_list *list;
2839384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_replace;
2841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
28423aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	list = nft_rule_list_create(h);
28433aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (list == NULL) {
28443aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		DEBUGP("cannot allocate rule list\n");
28453aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		return 0;
28463aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	}
28473aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
28483aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	r = nft_rule_find(list, chain, table, cs, rulenum);
28493aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	if (r != NULL) {
28501298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso		DEBUGP("replacing rule with handle=%llu\n",
28511298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso			(unsigned long long)
28521298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso			nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE));
2853384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
28549e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (h->commit) {
28559e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS,
28569e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso						 NFT_RULE_F_COMMIT);
28579e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		}
28583aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		ret = nft_rule_add(h, chain, table, cs, true,
28591298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso				   nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE),
28603aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso				   verbose);
28613aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	} else
28623aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso		errno = ENOENT;
28633aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
28643aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	nft_rule_list_destroy(list);
28653aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso
28663aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso	return ret;
2867384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2868384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/*
2870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * iptables print output emulation
2871384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso */
2872384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2873384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NUMERIC	0x0001
2874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NOCOUNTS	0x0002
2875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_KILOMEGAGIGA 0x0004
2876384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_OPTIONS	0x0008
2877384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NOTABLE	0x0010
2878384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NOTARGET	0x0020
2879384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_VIA		0x0040
2880384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NONEWLINE	0x0080
2881384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_LINENUMBERS 0x0100
2882384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2883384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
2884384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			| FMT_NUMERIC | FMT_NOTABLE)
2885384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
2886384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2887384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2888384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_num(uint64_t number, unsigned int format)
2889384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2890384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_KILOMEGAGIGA) {
2891384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (number > 99999) {
2892384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			number = (number + 500) / 1000;
2893384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (number > 9999) {
2894384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				number = (number + 500) / 1000;
2895384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				if (number > 9999) {
2896384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					number = (number + 500) / 1000;
2897384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					if (number > 9999) {
2898384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						number = (number + 500) / 1000;
2899384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						printf(FMT("%4lluT ","%lluT "), (unsigned long long)number);
2900384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					}
2901384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					else printf(FMT("%4lluG ","%lluG "), (unsigned long long)number);
2902384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				}
2903384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				else printf(FMT("%4lluM ","%lluM "), (unsigned long long)number);
2904384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			} else
2905384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				printf(FMT("%4lluK ","%lluK "), (unsigned long long)number);
2906384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else
2907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5llu ","%llu "), (unsigned long long)number);
2908384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else
2909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%8llu ","%llu "), (unsigned long long)number);
2910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_header(unsigned int format, const char *chain, const char *pol,
2914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	     const struct xt_counters *counters, bool basechain, uint32_t refs)
2915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("Chain %s", chain);
2917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (basechain) {
2918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(" (policy %s", pol);
2919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (!(format & FMT_NOCOUNTS)) {
2920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputc(' ', stdout);
2921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_num(counters->pcnt, (format|FMT_NOTABLE));
2922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("packets, ", stdout);
2923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_num(counters->bcnt, (format|FMT_NOTABLE));
2924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("bytes", stdout);
2925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(")\n");
2927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else {
2928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(" (%u references)\n", refs);
2929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_LINENUMBERS)
2932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-4s ", "%s "), "num");
2933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOCOUNTS)) {
2934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (format & FMT_KILOMEGAGIGA) {
2935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5s ","%s "), "pkts");
2936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5s ","%s "), "bytes");
2937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%8s ","%s "), "pkts");
2939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%10s ","%s "), "bytes");
2940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2942384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOTARGET))
2943384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-9s ","%s "), "target");
2944384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	fputs(" prot ", stdout);
2945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_OPTIONS)
2946384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputs("opt", stdout);
2947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_VIA) {
2948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT(" %-6s ","%s "), "in");
2949384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-6s ","%s "), "out");
2950384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(FMT(" %-19s ","%s "), "source");
2952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(FMT(" %-19s "," %s "), "destination");
2953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("\n");
2954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_match(struct nft_rule_expr *expr, int numeric)
2958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
2960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *match_name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
2961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *match_info = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len);
2962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_match *match =
2963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		xtables_find_match(match_name, XTF_TRY_LOAD, NULL);
2964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_match *m =
2965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		calloc(1, sizeof(struct xt_entry_match) + len);
2966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* emulate struct xt_entry_match since ->print needs it */
2968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy((void *)&m->data, match_info, len);
2969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match) {
2971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (match->print)
2972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* FIXME missing first parameter */
2973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			match->print(NULL, m, numeric);
2974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
2975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("%s ", match_name);
2976384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else {
2977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (match_name[0])
2978384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("UNKNOWN match `%s' ", match_name);
2979384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2980384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2981384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(m);
2982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
29850391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykaprint_ipv4_addr(const struct iptables_command_state *cs, unsigned int format)
29860391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{
29870391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	char buf[BUFSIZ];
29880391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
29890391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	fputc(cs->fw.ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
29900391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if (cs->fw.ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC))
29910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		printf(FMT("%-19s ","%s "), "anywhere");
29920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	else {
29930391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (format & FMT_NUMERIC)
29940391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.src));
29950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		else
29960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.src));
29970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.smsk));
29980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		printf(FMT("%-19s ","%s "), buf);
29990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	}
30000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
30010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	fputc(cs->fw.ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
30020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if (cs->fw.ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC))
30030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		printf(FMT("%-19s ","-> %s"), "anywhere");
30040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	else {
30050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (format & FMT_NUMERIC)
30060391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.dst));
30070391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		else
30080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.dst));
30090391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.dmsk));
30100391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		printf(FMT("%-19s ","-> %s"), buf);
30110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	}
30120391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
30130391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
30140391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void
30150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykaprint_ipv6_addr(const struct iptables_command_state *cs, unsigned int format)
30160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{
30170391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	char buf[BUFSIZ];
30180391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
30190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	fputc(cs->fw6.ipv6.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
30200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if (IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src)
30210391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	    && !(format & FMT_NUMERIC))
30220391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		printf(FMT("%-19s ","%s "), "anywhere");
30230391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	else {
30240391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (format & FMT_NUMERIC)
30250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			strcpy(buf,
30260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			       xtables_ip6addr_to_numeric(&cs->fw6.ipv6.src));
30270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		else
30280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			strcpy(buf,
30290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			       xtables_ip6addr_to_anyname(&cs->fw6.ipv6.src));
30300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		strcat(buf, xtables_ip6mask_to_numeric(&cs->fw6.ipv6.smsk));
30310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		printf(FMT("%-19s ","%s "), buf);
30320391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	}
30330391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
30340391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
30350391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	fputc(cs->fw6.ipv6.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
30360391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if (IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst)
30370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	    && !(format & FMT_NUMERIC))
30380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		printf(FMT("%-19s ","-> %s"), "anywhere");
30390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	else {
30400391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (format & FMT_NUMERIC)
30410391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			strcpy(buf,
30420391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			       xtables_ip6addr_to_numeric(&cs->fw6.ipv6.dst));
30430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		else
30440391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			strcpy(buf,
30450391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			       xtables_ip6addr_to_anyname(&cs->fw6.ipv6.dst));
30460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		strcat(buf, xtables_ip6mask_to_numeric(&cs->fw6.ipv6.dmsk));
30470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		printf(FMT("%-19s ","-> %s"), buf);
30480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	}
30490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka}
30500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
30510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void
3052384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_firewall(const struct iptables_command_state *cs, struct nft_rule *r,
3053384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	       unsigned int num, unsigned int format)
3054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
3055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_target *target = NULL;
3056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *targname = NULL;
3057384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *targinfo = NULL;
30580391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	int family;
30590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint8_t flags = 0;
30600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint8_t invflags = 0;
30610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	uint8_t proto = 0;
30620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	const char *iniface = NULL, *outiface = NULL;
3063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
3064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
3065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_target *t;
3066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t target_len = 0;
3067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
3069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
3070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
3071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
3072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
3075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
3076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
3077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
3078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3079384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "target") == 0) {
30800391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			targname = nft_rule_expr_get_str(expr,
30810391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka							 NFT_EXPR_TG_NAME);
30820391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			targinfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO,
30830391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka						     &target_len);
3084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
3085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
3086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			uint32_t verdict =
3087384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
3088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			switch(verdict) {
3090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_ACCEPT:
3091384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "ACCEPT";
3092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
3093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_DROP:
3094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "DROP";
3095384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
3096384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_RETURN:
3097384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "RETURN";
3098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
3099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_GOTO:
31000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				targname = nft_rule_expr_get_str(expr,
31010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka							NFT_EXPR_IMM_CHAIN);
3102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
3103384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_JUMP:
31040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka				targname = nft_rule_expr_get_str(expr,
31050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka							NFT_EXPR_IMM_CHAIN);
3106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
3107384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
3108384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
3109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
3110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3111384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
3112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
31130391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY);
31140391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka
31150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	switch (family) {
31160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET:
31170391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		flags = cs->fw.ip.flags;
31180391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		invflags = flags = cs->fw.ip.invflags;
31190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		proto = cs->fw.ip.proto;
31200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		iniface = cs->fw.ip.iniface;
31210391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		outiface = cs->fw.ip.outiface;
31220391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
31230391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET6:
31240391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		flags = cs->fw6.ipv6.flags;
31250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		invflags = cs->fw6.ipv6.invflags;
31260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		proto = cs->fw6.ipv6.proto;
31270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		iniface = cs->fw6.ipv6.iniface;
31280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		outiface = cs->fw6.ipv6.outiface;
31290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
31300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	}
3131384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3132384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_LINENUMBERS)
3133384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-4u ", "%u "), num);
3134384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3135384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOCOUNTS)) {
3136384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		print_num(cs->counters.pcnt, format);
3137384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		print_num(cs->counters.bcnt, format);
3138384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3139384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOTARGET))
3141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-9s ", "%s "), targname ? targname : "");
3142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
31430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	fputc(invflags & XT_INV_PROTO ? '!' : ' ', stdout);
3144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	{
3145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *pname =
31460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			proto_to_name(proto, format&FMT_NUMERIC);
3147384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (pname)
3148384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%-5s", "%s "), pname);
3149384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
31500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			printf(FMT("%-5hu", "%hu "), proto);
3151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_OPTIONS) {
3154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (format & FMT_NOTABLE)
3155384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("opt ", stdout);
31560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		fputc(invflags & IPT_INV_FRAG ? '!' : '-', stdout);
3157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputc(flags & IPT_F_FRAG ? 'f' : '-', stdout);
3158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputc(' ', stdout);
3159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3160384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3161384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_VIA) {
3162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		char iface[IFNAMSIZ+2];
31630391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (invflags & IPT_INV_VIA_IN) {
3164384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			iface[0] = '!';
3165384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			iface[1] = '\0';
3166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
3167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else iface[0] = '\0';
3168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
31690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (iniface[0] != '\0') {
31700391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			strcat(iface, iniface);
3171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
3172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (format & FMT_NUMERIC) strcat(iface, "*");
3173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else strcat(iface, "any");
3174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT(" %-6s ","in %s "), iface);
3175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
31760391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (invflags & IPT_INV_VIA_OUT) {
3177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			iface[0] = '!';
3178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			iface[1] = '\0';
3179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
3180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else iface[0] = '\0';
3181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
31820391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		if (outiface[0] != '\0') {
31830391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka			strcat(iface, outiface);
3184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
3185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (format & FMT_NUMERIC) strcat(iface, "*");
3186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else strcat(iface, "any");
3187384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-6s ","out %s "), iface);
3188384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
31910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	switch (family) {
31920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET:
31930391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		print_ipv4_addr(cs, format);
31940391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
31950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	case AF_INET6:
31960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		print_ipv6_addr(cs, format);
31970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka		break;
3198384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3199384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3200384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_NOTABLE)
3201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputs("  ", stdout);
3202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3203384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef IPT_F_GOTO
32040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka	if(flags & IPT_F_GOTO)
3205384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("[goto] ");
3206384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
3207384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3208384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
3209384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
3210384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
3211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
3212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3214384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
3215384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
3216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
3217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
3218384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3219384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "match") == 0)
3220384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_match(expr, format & FMT_NUMERIC);
3221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3222384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
3223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
3225384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = calloc(1, sizeof(struct xt_entry_target) + target_len);
3227384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (t == NULL)
3228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
3229384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3230384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* emulate struct xt_entry_match since ->print needs it */
3231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy((void *)&t->data, targinfo, target_len);
3232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (targname) {
3234384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		target = xtables_find_target(targname, XTF_TRY_LOAD);
3235384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (target) {
3236384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (target->print)
3237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				/* FIXME missing first parameter */
3238384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				target->print(NULL, t, format & FMT_NUMERIC);
3239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else
3240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("[%ld bytes of unknown target data] ",
3241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				target_len);
3242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(t);
3244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3245384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NONEWLINE))
3246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputc('\n', stdout);
3247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
3248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
3250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_list(struct nft_handle *h, struct nft_chain *c, const char *table,
3251384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int rulenum, unsigned int format,
3252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		void (*cb)(const struct iptables_command_state *cs,
3253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			   struct nft_rule *r, unsigned int num,
3254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			   unsigned int format))
3255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
3256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
3257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list_iter *iter;
3258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
3259384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int rule_ctr = 0, ret = 0;
3260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
3261384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3262384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
3263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
3264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot retrieve rule list from kernel\n");
3265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
3266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
3269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
3270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
3271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
3272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
3275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
3276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
3277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
3278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
3279384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
3280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		rule_ctr++;
3282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
3284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0)
3285384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
3286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (rulenum > 0) {
3288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* List by rule number case */
3289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (rule_ctr != rulenum) {
3290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				rule_ctr++;
3291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
3292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
3293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
3294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			struct iptables_command_state cs = {};
3295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Show all rules case */
3296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_to_iptables_command_state(r, &cs);
3297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cb(&cs, r, rule_ctr, format);
3299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
3300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
3301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
3302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_iter_destroy(iter);
3305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_free(list);
3306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3307384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == 0)
3308384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
3309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
3311384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
3312384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
3314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  int rulenum, unsigned int format)
3315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
3316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
3317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
3318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
3319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3320384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
3321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
3323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
3324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
3325384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
3326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3328384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
3329384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
3330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
3331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
3332384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
3333384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
3334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
3335384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
3336384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t refs =
3337384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_USE);
3338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct xt_counters ctrs = {
3339384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			.pcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS),
3340384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			.bcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES),
3341384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		};
3342384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
3343384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3344384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM))
3345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			basechain = true;
3346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3347384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
3348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
3349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
3350384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
3351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3352384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		print_header(format, chain_name, policy_name[policy], &ctrs,
3353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			     basechain, refs);
3354384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
335506fc595fa99ab0036d87b259b0d20e4916522969Pablo Neira Ayuso		__nft_rule_list(h, c, table, rulenum, format, print_firewall);
3356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
3357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
3358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
3361384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
3363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
3364384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3365384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
3366384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusolist_save(const struct iptables_command_state *cs, struct nft_rule *r,
3367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  unsigned int num, unsigned int format)
3368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
3369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_print_save(r, !(format & FMT_NOCOUNTS));
3370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
3371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
3373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_list_chain_save(struct nft_handle *h, const char *table,
3374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 struct nft_chain_list *list, int counters)
3375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
3376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
3377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
3378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
3380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
3381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
3382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
3383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
3386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
3387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
3388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
3389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
3390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
3391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
3392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
3393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
3395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
3396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* this is a base chain */
3398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM)) {
3399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-P %s %s", chain_name, policy_name[policy]);
3400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (counters) {
3402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				printf(" -c %lu %lu\n",
3403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS),
3404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES));
3405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			} else
3406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				printf("\n");
3407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
3408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-N %s\n", chain_name);
3409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
3410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
3411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
3412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
3415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
3416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list_save(struct nft_handle *h, const char *chain,
3418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       const char *table, int rulenum, int counters)
3419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
3420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
3421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
3422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
3423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
3425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Dump policies and custom chains first */
3427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_chain_save(h, table, list, counters);
3428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Now dump out rules in this table */
3430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
3431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
3432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
3433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
3434384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3436384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
3437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
3438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
3439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
3440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
3441384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
3442384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
3444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
3445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
3446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
3447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		__nft_rule_list(h, c, table, rulenum,
3449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				counters ? 0 : FMT_NOCOUNTS, list_save);
3450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
3451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
3452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
3455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3456384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
3457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
3458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
34599e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusostatic int nft_action(struct nft_handle *h, int type)
34609e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
34619e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
34629e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	struct nlmsghdr *nlh;
34639e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	uint32_t seq;
34649e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	int ret;
34659e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
34669e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh = mnl_nlmsg_put_header(buf);
34679e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh->nlmsg_type = (NFNL_SUBSYS_NFTABLES<< 8) | type;
34689e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
34699e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nlh->nlmsg_seq = seq = time(NULL);
34709e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
34719e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
34729e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nfg->nfgen_family = AF_INET;
34739e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nfg->version = NFNETLINK_V0;
34749e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	nfg->res_id = 0;
34759e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
34769e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
34779e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	if (ret < 0) {
34789e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso		if (errno != EEXIST)
34799e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso			perror("mnl-talk:nft_commit");
34809e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	}
34819e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	return ret;
34829e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
34839e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
34849e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_commit(struct nft_handle *h)
34859e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
34869e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	return nft_action(h, NFT_MSG_COMMIT);
34879e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
34889e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
34899e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_abort(struct nft_handle *h)
34909e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{
34919e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso	return nft_action(h, NFT_MSG_ABORT);
34929e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso}
34939e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso
3494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_compatible_revision(const char *name, uint8_t rev, int opt)
3495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
3496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct mnl_socket *nl;
3497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
3498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
3499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t portid, seq, type;
3500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
3501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (opt == IPT_SO_GET_REVISION_MATCH)
3503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 0;
3504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
3505384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 1;
3506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = mnl_nlmsg_put_header(buf);
3508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_type = (NFNL_SUBSYS_NFT_COMPAT << 8) | NFNL_MSG_COMPAT_GET;
3509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
3510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_seq = seq = time(NULL);
3511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
3513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->nfgen_family = AF_INET;
3514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->version = NFNETLINK_V0;
3515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->res_id = 0;
3516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_strz(nlh, NFTA_COMPAT_NAME, name);
3518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_REV, htonl(rev));
3519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_TYPE, htonl(type));
3520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	DEBUGP("requesting `%s' rev=%d type=%d via nft_compat\n",
3522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		name, rev, type);
3523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nl = mnl_socket_open(NETLINK_NETFILTER);
3525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nl == NULL) {
3526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_open");
3527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
3528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
3531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_bind");
3532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
3533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	portid = mnl_socket_get_portid(nl);
3535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
3537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_send");
3538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
3539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
3542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
3543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_recvfrom");
3544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
3545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
3548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
3549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_cb_run");
3550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
3551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
3554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(nl);
3555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret < 0 ? 0 : 1;
3557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
3558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/* Translates errno numbers into more human-readable form than strerror. */
3560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoconst char *nft_strerror(int err)
3561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
3562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
3563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	static struct table_struct {
3564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		void *fn;
3565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int err;
3566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *message;
3567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} table[] =
3568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  {
3569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, ENOTEMPTY, "Chain is not empty" },
3570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EINVAL, "Can't delete built-in chain" },
3571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EMLINK,
3572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Can't delete chain with references left" },
3573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_add, EEXIST, "Chain already exists" },
3574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, E2BIG, "Index of insertion too big" },
3575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_replace, E2BIG, "Index of replacement too big" },
3576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete_num, E2BIG, "Index of deletion too big" },
3577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/*	    { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
3578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, */
3579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, ELOOP, "Loop found in table" },
3580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, EINVAL, "Target problem" },
3581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    /* ENOENT for DELETE probably means no matching rule */
3582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete, ENOENT,
3583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Bad rule (does a matching rule exist in that chain?)" },
3584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, ENOENT, "Bad built-in chain name" },
3585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, EINVAL, "Bad policy name" },
3586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, EPERM, "Permission denied (you must be root)" },
3587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, 0, "Incompatible with this kernel" },
3588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
3589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOSYS, "Will be implemented real soon.  I promise ;)" },
3590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOMEM, "Memory allocation problem" },
3591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOENT, "No chain/target/match by that name" },
3592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  };
3593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
3595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if ((!table[i].fn || table[i].fn == nft_fn)
3596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    && table[i].err == err)
3597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return table[i].message;
3598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
3599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
3600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return strerror(err);
3601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
3602