nft.c revision e17b5f15c2beda86565a8f4e55fdf12ceb20dd59
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>
37384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter_ipv4/ip_tables.h>	/* FIXME: only IPV4 by now */
38384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
39384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netlink.h>
40384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nfnetlink.h>
41384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nf_tables.h>
42384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nf_tables_compat.h>
43384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
44384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libmnl/libmnl.h>
45384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/table.h>
46384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/chain.h>
47384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/rule.h>
48384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/expr.h>
49384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
50384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <netinet/in.h>	/* inet_ntoa */
51384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <arpa/inet.h>
52384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
53384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include "nft.h"
54384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include "xshared.h" /* proto_to_name */
55384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
56384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void *nft_fn;
57384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
58384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh,
59384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    int (*cb)(const struct nlmsghdr *nlh, void *data),
60384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    void *data)
61384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
62384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
63384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
64384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
65384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0) {
66384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_send");
67384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
68384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
69384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
70384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
71384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (ret > 0) {
72384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = mnl_cb_run(buf, ret, h->seq, h->portid, cb, data);
73384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (ret <= 0)
74384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
75384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
76384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
77384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
78384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
79384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
80384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
81384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
82384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
83384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
84384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
85e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusostatic int nft_table_builtin_add(struct nft_handle *h, const char *table)
86384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
87384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
88384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
89384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
90e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int ret;
91384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
92384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_alloc();
93384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (t == NULL)
94e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		return -1;
95384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
96c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)table);
97384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
98384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, AF_INET,
99384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
101384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_free(t);
102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
103e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
104e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	if (ret < 0) {
105384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl-talk:nft_table_init_one");
107384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
108e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	return ret;
109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
111384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FILTER		0
112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define MANGLE		1
113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define RAW		2
114384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define SECURITY	3
115384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define TABLES_MAX	4
116384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
117e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusostruct builtin_chain {
118e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	const char *name;
119e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	uint32_t hook;
120e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso};
121e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
122c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_table {
123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
124384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t prio;
125e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	struct builtin_chain chains[NF_INET_NUMHOOKS];
126384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} tables[TABLES_MAX] = {
127384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[RAW] = {
128384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "raw",
129384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.prio	= -300,	/* NF_IP_PRI_RAW */
130e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
131e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
132e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "PREROUTING",
133e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
134e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
135e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
136e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
137e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
138e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
139e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[MANGLE] = {
142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "mangle",
143384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.prio	= -150,	/* NF_IP_PRI_MANGLE */
144e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
145e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
146e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "PREROUTING",
147e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_PRE_ROUTING,
148e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
149e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
150e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
151e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
152e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
153e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
154e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
155e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
156e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
157e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
158e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
159e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
160e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
161e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
162e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "POSTROUTING",
163e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_POST_ROUTING,
164e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
165e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[FILTER] = {
168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "filter",
169384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.prio	= 0,	/* NF_IP_PRI_FILTER */
170e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
171e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
172e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
173e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
174e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
175e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
176e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
177e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
178e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
179e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
180e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
181e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
182e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
183e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		},
184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[SECURITY] = {
186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.name	= "security",
187384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.prio	= 150,	/* NF_IP_PRI_SECURITY */
188e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		.chains = {
189e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
190e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "INPUT",
191e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_IN,
192e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
193e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
194e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "FORWARD",
195e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_FORWARD,
196e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
197e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			{
198e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.name	= "OUTPUT",
199e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso				.hook	= NF_INET_LOCAL_OUT,
200e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			},
201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		},
202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	},
203e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* nat already registered by nf_tables */
204384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso};
205384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
206c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct nft_chain *
207c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_alloc(struct builtin_table *table,
208c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			struct builtin_chain *chain, int policy)
209384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
210384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL)
214c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		return NULL;
215384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table->name);
217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain->name);
218384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_HOOKNUM, chain->hook);
219384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_PRIO, table->prio);
220384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy);
221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
222c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return c;
223c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
224c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
225c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic void
226c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table,
227c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		      struct builtin_chain *chain, int policy)
228c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
229c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
230c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct nlmsghdr *nlh;
231c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct nft_chain *c;
232c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
233c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	c = nft_chain_builtin_alloc(table, chain, policy);
234c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (c == NULL)
235c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		return;
236c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET,
238384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_talk(h, nlh, NULL, NULL) < 0) {
243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
244c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			perror("mnl_talk:nft_chain_builtin_add");
245c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
246c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
247c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
248c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in table already exists */
249c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_table *nft_table_builtin_find(const char *table)
250c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
251c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	int i;
252c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	bool found = false;
253c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
254c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	for (i=0; i<TABLES_MAX; i++) {
255c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		if (strcmp(tables[i].name, table) != 0)
256c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			continue;
257c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
258c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		found = true;
259c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		break;
260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
261c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
262c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return found ? &tables[i] : NULL;
263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
265c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in chain already exists */
266c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_chain *
267e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusonft_chain_builtin_find(struct builtin_table *t, const char *chain)
268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
269e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int i;
270c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	bool found = false;
271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
272e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	for (i=0; i<NF_IP_NUMHOOKS && t->chains[i].name != NULL; i++) {
273e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (strcmp(t->chains[i].name, chain) != 0)
274e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			continue;
275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
276e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		found = true;
277e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		break;
278e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	}
279e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	return found ? &t->chains[i] : NULL;
280e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso}
281e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
282e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusostatic void
283e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso__nft_chain_builtin_init(struct nft_handle *h,
284e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			 struct builtin_table *table, const char *chain,
285e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			 int policy)
286e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso{
287e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int i, default_policy;
288e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
289e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* Initialize all built-in chains. Exception, for e one received as
290e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	 * parameter, set the default policy as requested.
291e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	 */
292e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	for (i=0; i<NF_IP_NUMHOOKS && table->chains[i].name != NULL; i++) {
293e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (chain && strcmp(table->chains[i].name, chain) == 0)
294e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			default_policy = policy;
295e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		else
296e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			default_policy = NF_ACCEPT;
297e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
298e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		nft_chain_builtin_add(h, table, &table->chains[i],
299e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso					default_policy);
300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
301c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso}
302c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
303c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic int
304c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_init(struct nft_handle *h, const char *table,
305c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		       const char *chain, int policy)
306c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{
307c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	int ret = 0;
308c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_table *t;
309c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
310c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	t = nft_table_builtin_find(table);
311c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (t == NULL) {
312c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		ret = -1;
313c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		goto out;
314c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
315e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	if (nft_table_builtin_add(h, table) < 0) {
316e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		/* Built-in table already initialized, skip. */
317e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso		if (errno == EEXIST)
318e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso			goto out;
319c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
320e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	__nft_chain_builtin_init(h, t, chain, policy);
321c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusoout:
322c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	return ret;
323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
325384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_init(struct nft_handle *h)
326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->nl = mnl_socket_open(NETLINK_NETFILTER);
328384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (h->nl == NULL) {
329384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_open");
330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
332384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
333384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_bind");
335384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
336384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
337384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	h->portid = mnl_socket_get_portid(h->nl);
338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
339384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
340384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
341384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
342384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusovoid nft_fini(struct nft_handle *h)
343384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
344384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(h->nl);
345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
347384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_table_add(struct nft_handle *h, const struct nft_table *t)
348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
350384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
352384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, AF_INET,
353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
354384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_nlmsg_build_payload(nlh, t);
355384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_add(struct nft_handle *h, const struct nft_chain *c)
360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
361384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
364384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET,
365384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
366384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mnl_talk(h, nlh, NULL, NULL);
369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_debug(struct nft_chain *c, struct nlmsghdr *nlh)
372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_snprintf(tmp, sizeof(tmp), c, 0, 0);
377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("DEBUG: chain: %s", tmp);
378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_chain_set(struct nft_handle *h, const char *table,
384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain, int policy,
385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const struct xt_counters *counters)
386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
390c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_table *_t;
391c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	struct builtin_chain *_c;
392e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	int ret;
393c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
394c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	_t = nft_table_builtin_find(table);
395c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	/* if this built-in table does not exists, create it */
396c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_t != NULL)
397c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		nft_table_builtin_add(h, table);
398c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
399e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	_c = nft_chain_builtin_find(_t, chain);
400c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	if (_c != NULL) {
401c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		/* This is a built-in chain */
402c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		c = nft_chain_builtin_alloc(_t, _c, policy);
403c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		if (c == NULL)
404c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			return -1;
405c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
406c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	} else {
407c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		/* This is a custom chain */
408c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		c = nft_chain_alloc();
409c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		if (c == NULL)
410c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso			return -1;
411c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
412c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
413c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain);
414c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso		nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy);
415c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	}
416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (counters) {
418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES,
419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->bcnt);
420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_PACKETS,
421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					counters->pcnt);
422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET,
425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_print_debug(c, nlh);
429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
434384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:__nft_chain_policy");
435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
436384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_set(struct nft_handle *h, const char *table,
440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const char *chain, const char *policy,
441384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  const struct xt_counters *counters)
442384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = -1;
444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_chain_set;
446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(policy, "DROP") == 0)
448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_set(h, table, chain, NF_DROP, counters);
449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else if (strcmp(policy, "ACCEPT") == 0)
450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_set(h, table, chain, NF_ACCEPT, counters);
451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
456384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void __add_match(struct nft_rule_expr *e, struct xt_entry_match *m)
457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	void *info;
459384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_MT_NAME, m->u.user.name, strlen(m->u.user.name));
461384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(e, NFT_EXPR_MT_REV, m->u.user.revision);
462384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
463384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	info = calloc(1, m->u.match_size);
464384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (info == NULL)
465384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
466384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
467384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(info, m->data, m->u.match_size);
468384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_MT_INFO, info, m->u.match_size - sizeof(*m));
469384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
470384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
471384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_match(struct nft_rule *r, struct xt_entry_match *m)
472384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
473384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
474384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
475384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("match");
476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	__add_match(expr, m);
480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void __add_target(struct nft_rule_expr *e, struct xt_entry_target *t)
484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	void *info = NULL;
486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_TG_NAME, t->u.user.name,
488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  strlen(t->u.user.name));
489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(e, NFT_EXPR_TG_REV, t->u.user.revision);
490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (info == NULL) {
492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		info = calloc(1, t->u.target_size);
493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (info == NULL)
494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return;
495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(info, t->data, t->u.target_size);
497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(e, NFT_EXPR_TG_INFO, info, t->u.target_size - sizeof(*t));
500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_target(struct nft_rule *r, struct xt_entry_target *t)
503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
505384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("target");
507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	__add_target(expr, t);
511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_jumpto(struct nft_rule *r, const char *name, int verdict)
515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("immediate");
519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT);
523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict);
524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_str(expr, NFT_EXPR_IMM_CHAIN, (char *)name);
525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_verdict(struct nft_rule *r, int verdict)
529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("immediate");
533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT);
537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict);
538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_rule_print_debug(struct nft_rule *r, struct nlmsghdr *nlh)
542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG
544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char tmp[1024];
545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_snprintf(tmp, sizeof(tmp), r, 0, 0);
547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("DEBUG: rule: %s", tmp);
548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg));
549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_meta(struct nft_rule *r, uint32_t key)
553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("meta");
557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_META_KEY, key);
561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_META_DREG, NFT_REG_1);
562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_payload(struct nft_rule *r, int offset, int len)
567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("payload");
571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_BASE,
575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				NFT_PAYLOAD_NETWORK_HEADER);
576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_DREG, NFT_REG_1);
577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_OFFSET, offset);
578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_LEN, len);
579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_cmp_ptr(struct nft_rule *r, uint32_t op, void *data, size_t len)
584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("cmp");
588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u8(expr, NFT_EXPR_CMP_SREG, NFT_REG_1);
592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u8(expr, NFT_EXPR_CMP_OP, op);
593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set(expr, NFT_EXPR_CMP_DATA, data, len);
594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_cmp_u32(struct nft_rule *r, uint32_t val, uint32_t op)
599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	add_cmp_ptr(r, op, &val, sizeof(val));
601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_counters(struct nft_rule *r, uint64_t packets, uint64_t bytes)
604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_alloc("counter");
608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (expr == NULL)
609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_BYTES, packets);
612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_PACKETS, bytes);
613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_add_expr(r, expr);
615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint
618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_add(struct nft_handle *h, const char *chain, const char *table,
619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	     struct iptables_command_state *cs, bool append, bool verbose)
620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 1;
626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t op;
627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int flags = append ? NLM_F_APPEND : 0;
628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
629e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
630c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso	nft_chain_builtin_init(h, table, chain, NF_ACCEPT);
631c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso
632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_add;
633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL) {
636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
637384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
639384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (cs->fw.ip.iniface[0] != '\0') {
644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int iface_len = strlen(cs->fw.ip.iniface);
645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.invflags & IPT_INV_VIA_IN)
647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			op = NFT_CMP_NEQ;
648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			op = NFT_CMP_EQ;
650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.iniface[iface_len - 1] == '+') {
652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_meta(r, NFT_META_IIFNAME);
653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_cmp_ptr(r, op, cs->fw.ip.iniface, iface_len - 1);
654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_meta(r, NFT_META_IIF);
656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_cmp_u32(r, if_nametoindex(cs->fw.ip.iniface), op);
657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (cs->fw.ip.outiface[0] != '\0') {
660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int iface_len = strlen(cs->fw.ip.outiface);
661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.invflags & IPT_INV_VIA_OUT)
663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			op = NFT_CMP_NEQ;
664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			op = NFT_CMP_EQ;
666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.outiface[iface_len - 1] == '+') {
668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_meta(r, NFT_META_OIFNAME);
669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_cmp_ptr(r, op, cs->fw.ip.outiface, iface_len - 1);
670384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_meta(r, NFT_META_OIF);
672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_cmp_u32(r, if_nametoindex(cs->fw.ip.outiface), op);
673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (cs->fw.ip.src.s_addr != 0) {
676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		add_payload(r, offsetof(struct iphdr, saddr), 4);
677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.invflags & IPT_INV_SRCIP)
678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			op = NFT_CMP_NEQ;
679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			op = NFT_CMP_EQ;
681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		add_cmp_u32(r, cs->fw.ip.src.s_addr, op);
683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (cs->fw.ip.dst.s_addr != 0) {
685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		add_payload(r, offsetof(struct iphdr, daddr), 4);
686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.invflags & IPT_INV_DSTIP)
687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			op = NFT_CMP_NEQ;
688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			op = NFT_CMP_EQ;
690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
691384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		add_cmp_u32(r, cs->fw.ip.dst.s_addr, op);
692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (cs->fw.ip.proto != 0) {
694384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		add_payload(r, offsetof(struct iphdr, protocol), 1);
695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.invflags & XT_INV_PROTO)
696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			op = NFT_CMP_NEQ;
697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			op = NFT_CMP_EQ;
699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
700384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		add_cmp_u32(r, cs->fw.ip.proto, op);
701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (matchp = cs->matches; matchp; matchp = matchp->next)
704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		add_match(r, matchp->match->m);
705384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
706384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Counters need to me added before the target, otherwise they are
707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 * increased for each rule because of the way nf_tables works.
708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 */
709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	add_counters(r, cs->counters.pcnt, cs->counters.bcnt);
710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* If no target at all, add nothing (default to continue) */
712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (cs->target != NULL) {
713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* Standard target? */
714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_verdict(r, NF_ACCEPT);
716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_verdict(r, NF_DROP);
718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_verdict(r, NFT_RETURN);
720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_target(r, cs->target->t);
722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else if (strlen(cs->jumpto) > 0) {
723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* Not standard, then it's a go / jump to chain */
724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.flags & IPT_F_GOTO)
725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_jumpto(r, cs->jumpto, NFT_GOTO);
726384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			add_jumpto(r, cs->jumpto, NFT_JUMP);
728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* NLM_F_CREATE autoloads the built-in table if it does not exists */
731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, AF_INET,
732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_CREATE|flags, h->seq);
733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_print_debug(r, nlh);
736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
737384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
738384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_add");
742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
746384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
747384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_match_save(struct nft_rule_expr *expr)
749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
750384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
751384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_match *match;
752384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_match *emu;
753384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *mtinfo;
754384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
755384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
756384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
757384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
758384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	match = xtables_find_match(name, XTF_TRY_LOAD, NULL);
759384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match == NULL)
760384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
761384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
762384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mtinfo = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len);
763384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mtinfo == NULL)
764384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
766384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	emu = calloc(1, sizeof(struct xt_entry_match) + len);
767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (emu == NULL)
768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
769384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
770384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(&emu->data, mtinfo, len);
771384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
772384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match->alias)
773384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-m %s", match->alias(emu));
774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
775384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-m %s", match->name);
776384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
777384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* FIXME missing parameter */
778384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	match->save(NULL, emu);
779384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
780384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(" ");
781384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(emu);
783384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
784384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
785384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_target_save(struct nft_rule_expr *expr)
786384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
787384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
788384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_target *target;
789384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_target *emu;
790384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *tginfo;
791384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
792384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
793384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
794384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
795384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Standard target not supported, we use native immediate expression */
796384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "") == 0) {
797384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("ERROR: standard target seen, should not happen\n");
798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
800384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	target = xtables_find_target(name, XTF_TRY_LOAD);
802384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target == NULL)
803384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	tginfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len);
806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (tginfo == NULL)
807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	emu = calloc(1, sizeof(struct xt_entry_match) + len);
810384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (emu == NULL)
811384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
812384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
813384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(emu->data, tginfo, len);
814384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
815384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target->alias)
816384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s", target->alias(emu));
817384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
818384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s", target->name);
819384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
820384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* FIXME missing parameter */
821384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	target->save(NULL, emu);
822384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
823384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(emu);
824384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
825384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
826384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_immediate_save(struct nft_rule_expr *expr)
827384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
828384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t verdict;
829384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
830384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
832384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(verdict) {
833384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_ACCEPT:
834384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j ACCEPT");
835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
836384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_DROP:
837384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j DROP");
838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
839384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_RETURN:
840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j RETURN");
841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
842384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_GOTO:
843384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-g %s",
844384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN));
845384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
846384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_JUMP:
847384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-j %s",
848384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN));
849384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
850384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
851384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
852384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
853384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
854384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_print_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
855384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
856384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
857384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t value;
858384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
859384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char ifname[IFNAMSIZ];
860384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *ifname_ptr;
861384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
862384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
863384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
864384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (e == NULL)
865384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
866384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
867384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
868384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* meta should be followed by cmp */
869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "cmp") != 0) {
870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("skipping no cmp after meta\n");
871384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
872384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
873384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(key) {
875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIF:
876384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
877384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if_indextoname(value, ifname);
878384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
879384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
880384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
881384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-i %s ", ifname);
882384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
883384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
884384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -i %s ", ifname);
885384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
886384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
887384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
888384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIF:
889384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
890384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if_indextoname(value, ifname);
891384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
892384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
893384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
894384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-o %s ", ifname);
895384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
896384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
897384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -o %s ", ifname);
898384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
899384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
900384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
901384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIFNAME:
902384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
903384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(ifname, ifname_ptr, len);
904384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname[len] = '\0';
905384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
906384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* if this is zero, then assume this is a interface mask */
907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (if_nametoindex(ifname) == 0) {
908384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len] = '+';
909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len+1] = '\0';
910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-i %s ", ifname);
915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -i %s ", ifname);
918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIFNAME:
922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(ifname, ifname_ptr, len);
924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname[len] = '\0';
925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* if this is zero, then assume this is a interface mask */
927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (if_nametoindex(ifname) == 0) {
928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len] = '+';
929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			ifname[len+1] = '\0';
930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) {
933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_EQ:
934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-o %s ", ifname);
935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		case NFT_CMP_NEQ:
937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -o %s ", ifname);
938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	default:
942384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("unknown meta key %d\n", key);
943384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
944384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
946384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoget_cmp_data(struct nft_rule_expr_iter *iter, void *data, size_t dlen, bool *inv)
949384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
950384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *e;
951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t op;
954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (e == NULL)
957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "cmp") != 0) {
961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("skipping no cmp after meta\n");
962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy(data, nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len), dlen);
966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	op = nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP);
967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (op == NFT_CMP_NEQ)
968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		*inv = true;
969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		*inv = false;
971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void print_proto(uint16_t proto, int invert)
974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct protoent *pent = getprotobynumber(proto);
976384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (invert)
978384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("! ");
979384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
980384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (pent) {
981384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-p %s ", pent->p_name);
982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
985384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("-p %u ", proto);
986384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
987384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
988384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic const char *mask_to_str(uint32_t mask)
989384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
990384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	static char mask_str[sizeof("255.255.255.255")];
991384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t bits, hmask = ntohl(mask);
992384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct in_addr mask_addr = {
993384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		.s_addr = mask,
994384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	};
995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int i;
996384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
997384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mask == 0xFFFFFFFFU) {
998384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		sprintf(mask_str, "32");
999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return mask_str;
1000384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1001384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	i    = 32;
1003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bits = 0xFFFFFFFEU;
1004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (--i >= 0 && hmask != bits)
1005384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bits <<= 1;
1006384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (i >= 0)
1007384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		sprintf(mask_str, "%u", i);
1008384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
1009384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		sprintf(mask_str, "%s", inet_ntoa(mask_addr));
1010384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1011384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return mask_str;
1012384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1013384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1014384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1015384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_print_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
1016384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1017384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t offset;
1018384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool inv;
1019384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1020384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
1021384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1022384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(offset) {
1023384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct in_addr addr;
1024384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t proto;
1025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, saddr):
1027384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &addr, sizeof(addr), &inv);
1028384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (inv)
1029384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -s %s/%s ", inet_ntoa(addr),
1030384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						mask_to_str(0xffffffff));
1031384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
1032384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-s %s/%s ", inet_ntoa(addr),
1033384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						mask_to_str(0xffffffff));
1034384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1035384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, daddr):
1036384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &addr, sizeof(addr), &inv);
1037384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (inv)
1038384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("! -d %s/%s ", inet_ntoa(addr),
1039384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						mask_to_str(0xffffffff));
1040384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
1041384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-d %s/%s ", inet_ntoa(addr),
1042384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						mask_to_str(0xffffffff));
1043384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1044384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, protocol):
1045384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &proto, sizeof(proto), &inv);
1046384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		print_proto(proto, inv);
1047384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1048384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	default:
1049384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("unknown payload offset %d\n", offset);
1050384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1051384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1052384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1053384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_print_counters(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
1056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   bool counters)
1057384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1058384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (counters) {
1059384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("-c %lu %lu ",
1060384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS),
1061384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES));
1062384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_rule_print_save(struct nft_rule *r, bool counters)
1066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
1069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
1071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("-A %s ", nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN));
1072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL)
1075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1079384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1080384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1081384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1082384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "counter") == 0) {
1083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_print_counters(expr, iter, counters);
1084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "payload") == 0) {
1085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_print_payload(expr, iter);
1086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "meta") == 0) {
1087384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_print_meta(expr, iter);
1088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "match") == 0) {
1089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_match_save(expr);
1090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "target") == 0) {
1091384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_target_save(expr);
1092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
1093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_immediate_save(expr);
1094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1095384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1096384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1097384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("\n");
1100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1101384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_chain_list_cb(const struct nlmsghdr *nlh, void *data)
1103384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1104384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1105384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list = data;
1106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1107384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
1108384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL) {
1109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1111384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_chain_nlmsg_parse(nlh, c) < 0) {
1114384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1115384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1116384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1117384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1118384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_add(c, list);
1119384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1120384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1121384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1122384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
1123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1124384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1125384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1126384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1127384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_chain_list *nft_chain_list_get(struct nft_handle *h)
1128384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1129384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1130384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1131384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1132384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1133384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1134384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_alloc();
1135384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1136384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list\n");
1137384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1138384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1139384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, AF_INET,
1141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1143384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_chain_list_cb, list);
1144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_chain_list_get");
1146384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1147384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1148384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1149384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1150384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostruct nft_chain_list *nft_chain_dump(struct nft_handle *h)
1151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return nft_chain_list_get(h);
1153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1155384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic const char *policy_name[NF_ACCEPT+1] = {
1156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_DROP] = "DROP",
1157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	[NF_ACCEPT] = "ACCEPT",
1158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso};
1159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1160384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_save(struct nft_chain *c, bool basechain)
1161384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1163384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint64_t pkts = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS);
1164384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint64_t bytes = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES);
1165384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* print chain name */
1167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (basechain) {
1168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t pol = NF_ACCEPT;
1169384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1170384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* no default chain policy? don't crash, display accept */
1171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_POLICY))
1172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			pol = nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
1173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(":%s %s [%lu:%lu]\n", chain, policy_name[pol],
1175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					     pkts, bytes);
1176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else
1177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(":%s - [%lu:%lu]\n", chain, pkts, bytes);
1178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_save(struct nft_handle *h, struct nft_chain_list *list,
1181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   const char *table)
1182384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1183384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1187384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1188384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1194384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
1195384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1196384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
1197384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1198384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
1199384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1200384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM))
1202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			basechain = true;
1203384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1204384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_chain_print_save(c, basechain);
1205384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1206384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1207384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1208384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1209384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1210384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1214384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_rule_list_cb(const struct nlmsghdr *nlh, void *data)
1215384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list = data;
1218384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1219384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
1220384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL) {
1221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1222384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1225384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_rule_nlmsg_parse(nlh, r) < 0) {
1226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1227384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1229384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1230384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_add(r, list);
1231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1234384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
1235384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1236384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1238384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_rule_list *nft_rule_list_get(struct nft_handle *h)
1240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
1244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1245384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_alloc();
1247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list\n");
1249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1251384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, AF_INET,
1253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_rule_list_cb, list);
1256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_save");
1258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_rule_list_free(list);
1259384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return NULL;
1260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1261384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1262384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_save(struct nft_handle *h, const char *table, bool counters)
1266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
1268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list_iter *iter;
1269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
1272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot retrieve rule list from kernel\n");
1274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
1278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1279384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
1284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
1285384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
1286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
1287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0)
1289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		nft_rule_print_save(r, counters);
1292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
1295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_free(list);
1298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
1301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
1305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1307384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1308384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
1309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_alloc();
1311384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (r == NULL)
1312384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
1315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
1316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Delete all rules in this table + chain */
1318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, AF_INET,
1319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1320384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
1321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_free(r);
1322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_talk(h, nlh, NULL, NULL) < 0) {
1324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
1325384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:__nft_rule_flush");
1326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1328384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1329384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_flush(struct nft_handle *h, const char *chain, const char *table)
1330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1332384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1333384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1335384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1336384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_flush;
1337384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_get(h);
1339384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1340384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
1341384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1342384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1343384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1344384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1347384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1350384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1352384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1354384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1355384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1361384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		__nft_rule_flush(h, table_name, chain_name);
1364384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1365384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1366384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table)
1377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1383e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	/* If built-in chains don't exist for this table, create them */
1384e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso	nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
1385e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso
1386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_alloc();
1387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (c == NULL) {
1388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate chain\n");
1389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return -1;
1390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
1393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain);
1394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET,
1396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK|NLM_F_EXCL, h->seq);
1397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
1398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_free(c);
1399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST)
1403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:nft_chain_add");
1404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int __nft_chain_del(struct nft_handle *h, struct nft_chain *c)
1411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, AF_INET,
1417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
1418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_nlmsg_build_payload(nlh, c);
1419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
1421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0) {
1422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (errno != EEXIST && errno != ENOENT)
1423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			perror("mnl_talk:__nft_chain_del");
1424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool nft_chain_builtin(struct nft_chain *c)
1430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Check if this chain has hook number, in that case is built-in.
1432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 * Should we better export the flags to user-space via nf_tables?
1433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 */
1434384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM) != NULL;
1435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1436384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table)
1438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
1440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
1441384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
1442384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
1443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int deleted_ctr = 0;
1444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_list_get(h);
1446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
1450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
1456384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
1457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *table_name =
1458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
1459384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
1460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
1461384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1462384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* don't delete built-in chain */
1463384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_builtin(c))
1464384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1465384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1466384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, table_name) != 0)
1467384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1468384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1469384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain != NULL && strcmp(chain, chain_name) != 0)
1470384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
1471384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1472384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = __nft_chain_del(h, c);
1473384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (ret < 0)
1474384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
1475384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		deleted_ctr++;
1477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
1478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
1479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
1483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* chain not found */
1485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0 && deleted_ctr == 0)
1486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
1487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_rename(struct nft_handle *h,const char *chain,
1493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			  const char *table, const char *newname)
1494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* XXX need new operation in nf_tables to support this */
1498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = nft_chain_user_del(h, chain, table);
1499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return ret;
1501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return nft_chain_user_add(h, newname, table);
1503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1505384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_table_list_cb(const struct nlmsghdr *nlh, void *data)
1506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list = data;
1509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_alloc();
1511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (t == NULL) {
1512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("OOM");
1513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nft_table_nlmsg_parse(nlh, t) < 0) {
1517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("nft_rule_nlmsg_parse");
1518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto out;
1519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_add(t, list);
1522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout:
1525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_free(t);
1526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return MNL_CB_OK;
1528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_table_list *nft_table_list_get(struct nft_handle *h)
1531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
1533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
1534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
1535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_alloc();
1538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate table list\n");
1540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, AF_INET,
1544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_DUMP, h->seq);
1545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, nft_table_list_cb, list);
1547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
1548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_table_list_get");
1549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return list;
1551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusobool nft_table_find(struct nft_handle *h, const char *tablename)
1554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list_iter *iter;
1557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool ret = false;
1559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_get(h);
1561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL)
1562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_table_list_iter_create(list);
1565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_list_iter_next(iter);
1571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
1572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *this_tablename =
1573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_table_attr_get(t, NFT_TABLE_ATTR_NAME);
1574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(tablename, this_tablename) == 0)
1576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return true;
1577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		t = nft_table_list_iter_next(iter);
1579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_free(list);
1582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
1585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_for_each_table(struct nft_handle *h,
1588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       int (*func)(struct nft_handle *h, const char *tablename, bool counters),
1589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       bool counters)
1590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 1;
1592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list *list;
1593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table_list_iter *iter;
1594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_table *t;
1595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_table_list_get(h);
1597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
1598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 0;
1599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
1600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_table_list_iter_create(list);
1603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
1606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = nft_table_list_iter_next(iter);
1609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (t != NULL) {
1610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *tablename =
1611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_table_attr_get(t, NFT_TABLE_ATTR_NAME);
1612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		func(h, tablename, counters);
1614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		t = nft_table_list_iter_next(iter);
1616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_table_list_free(list);
1619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
1621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* the core expects 1 for success and 0 for error */
1622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret == 0 ? 1 : 0;
1623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic inline int
1626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusomatch_different(const struct xt_entry_match *a,
1627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const unsigned char *a_elems,
1628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const unsigned char *b_elems,
1629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		unsigned char **maskptr)
1630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xt_entry_match *b;
1632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
1633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Offset of b is the same as a. */
1635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	b = (void *)b_elems + ((unsigned char *)a - a_elems);
1636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1637384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (a->u.match_size != b->u.match_size)
1638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 1;
1639384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(a->u.user.name, b->u.user.name) != 0)
1641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 1;
1642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	*maskptr += XT_ALIGN(sizeof(*a));
1644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < a->u.match_size - XT_ALIGN(sizeof(*a)); i++)
1646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0)
1647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return 1;
1648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	*maskptr += i;
1649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 0;
1650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
1653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusois_same(const struct iptables_command_state *a, const struct iptables_command_state *b)
1654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
1656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Always compare head structures: ignore mask here. */
1658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (a->fw.ip.src.s_addr != b->fw.ip.src.s_addr
1659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    || a->fw.ip.dst.s_addr != b->fw.ip.dst.s_addr
1660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    || a->fw.ip.smsk.s_addr != b->fw.ip.smsk.s_addr
1661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    || a->fw.ip.dmsk.s_addr != b->fw.ip.dmsk.s_addr
1662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    || a->fw.ip.proto != b->fw.ip.proto
1663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    || a->fw.ip.flags != b->fw.ip.flags
1664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    || a->fw.ip.invflags != b->fw.ip.invflags) {
1665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("different src/dst/proto/flags/invflags\n");
1666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < IFNAMSIZ; i++) {
1670384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (a->fw.ip.iniface_mask[i] != b->fw.ip.iniface_mask[i]) {
1671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different iniface mask %x, %x (%d)\n",
1672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			a->fw.ip.iniface_mask[i] & 0xff, b->fw.ip.iniface_mask[i] & 0xff, i);
1673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return false;
1674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if ((a->fw.ip.iniface[i] & a->fw.ip.iniface_mask[i])
1676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    != (b->fw.ip.iniface[i] & b->fw.ip.iniface_mask[i])) {
1677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different iniface\n");
1678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return false;
1679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (a->fw.ip.outiface_mask[i] != b->fw.ip.outiface_mask[i]) {
1681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different outiface mask\n");
1682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return false;
1683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if ((a->fw.ip.outiface[i] & a->fw.ip.outiface_mask[i])
1685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    != (b->fw.ip.outiface[i] & b->fw.ip.outiface_mask[i])) {
1686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different outiface\n");
1687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return false;
1688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1691384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
1692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1694384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
1696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	       struct iptables_command_state *cs)
1697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
1699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t value;
1700384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *name;
1701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *ifname;
1702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
1703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	e = nft_rule_expr_iter_next(iter);
1705384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (e == NULL)
1706384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME);
1709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(name, "cmp") != 0) {
1710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("skipping no cmp after meta\n");
1711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(key) {
1715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIF:
1716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
1717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
1718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.invflags |= IPT_INV_VIA_IN;
1719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if_indextoname(value, cs->fw.ip.iniface);
1721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memset(cs->fw.ip.iniface_mask, 0xff,
1723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       strlen(cs->fw.ip.iniface)+1);
1724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIF:
1726384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
1727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
1728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.invflags |= IPT_INV_VIA_OUT;
1729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if_indextoname(value, cs->fw.ip.outiface);
1731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memset(cs->fw.ip.outiface_mask, 0xff,
1733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       strlen(cs->fw.ip.outiface)+1);
1734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_IIFNAME:
1736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
1737384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
1738384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.invflags |= IPT_INV_VIA_IN;
1739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(cs->fw.ip.iniface, ifname, len);
1741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.iniface[len] = '\0';
1742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* If zero, then this is an interface mask */
1744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (if_nametoindex(cs->fw.ip.iniface) == 0) {
1745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.iniface[len] = '+';
1746384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.iniface[len+1] = '\0';
1747384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memset(cs->fw.ip.iniface_mask, 0xff, len);
1750384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1751384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_META_OIFNAME:
1752384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ifname = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
1753384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
1754384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.invflags |= IPT_INV_VIA_OUT;
1755384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1756384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memcpy(cs->fw.ip.outiface, ifname, len);
1757384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.outiface[len] = '\0';
1758384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1759384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* If zero, then this is an interface mask */
1760384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (if_nametoindex(cs->fw.ip.outiface) == 0) {
1761384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.outiface[len] = '+';
1762384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.outiface[len+1] = '\0';
1763384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1764384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		memset(cs->fw.ip.outiface_mask, 0xff, len);
1766384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	default:
1768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("unknown meta key %d\n", key);
1769384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1770384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1771384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1772384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1773384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
1775384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  struct iptables_command_state *cs)
1776384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1777384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t offset;
1778384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool inv;
1779384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1780384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
1781384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(offset) {
1783384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct in_addr addr;
1784384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t proto;
1785384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1786384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, saddr):
1787384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &addr, sizeof(addr), &inv);
1788384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.src.s_addr = addr.s_addr;
1789384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.smsk.s_addr = 0xffffffff;
1790384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (inv)
1791384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.invflags |= IPT_INV_SRCIP;
1792384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1793384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, daddr):
1794384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &addr, sizeof(addr), &inv);
1795384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.dst.s_addr = addr.s_addr;
1796384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.dmsk.s_addr = 0xffffffff;
1797384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (inv)
1798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.invflags |= IPT_INV_DSTIP;
1799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1800384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case offsetof(struct iphdr, protocol):
1801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		get_cmp_data(iter, &proto, sizeof(proto), &inv);
1802384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.proto = proto;
1803384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (inv)
1804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cs->fw.ip.invflags |= IPT_INV_PROTO;
1805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	default:
1807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("unknown payload offset %d\n", offset);
1808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1810384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1811384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1812384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1813384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_counter(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
1814384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  struct xt_counters *counters)
1815384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1816384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	counters->pcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS);
1817384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	counters->bcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES);
1818384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1819384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1820384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1821384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_immediate(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
1822384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    struct iptables_command_state *cs)
1823384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1824384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int verdict = nft_rule_expr_get_u32(e, NFT_EXPR_IMM_VERDICT);
1825384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_rule_expr_get_str(e, NFT_EXPR_IMM_CHAIN);
1826384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1827384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Standard target? */
1828384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	switch(verdict) {
1829384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_ACCEPT:
1830384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "ACCEPT";
1831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1832384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NF_DROP:
1833384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "DROP";
1834384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_RETURN:
1836384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = "RETURN";
1837384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_GOTO:
1839384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->fw.ip.flags |= IPT_F_GOTO;
1840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	case NFT_JUMP:
1841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		cs->jumpto = chain;
1842384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1843384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1844384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1845384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1846384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
1847384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_to_iptables_command_state(struct nft_rule *r,
1848384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				   struct iptables_command_state *cs)
1849384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1850384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1851384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
1852384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1853384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1854384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL)
1855384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
1856384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1857384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1858384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1859384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1860384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1861384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1862384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "counter") == 0) {
1863384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_parse_counter(expr, iter, &cs->counters);
1864384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "payload") == 0) {
1865384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_parse_payload(expr, iter, cs);
1866384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "meta") == 0) {
1867384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_parse_meta(expr, iter, cs);
1868384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
1869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_parse_immediate(expr, iter, cs);
1870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1871384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1872384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1873384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
1876384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1877384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1878384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int matches_howmany(struct xtables_rule_match *matches)
1879384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1880384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
1881384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int matches_ctr = 0;
1882384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1883384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (matchp = matches; matchp; matchp = matchp->next)
1884384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		matches_ctr++;
1885384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1886384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return matches_ctr;
1887384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1888384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1889384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
1890384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__find_match(struct nft_rule_expr *expr, struct xtables_rule_match *matches)
1891384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1892384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *matchname = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
1893384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Netlink aligns this match info, don't trust this length variable */
1894384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *data = nft_rule_expr_get_str(expr, NFT_EXPR_MT_INFO);
1895384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xtables_rule_match *matchp;
1896384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool found = false;
1897384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1898384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (matchp = matches; matchp; matchp = matchp->next) {
1899384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct xt_entry_match *m = matchp->match->m;
1900384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1901384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(m->u.user.name, matchname) != 0) {
1902384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("mismatching match name\n");
1903384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			continue;
1904384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1905384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1906384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (memcmp(data, m->data, m->u.user.match_size - sizeof(*m)) != 0) {
1907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("mismatch match data\n");
1908384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			continue;
1909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		found = true;
1911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		break;
1912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return found;
1915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool find_matches(struct xtables_rule_match *matches, struct nft_rule *r)
1918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
1921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int kernel_matches = 0;
1922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "match") == 0) {
1935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!__find_match(expr, matches))
1936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
1937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			kernel_matches++;
1939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
1940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
1941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1942384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
1943384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1944384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* same number of matches? */
1945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (matches_howmany(matches) != kernel_matches)
1946384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
1949384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1950384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool __find_target(struct nft_rule_expr *expr, struct xt_entry_target *t)
1952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
1954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *tgname = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
1955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Netlink aligns this target info, don't trust this length variable */
1956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *data = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len);
1957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (strcmp(t->u.user.name, tgname) != 0) {
1959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("mismatching target name\n");
1960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (memcmp(data, t->data,  t->u.user.target_size - sizeof(*t)) != 0)
1964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
1967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int targets_howmany(struct xtables_target *target)
1970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return target != NULL ? 1 : 0;
1972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
1973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
1975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusofind_target(struct xtables_target *target, struct nft_rule *r)
1976384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
1977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
1978384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
1979384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int kernel_targets = 0;
1980384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1981384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Special case: we use native immediate expressions to emulated
1982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 * standard targets. Also, we don't want to crash with no targets.
1983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	 */
1984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (target == NULL || strcmp(target->name, "standard") == 0)
1985384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return true;
1986384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1987384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
1988384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
1989384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
1990384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
1991384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
1992384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1993384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
1994384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
1995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
1996384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
1997384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
1998384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "target") == 0) {
1999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* we may support several targets in the future */
2000384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!__find_target(expr, target->t))
2001384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
2002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			kernel_targets++;
2004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2005384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2006384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2007384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2008384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2009384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* same number of targets? */
2010384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (targets_howmany(target) != kernel_targets) {
2011384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("kernel targets is %d but we passed %d\n",
2012384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		kernel_targets, targets_howmany(target));
2013384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
2014384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2015384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2016384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
2017384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2018384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2019384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool
2020384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusofind_immediate(struct nft_rule *r, const char *jumpto)
2021384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2022384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
2023384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
2024384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
2026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2027384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2028384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return false;
2029384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2030384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2031384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
2032384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
2033384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
2034384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
2035384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2036384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "immediate") == 0) {
2037384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			int verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
2038384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			const char *verdict_name = NULL;
2039384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2040384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* No target specified but immediate shows up, this
2041384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 * is not the rule we are looking for.
2042384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 */
2043384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (strlen(jumpto) == 0)
2044384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
2045384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2046384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			switch(verdict) {
2047384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_ACCEPT:
2048384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "ACCEPT";
2049384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2050384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_DROP:
2051384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "DROP";
2052384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2053384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_RETURN:
2054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				verdict_name = "RETURN";
2055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2057384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2058384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Standard target? */
2059384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (verdict_name && strcmp(jumpto, verdict_name) != 0)
2060384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				return false;
2061384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2062384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return true;
2067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_del(struct nft_handle *h, struct nft_rule *r)
2071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
2073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
2074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
2075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, AF_INET,
2077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					NLM_F_ACK, h->seq);
2078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_nlmsg_build_payload(nlh, r);
2079384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2080384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_print_debug(r, nlh);
2081384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2082384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_talk(h, nlh, NULL, NULL);
2083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
2084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_talk:nft_rule_del");
2085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2087384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
2088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_check(struct nft_handle *h, const char *chain, const char *table,
2089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		 struct iptables_command_state *cs,
2090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		 bool delete, int rulenum, bool verbose)
2091384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
2093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list_iter *iter;
2094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
2095384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
2096384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int rule_ctr = 0;
2097384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	bool found = false;
2098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
2100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
2101384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot retrieve rule list from kernel\n");
2102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2103384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2104384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2105384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
2106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2107384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2108384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2111384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
2112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
2113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
2114384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
2115384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
2116384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
2117384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct iptables_command_state this = {};
2118384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2119384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
2120384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0) {
2121384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("different chain / table\n");
2122384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2124384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2125384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (rulenum >= 0) {
2126384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Delete by rule number case */
2127384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (rule_ctr != rulenum) {
2128384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				rule_ctr++;
2129384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2130384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2131384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2132384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Delete by matching rule case */
2133384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("comparing with... ");
2134384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef DEBUG_DEL
2135384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_print_save(r, 0);
2136384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
2137384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2138384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_to_iptables_command_state(r, &this);
2139384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!is_same(cs, &this))
2141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2143384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_matches(cs->matches, r)) {
2144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("matches not found\n");
2145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2146384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2147384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2148384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_target(cs->target, r)) {
2149384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("target not found\n");
2150384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (!find_immediate(r, cs->jumpto)) {
2154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				DEBUGP("immediate not found\n");
2155384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			found = true;
2159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
2160384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2161384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
2163384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2164384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2165384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (found) {
2166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		ret = 1;
2167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (delete) {
2169384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			DEBUGP("deleting rule\n");
2170384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			__nft_rule_del(h, r);
2171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_iter_destroy(iter);
2175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_free(list);
2176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == 0)
2178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
2179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
2181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2182384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2183384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_check(struct nft_handle *h, const char *chain,
2184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   const char *table, struct iptables_command_state *e,
2185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		   bool verbose)
2186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2187384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_check;
2188384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return __nft_rule_check(h, chain, table, e, false, -1, verbose);
2190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete(struct nft_handle *h, const char *chain,
2193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    const char *table, struct iptables_command_state *e,
2194384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    bool verbose)
2195384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2196384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete;
2197384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2198384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return __nft_rule_check(h, chain, table, e, true, -1, verbose);
2199384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2200384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete_num(struct nft_handle *h, const char *chain,
2202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			const char *table, int rulenum,
2203384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			bool verbose)
2204384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2205384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_delete_num;
2206384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2207384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return __nft_rule_check(h, chain, table, NULL, true, rulenum, verbose);
2208384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2209384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2210384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_replace(struct nft_handle *h, const char *chain,
2211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		     const char *table, struct iptables_command_state *cs,
2212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		     int rulenum, bool verbose)
2213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2214384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret;
2215384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_fn = nft_rule_replace;
2217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2218384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = __nft_rule_check(h, chain, table, NULL, true, rulenum, verbose);
2219384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret < 0)
2220384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return ret;
2221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2222384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* XXX needs to be inserted in position, this is appending */
2223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return nft_rule_add(h, chain, table, cs, true, verbose);
2224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2225384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/*
2227384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * iptables print output emulation
2228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso */
2229384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2230384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NUMERIC	0x0001
2231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NOCOUNTS	0x0002
2232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_KILOMEGAGIGA 0x0004
2233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_OPTIONS	0x0008
2234384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NOTABLE	0x0010
2235384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NOTARGET	0x0020
2236384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_VIA		0x0040
2237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NONEWLINE	0x0080
2238384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_LINENUMBERS 0x0100
2239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
2241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			| FMT_NUMERIC | FMT_NOTABLE)
2242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
2243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2245384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_num(uint64_t number, unsigned int format)
2246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_KILOMEGAGIGA) {
2248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (number > 99999) {
2249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			number = (number + 500) / 1000;
2250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (number > 9999) {
2251384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				number = (number + 500) / 1000;
2252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				if (number > 9999) {
2253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					number = (number + 500) / 1000;
2254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					if (number > 9999) {
2255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						number = (number + 500) / 1000;
2256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso						printf(FMT("%4lluT ","%lluT "), (unsigned long long)number);
2257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					}
2258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					else printf(FMT("%4lluG ","%lluG "), (unsigned long long)number);
2259384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				}
2260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				else printf(FMT("%4lluM ","%lluM "), (unsigned long long)number);
2261384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			} else
2262384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				printf(FMT("%4lluK ","%lluK "), (unsigned long long)number);
2263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else
2264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5llu ","%llu "), (unsigned long long)number);
2265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else
2266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%8llu ","%llu "), (unsigned long long)number);
2267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_header(unsigned int format, const char *chain, const char *pol,
2271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	     const struct xt_counters *counters, bool basechain, uint32_t refs)
2272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("Chain %s", chain);
2274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (basechain) {
2275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(" (policy %s", pol);
2276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (!(format & FMT_NOCOUNTS)) {
2277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputc(' ', stdout);
2278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_num(counters->pcnt, (format|FMT_NOTABLE));
2279384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("packets, ", stdout);
2280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_num(counters->bcnt, (format|FMT_NOTABLE));
2281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("bytes", stdout);
2282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(")\n");
2284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else {
2285384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(" (%u references)\n", refs);
2286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_LINENUMBERS)
2289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-4s ", "%s "), "num");
2290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOCOUNTS)) {
2291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (format & FMT_KILOMEGAGIGA) {
2292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5s ","%s "), "pkts");
2293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%5s ","%s "), "bytes");
2294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%8s ","%s "), "pkts");
2296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%10s ","%s "), "bytes");
2297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOTARGET))
2300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-9s ","%s "), "target");
2301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	fputs(" prot ", stdout);
2302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_OPTIONS)
2303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputs("opt", stdout);
2304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_VIA) {
2305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT(" %-6s ","%s "), "in");
2306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-6s ","%s "), "out");
2307384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2308384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(FMT(" %-19s ","%s "), "source");
2309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf(FMT(" %-19s "," %s "), "destination");
2310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	printf("\n");
2311384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2312384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_match(struct nft_rule_expr *expr, int numeric)
2315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t len;
2317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *match_name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME);
2318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *match_info = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len);
2319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_match *match =
2320384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		xtables_find_match(match_name, XTF_TRY_LOAD, NULL);
2321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_match *m =
2322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		calloc(1, sizeof(struct xt_entry_match) + len);
2323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* emulate struct xt_entry_match since ->print needs it */
2325384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy((void *)&m->data, match_info, len);
2326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (match) {
2328384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (match->print)
2329384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* FIXME missing first parameter */
2330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			match->print(NULL, m, numeric);
2331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
2332384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("%s ", match_name);
2333384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} else {
2334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (match_name[0])
2335384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("UNKNOWN match `%s' ", match_name);
2336384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2337384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(m);
2339384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2340384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2341384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2342384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_firewall(const struct iptables_command_state *cs, struct nft_rule *r,
2343384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	       unsigned int num, unsigned int format)
2344384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const struct xtables_target *target = NULL;
2346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *targname = NULL;
2347384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const void *targinfo = NULL;
2348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint8_t flags;
2349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[BUFSIZ];
2350384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr_iter *iter;
2351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_expr *expr;
2352384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct xt_entry_target *t;
2353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	size_t target_len = 0;
2354384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2355384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
2356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2361384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
2362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
2363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
2364384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
2365384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2366384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "target") == 0) {
2367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			targname = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
2368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			targinfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &target_len);
2369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
2370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else if (strcmp(name, "immediate") == 0) {
2371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			uint32_t verdict =
2372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT);
2373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			switch(verdict) {
2375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_ACCEPT:
2376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "ACCEPT";
2377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NF_DROP:
2379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "DROP";
2380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_RETURN:
2382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = "RETURN";
2383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_GOTO:
2385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN);
2386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				break;
2387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			case NFT_JUMP:
2388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				targname = nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN);
2389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			break;
2390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	flags = cs->fw.ip.flags;
2397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_LINENUMBERS)
2399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-4u ", "%u "), num);
2400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOCOUNTS)) {
2402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		print_num(cs->counters.pcnt, format);
2403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		print_num(cs->counters.bcnt, format);
2404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NOTARGET))
2407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-9s ", "%s "), targname ? targname : "");
2408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	fputc(cs->fw.ip.invflags & XT_INV_PROTO ? '!' : ' ', stdout);
2410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	{
2411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *pname =
2412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			proto_to_name(cs->fw.ip.proto, format&FMT_NUMERIC);
2413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (pname)
2414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%-5s", "%s "), pname);
2415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
2416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf(FMT("%-5hu", "%hu "), cs->fw.ip.proto);
2417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_OPTIONS) {
2420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (format & FMT_NOTABLE)
2421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			fputs("opt ", stdout);
2422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputc(cs->fw.ip.invflags & IPT_INV_FRAG ? '!' : '-', stdout);
2423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputc(flags & IPT_F_FRAG ? 'f' : '-', stdout);
2424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputc(' ', stdout);
2425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_VIA) {
2428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		char iface[IFNAMSIZ+2];
2429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.invflags & IPT_INV_VIA_IN) {
2430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			iface[0] = '!';
2431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			iface[1] = '\0';
2432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else iface[0] = '\0';
2434384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.iniface[0] != '\0') {
2436384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			strcat(iface, cs->fw.ip.iniface);
2437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (format & FMT_NUMERIC) strcat(iface, "*");
2439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else strcat(iface, "any");
2440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT(" %-6s ","in %s "), iface);
2441384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2442384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.invflags & IPT_INV_VIA_OUT) {
2443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			iface[0] = '!';
2444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			iface[1] = '\0';
2445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else iface[0] = '\0';
2447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (cs->fw.ip.outiface[0] != '\0') {
2449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			strcat(iface, cs->fw.ip.outiface);
2450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else if (format & FMT_NUMERIC) strcat(iface, "*");
2452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else strcat(iface, "any");
2453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-6s ","out %s "), iface);
2454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2456384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	fputc(cs->fw.ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
2457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (cs->fw.ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC))
2458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-19s ","%s "), "anywhere");
2459384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else {
2460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (format & FMT_NUMERIC)
2461384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.src));
2462384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
2463384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.src));
2464384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.smsk));
2465384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-19s ","%s "), buf);
2466384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2467384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2468384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	fputc(cs->fw.ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
2469384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (cs->fw.ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC))
2470384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-19s ","-> %s"), "anywhere");
2471384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else {
2472384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (format & FMT_NUMERIC)
2473384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.dst));
2474384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		else
2475384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.dst));
2476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.dmsk));
2477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf(FMT("%-19s ","-> %s"), buf);
2478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (format & FMT_NOTABLE)
2481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputs("  ", stdout);
2482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef IPT_F_GOTO
2484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if(cs->fw.ip.flags & IPT_F_GOTO)
2485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		printf("[goto] ");
2486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif
2487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_expr_iter_create(r);
2489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	expr = nft_rule_expr_iter_next(iter);
2495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (expr != NULL) {
2496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *name =
2497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
2498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(name, "match") == 0)
2500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			print_match(expr, format & FMT_NUMERIC);
2501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		expr = nft_rule_expr_iter_next(iter);
2503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_expr_iter_destroy(iter);
2505384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	t = calloc(1, sizeof(struct xt_entry_target) + target_len);
2507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (t == NULL)
2508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return;
2509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* emulate struct xt_entry_match since ->print needs it */
2511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	memcpy((void *)&t->data, targinfo, target_len);
2512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (targname) {
2514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		target = xtables_find_target(targname, XTF_TRY_LOAD);
2515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (target) {
2516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (target->print)
2517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				/* FIXME missing first parameter */
2518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				target->print(NULL, t, format & FMT_NUMERIC);
2519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else
2520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("[%ld bytes of unknown target data] ",
2521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				target_len);
2522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	free(t);
2524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (!(format & FMT_NONEWLINE))
2526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		fputc('\n', stdout);
2527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
2530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_list(struct nft_handle *h, struct nft_chain *c, const char *table,
2531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int rulenum, unsigned int format,
2532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		void (*cb)(const struct iptables_command_state *cs,
2533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			   struct nft_rule *r, unsigned int num,
2534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			   unsigned int format))
2535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list *list;
2537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule_list_iter *iter;
2538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_rule *r;
2539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int rule_ctr = 0, ret = 0;
2540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	const char *chain = nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_rule_list_get(h);
2543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (list == NULL) {
2544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot retrieve rule list from kernel\n");
2545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_rule_list_iter_create(list);
2549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	r = nft_rule_list_iter_next(iter);
2555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (r != NULL) {
2556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_table =
2557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE);
2558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *rule_chain =
2559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN);
2560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		rule_ctr++;
2562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, rule_table) != 0 ||
2564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    strcmp(chain, rule_chain) != 0)
2565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (rulenum > 0) {
2568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* List by rule number case */
2569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (rule_ctr != rulenum) {
2570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				rule_ctr++;
2571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				goto next;
2572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			}
2573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			struct iptables_command_state cs = {};
2575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			/* Show all rules case */
2576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_rule_to_iptables_command_state(r, &cs);
2577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			cb(&cs, r, rule_ctr, format);
2579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		r = nft_rule_list_iter_next(iter);
2582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_iter_destroy(iter);
2585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_free(list);
2586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == 0)
2588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		errno = ENOENT;
2589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret;
2591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list(struct nft_handle *h, const char *chain, const char *table,
2594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		  int rulenum, unsigned int format)
2595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
2597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
2599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
2601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
2615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
2616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t refs =
2617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_USE);
2618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		struct xt_counters ctrs = {
2619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			.pcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS),
2620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			.bcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES),
2621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		};
2622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		bool basechain = false;
2623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM))
2625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			basechain = true;
2626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
2630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		print_header(format, chain_name, policy_name[policy], &ctrs,
2633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			     basechain, refs);
2634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* this is a base chain */
2636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM)) {
2637384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			__nft_rule_list(h, c, table, rulenum, format,
2638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					print_firewall);
2639384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
2645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void
2650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusolist_save(const struct iptables_command_state *cs, struct nft_rule *r,
2651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  unsigned int num, unsigned int format)
2652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_print_save(r, !(format & FMT_NOCOUNTS));
2654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int
2657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_list_chain_save(struct nft_handle *h, const char *table,
2658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			 struct nft_chain_list *list, int counters)
2659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
2662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2670384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		uint32_t policy =
2676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
2677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		/* this is a base chain */
2682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM)) {
2683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-P %s %s", chain_name, policy_name[policy]);
2684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			if (counters) {
2686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				printf(" -c %lu %lu\n",
2687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS),
2688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso					nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES));
2689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			} else
2690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				printf("\n");
2691384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		} else {
2692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			printf("-N %s\n", chain_name);
2693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		}
2694384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2700384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list_save(struct nft_handle *h, const char *chain,
2702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		       const char *table, int rulenum, int counters)
2703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list *list;
2705384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain_list_iter *iter;
2706384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nft_chain *c;
2707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	list = nft_chain_dump(h);
2709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Dump policies and custom chains first */
2711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_rule_list_chain_save(h, table, list, counters);
2712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	/* Now dump out rules in this table */
2714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	iter = nft_chain_list_iter_create(list);
2715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (iter == NULL) {
2716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		DEBUGP("cannot allocate rule list iterator\n");
2717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	c = nft_chain_list_iter_next(iter);
2721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	while (c != NULL) {
2722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_table =
2723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
2724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *chain_name =
2725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
2726384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (strcmp(table, chain_table) != 0)
2728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if (chain && strcmp(chain, chain_name) != 0)
2730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			goto next;
2731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		__nft_rule_list(h, c, table, rulenum,
2733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso				counters ? 0 : FMT_NOCOUNTS, list_save);
2734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext:
2735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		c = nft_chain_list_iter_next(iter);
2736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2737384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2738384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nft_chain_list_free(list);
2739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return 1;
2741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_compatible_revision(const char *name, uint8_t rev, int opt)
2744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct mnl_socket *nl;
2746384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	char buf[MNL_SOCKET_BUFFER_SIZE];
2747384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nlmsghdr *nlh;
2748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	uint32_t portid, seq, type;
2749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	int ret = 0;
2750384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2751384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (opt == IPT_SO_GET_REVISION_MATCH)
2752384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 0;
2753384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	else
2754384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		type = 1;
2755384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2756384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh = mnl_nlmsg_put_header(buf);
2757384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_type = (NFNL_SUBSYS_NFT_COMPAT << 8) | NFNL_MSG_COMPAT_GET;
2758384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
2759384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nlh->nlmsg_seq = seq = time(NULL);
2760384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2761384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
2762384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->nfgen_family = AF_INET;
2763384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->version = NFNETLINK_V0;
2764384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nfg->res_id = 0;
2765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2766384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_strz(nlh, NFTA_COMPAT_NAME, name);
2767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_REV, htonl(rev));
2768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_attr_put_u32(nlh, NFTA_COMPAT_TYPE, htonl(type));
2769384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2770384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	DEBUGP("requesting `%s' rev=%d type=%d via nft_compat\n",
2771384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		name, rev, type);
2772384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2773384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	nl = mnl_socket_open(NETLINK_NETFILTER);
2774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (nl == NULL) {
2775384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_open");
2776384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		return 0;
2777384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2778384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2779384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
2780384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_bind");
2781384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2783384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	portid = mnl_socket_get_portid(nl);
2784384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2785384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
2786384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_send");
2787384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2788384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2789384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2790384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
2791384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
2792384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_socket_recvfrom");
2793384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2794384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2795384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2796384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
2797384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	if (ret == -1) {
2798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		perror("mnl_cb_run");
2799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		goto err;
2800384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2802384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr:
2803384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	mnl_socket_close(nl);
2804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return ret < 0 ? 0 : 1;
2806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/* Translates errno numbers into more human-readable form than strerror. */
2809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoconst char *nft_strerror(int err)
2810384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{
2811384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	unsigned int i;
2812384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	static struct table_struct {
2813384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		void *fn;
2814384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		int err;
2815384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		const char *message;
2816384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	} table[] =
2817384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  {
2818384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, ENOTEMPTY, "Chain is not empty" },
2819384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EINVAL, "Can't delete built-in chain" },
2820384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_del, EMLINK,
2821384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Can't delete chain with references left" },
2822384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_user_add, EEXIST, "Chain already exists" },
2823384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, E2BIG, "Index of insertion too big" },
2824384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_replace, E2BIG, "Index of replacement too big" },
2825384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete_num, E2BIG, "Index of deletion too big" },
2826384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/*	    { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
2827384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, */
2828384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, ELOOP, "Loop found in table" },
2829384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_add, EINVAL, "Target problem" },
2830384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    /* ENOENT for DELETE probably means no matching rule */
2831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_rule_delete, ENOENT,
2832384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	      "Bad rule (does a matching rule exist in that chain?)" },
2833384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, ENOENT, "Bad built-in chain name" },
2834384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { nft_chain_set, EINVAL, "Bad policy name" },
2835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, EPERM, "Permission denied (you must be root)" },
2836384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, 0, "Incompatible with this kernel" },
2837384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
2838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOSYS, "Will be implemented real soon.  I promise ;)" },
2839384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOMEM, "Memory allocation problem" },
2840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	    { NULL, ENOENT, "No chain/target/match by that name" },
2841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	  };
2842384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2843384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
2844384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		if ((!table[i].fn || table[i].fn == nft_fn)
2845384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso		    && table[i].err == err)
2846384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso			return table[i].message;
2847384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	}
2848384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso
2849384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso	return strerror(err);
2850384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}
2851