xtables.c revision b32b361a725c8fe3a3aa494e6cdec09a80785aac
1ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman/*
2ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman * (C) 2000-2006 by the netfilter coreteam <coreteam@netfilter.org>:
3ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *
4ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *	This program is free software; you can redistribute it and/or modify
5ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *	it under the terms of the GNU General Public License as published by
6ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *	the Free Software Foundation; either version 2 of the License, or
7ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *	(at your option) any later version.
8ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *
9ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *	This program is distributed in the hope that it will be useful,
10ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *	but WITHOUT ANY WARRANTY; without even the implied warranty of
11ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *	GNU General Public License for more details.
13ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *
14ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *	You should have received a copy of the GNU General Public License
15ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *	along with this program; if not, write to the Free Software
16ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman */
18ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
19ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <errno.h>
20f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor#include <fcntl.h>
21f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor#include <netdb.h>
22f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor#include <stdarg.h>
23f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor#include <stdbool.h>
24ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <stdio.h>
25f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor#include <stdlib.h>
26f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor#include <string.h>
27ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <unistd.h>
28ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <sys/socket.h>
29f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor#include <sys/stat.h>
30ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <sys/statfs.h>
31ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <sys/types.h>
32ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <sys/wait.h>
33ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <arpa/inet.h>
34ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <linux/magic.h> /* for PROC_SUPER_MAGIC */
35ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
36ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <xtables.h>
37ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */
38ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <linux/netfilter_ipv4/ip_tables.h>
39ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <linux/netfilter_ipv6/ip6_tables.h>
40ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <libiptc/libxtc.h>
41ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
42ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#ifndef NO_SHARED_LIBS
43ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <dlfcn.h>
44ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#endif
45ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */
467e4c2b80178ee77f5c3ec4083c1310833621d7f2Jan Berkel#	define IPT_SO_GET_REVISION_MATCH	(IPT_BASE_CTL + 2)
47f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor#	define IPT_SO_GET_REVISION_TARGET	(IPT_BASE_CTL + 3)
487e4c2b80178ee77f5c3ec4083c1310833621d7f2Jan Berkel#endif
49ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */
50ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#	define IP6T_SO_GET_REVISION_MATCH	68
51ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#	define IP6T_SO_GET_REVISION_TARGET	69
52ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#endif
53ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include <getopt.h>
54ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include "iptables/internal.h"
55ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#include "xshared.h"
56ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
57ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#define NPROTO	255
58ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
59ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#ifndef PROC_SYS_MODPROBE
60ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
61ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#endif
62ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
63ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman/* we need this for ip6?tables-restore.  ip6?tables-restore.c sets line to the
64ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman * current line of the input file, in order  to give a more precise error
65ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman * message.  ip6?tables itself doesn't need this, so it is initialized to the
66ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman * magic number of -1 */
67ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanint line = -1;
68ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
69ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
70ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
71ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstruct xtables_globals *xt_params = NULL;
72ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
73ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...)
74ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
75ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	va_list args;
76ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
77ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	va_start(args, msg);
78ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version);
79ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	vfprintf(stderr, msg, args);
80ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	va_end(args);
81ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	fprintf(stderr, "\n");
82ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	exit(status);
83ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
84ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
85ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanvoid xtables_free_opts(int unused)
86ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
87ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (xt_params->opts != xt_params->orig_opts) {
88ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		free(xt_params->opts);
89ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		xt_params->opts = NULL;
90ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
91ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
92ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
93ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstruct option *xtables_merge_options(struct option *orig_opts,
94ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman				     struct option *oldopts,
95ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman				     const struct option *newopts,
96ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman				     unsigned int *option_offset)
97ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
98ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	unsigned int num_oold = 0, num_old = 0, num_new = 0, i;
99ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	struct option *merge, *mp;
100ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
101ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (newopts == NULL)
102ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		return oldopts;
103ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
104ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ;
105ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (oldopts != NULL)
106ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		for (num_old = 0; oldopts[num_old].name; num_old++) ;
107ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	for (num_new = 0; newopts[num_new].name; num_new++) ;
108ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
109ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	/*
110ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 * Since @oldopts also has @orig_opts already (and does so at the
111ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 * start), skip these entries.
112ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 */
113ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	oldopts += num_oold;
114ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	num_old -= num_oold;
115ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
116ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1));
117ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (merge == NULL)
118ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		return NULL;
119ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
120ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	/* Let the base options -[ADI...] have precedence over everything */
121ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	memcpy(merge, orig_opts, sizeof(*mp) * num_oold);
122ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	mp = merge + num_oold;
123ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
124ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	/* Second, the new options */
125ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	xt_params->option_offset += XT_OPTION_OFFSET_SCALE;
126ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	*option_offset = xt_params->option_offset;
127ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	memcpy(mp, newopts, sizeof(*mp) * num_new);
128ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
129ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	for (i = 0; i < num_new; ++i, ++mp)
130ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		mp->val += *option_offset;
131ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
132ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	/* Third, the old options */
133ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	memcpy(mp, oldopts, sizeof(*mp) * num_old);
134ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	mp += num_old;
135ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	xtables_free_opts(0);
136ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
137ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	/* Clear trailing entry */
138ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	memset(mp, 0, sizeof(*mp));
139ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	return merge;
140ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
141ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
142ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstatic const struct xtables_afinfo afinfo_ipv4 = {
143ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.kmod          = "ip_tables",
144ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.proc_exists   = "/proc/net/ip_tables_names",
145ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.libprefix     = "libipt_",
146ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.family	       = NFPROTO_IPV4,
147ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.ipproto       = IPPROTO_IP,
148ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.so_rev_match  = IPT_SO_GET_REVISION_MATCH,
149ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.so_rev_target = IPT_SO_GET_REVISION_TARGET,
150ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman};
151ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
152ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstatic const struct xtables_afinfo afinfo_ipv6 = {
153ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.kmod          = "ip6_tables",
154ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.proc_exists   = "/proc/net/ip6_tables_names",
155ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.libprefix     = "libip6t_",
156ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.family        = NFPROTO_IPV6,
157ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.ipproto       = IPPROTO_IPV6,
158ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.so_rev_match  = IP6T_SO_GET_REVISION_MATCH,
159ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	.so_rev_target = IP6T_SO_GET_REVISION_TARGET,
160ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman};
161ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
162ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanconst struct xtables_afinfo *afinfo;
163ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
164ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman/* Search path for Xtables .so files */
165ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstatic const char *xtables_libdir;
166ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
167ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman/* the path to command to load kernel module */
168ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanconst char *xtables_modprobe_program;
169ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
170ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman/* Keep track of matches/targets pending full registration: linked lists. */
171ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstruct xtables_match *xtables_pending_matches;
172ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstruct xtables_target *xtables_pending_targets;
173ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
174ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman/* Keep track of fully registered external matches/targets: linked lists. */
175ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstruct xtables_match *xtables_matches;
176ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstruct xtables_target *xtables_targets;
177ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
178ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman/* Fully register a match/target which was previously partially registered. */
179ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstatic void xtables_fully_register_pending_match(struct xtables_match *me);
180ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstatic void xtables_fully_register_pending_target(struct xtables_target *me);
181ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
182ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanvoid xtables_init(void)
183ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
184ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	xtables_libdir = getenv("XTABLES_LIBDIR");
185ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (xtables_libdir != NULL)
186ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		return;
187ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	xtables_libdir = getenv("IPTABLES_LIB_DIR");
188ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (xtables_libdir != NULL) {
189ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, "
190ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		        "use XTABLES_LIBDIR.\n");
191ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		return;
192ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
193ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	/*
194ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 * Well yes, IP6TABLES_LIB_DIR is of lower priority over
195ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok
196ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 * for these env vars are deprecated anyhow, and in light of the
197ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 * (shared) libxt_*.so files, makes less sense to have
198ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR.
199ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 */
200ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	xtables_libdir = getenv("IP6TABLES_LIB_DIR");
201ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (xtables_libdir != NULL) {
202ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, "
203ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		        "use XTABLES_LIBDIR.\n");
204ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		return;
205ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
206ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	xtables_libdir = XTABLES_LIBDIR;
207ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
208ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
209ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanvoid xtables_set_nfproto(uint8_t nfproto)
210ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
211ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	switch (nfproto) {
212ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	case NFPROTO_IPV4:
213ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		afinfo = &afinfo_ipv4;
214ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		break;
215ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	case NFPROTO_IPV6:
216ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		afinfo = &afinfo_ipv6;
217ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		break;
218ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	default:
219ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n",
220ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		        __func__);
221ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
222ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
223ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
224ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman/**
225ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman * xtables_set_params - set the global parameters used by xtables
226ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman * @xtp:	input xtables_globals structure
227ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *
228ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman * The app is expected to pass a valid xtables_globals data-filled
229ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman * with proper values
230ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman * @xtp cannot be NULL
231ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman *
232ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman * Returns -1 on failure to set and 0 on success
233ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman */
234ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanint xtables_set_params(struct xtables_globals *xtp)
235ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
236ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (!xtp) {
237ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		fprintf(stderr, "%s: Illegal global params\n",__func__);
238ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		return -1;
239ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
240ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
241ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	xt_params = xtp;
242ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
243ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (!xt_params->exit_err)
244ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		xt_params->exit_err = basic_exit_err;
245ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
246ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	return 0;
247ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
248ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
249ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanint xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto)
250ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
251ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	xtables_init();
252ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	xtables_set_nfproto(nfproto);
253ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	return xtables_set_params(xtp);
254ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
255ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
256ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman/**
257ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman * xtables_*alloc - wrappers that exit on failure
258ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman */
259ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanvoid *xtables_calloc(size_t count, size_t size)
260ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
261ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	void *p;
262ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
263ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if ((p = calloc(count, size)) == NULL) {
264ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		perror("ip[6]tables: calloc failed");
265ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		exit(1);
266ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
267ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
268ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	return p;
269ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
270ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
271ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanvoid *xtables_malloc(size_t size)
272ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
273ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	void *p;
274ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
275ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if ((p = malloc(size)) == NULL) {
276ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		perror("ip[6]tables: malloc failed");
277ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		exit(1);
278ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
279ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
280ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	return p;
281ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
282ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
283ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanvoid *xtables_realloc(void *ptr, size_t size)
284ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
285ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	void *p;
286ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
287ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if ((p = realloc(ptr, size)) == NULL) {
288ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		perror("ip[6]tables: realloc failed");
289ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		exit(1);
290ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
291ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
292ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	return p;
293ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
294ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
295ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstatic char *get_modprobe(void)
296ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
297ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	int procfile;
298ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	char *ret;
299ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
300ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman#define PROCFILE_BUFSIZ	1024
301ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
302ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (procfile < 0)
303ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		return NULL;
304ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) {
305ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		fprintf(stderr, "Could not set close on exec: %s\n",
306ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman			strerror(errno));
307ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		exit(1);
308ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
309ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
310ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	ret = malloc(PROCFILE_BUFSIZ);
311ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (ret) {
312ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		memset(ret, 0, PROCFILE_BUFSIZ);
313ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
314ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		case -1: goto fail;
315ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
316ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		}
317ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		if (ret[strlen(ret)-1]=='\n')
318ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman			ret[strlen(ret)-1]=0;
319ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		close(procfile);
320ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		return ret;
321ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
322ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman fail:
323ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	free(ret);
324ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	close(procfile);
325ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	return NULL;
326ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
327ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
328ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanint xtables_insmod(const char *modname, const char *modprobe, bool quiet)
329ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
330ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	char *buf = NULL;
331ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	char *argv[4];
332ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	int status;
333ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
334ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	/* If they don't explicitly set it, read out of kernel */
335ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (!modprobe) {
336ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		buf = get_modprobe();
337ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		if (!buf)
338ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman			return -1;
339ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		modprobe = buf;
340ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
341ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
342ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	/*
343ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 * Need to flush the buffer, or the child may output it again
344ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 * when switching the program thru execv.
345ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	 */
346ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	fflush(stdout);
347ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
348ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	switch (vfork()) {
349ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	case 0:
350ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		argv[0] = (char *)modprobe;
351ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		argv[1] = (char *)modname;
352ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		if (quiet) {
353ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman			argv[2] = "-q";
354ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman			argv[3] = NULL;
355ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		} else {
356ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman			argv[2] = NULL;
357ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman			argv[3] = NULL;
358ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		}
359ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		execv(argv[0], argv);
360ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
361ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		/* not usually reached */
362ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		exit(1);
363ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	case -1:
364ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		return -1;
365ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
366ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	default: /* parent */
367ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		wait(&status);
368ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	}
369ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
370ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	free(buf);
371ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
372ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman		return 0;
3737e4c2b80178ee77f5c3ec4083c1310833621d7f2Jan Berkel	return -1;
374ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman}
375ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
376ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman/* return true if a given file exists within procfs */
377ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanstatic bool proc_file_exists(const char *filename)
378ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
379ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	struct stat s;
380ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	struct statfs f;
381ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
382f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor	if (lstat(filename, &s))
383f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor		return false;
384f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor	if (!S_ISREG(s.st_mode))
3857e4c2b80178ee77f5c3ec4083c1310833621d7f2Jan Berkel		return false;
3867e4c2b80178ee77f5c3ec4083c1310833621d7f2Jan Berkel	if (statfs(filename, &f))
3877e4c2b80178ee77f5c3ec4083c1310833621d7f2Jan Berkel		return false;
3887e4c2b80178ee77f5c3ec4083c1310833621d7f2Jan Berkel	if (f.f_type != PROC_SUPER_MAGIC)
3897e4c2b80178ee77f5c3ec4083c1310833621d7f2Jan Berkel		return false;
390f5937727530ccf761ae1f35cb3888cb25cd3be2fRobert Taylor	return true;
3917e4c2b80178ee77f5c3ec4083c1310833621d7f2Jan Berkel}
392ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman
393ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowmanint xtables_load_ko(const char *modprobe, bool quiet)
394ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman{
395ab6d77189eef0b311133e648b979ecf1a564adbfEric Bowman	static bool loaded = false;
396	int ret;
397
398	if (loaded)
399		return 0;
400
401	if (proc_file_exists(afinfo->proc_exists)) {
402		loaded = true;
403		return 0;
404	};
405
406	ret = xtables_insmod(afinfo->kmod, modprobe, quiet);
407	if (ret == 0)
408		loaded = true;
409
410	return ret;
411}
412
413/**
414 * xtables_strtou{i,l} - string to number conversion
415 * @s:	input string
416 * @end:	like strtoul's "end" pointer
417 * @value:	pointer for result
418 * @min:	minimum accepted value
419 * @max:	maximum accepted value
420 *
421 * If @end is NULL, we assume the caller wants a "strict strtoul", and hence
422 * "15a" is rejected.
423 * In either case, the value obtained is compared for min-max compliance.
424 * Base is always 0, i.e. autodetect depending on @s.
425 *
426 * Returns true/false whether number was accepted. On failure, *value has
427 * undefined contents.
428 */
429bool xtables_strtoul(const char *s, char **end, unsigned long *value,
430                     unsigned long min, unsigned long max)
431{
432	unsigned long v;
433	char *my_end;
434
435	errno = 0;
436	v = strtoul(s, &my_end, 0);
437
438	if (my_end == s)
439		return false;
440	if (end != NULL)
441		*end = my_end;
442
443	if (errno != ERANGE && min <= v && (max == 0 || v <= max)) {
444		if (value != NULL)
445			*value = v;
446		if (end == NULL)
447			return *my_end == '\0';
448		return true;
449	}
450
451	return false;
452}
453
454bool xtables_strtoui(const char *s, char **end, unsigned int *value,
455                     unsigned int min, unsigned int max)
456{
457	unsigned long v;
458	bool ret;
459
460	ret = xtables_strtoul(s, end, &v, min, max);
461	if (value != NULL)
462		*value = v;
463	return ret;
464}
465
466int xtables_service_to_port(const char *name, const char *proto)
467{
468	struct servent *service;
469
470	if ((service = getservbyname(name, proto)) != NULL)
471		return ntohs((unsigned short) service->s_port);
472
473	return -1;
474}
475
476uint16_t xtables_parse_port(const char *port, const char *proto)
477{
478	unsigned int portnum;
479
480	if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) ||
481	    (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1)
482		return portnum;
483
484	xt_params->exit_err(PARAMETER_PROBLEM,
485		   "invalid port/service `%s' specified", port);
486}
487
488void xtables_parse_interface(const char *arg, char *vianame,
489			     unsigned char *mask)
490{
491	unsigned int vialen = strlen(arg);
492	unsigned int i;
493
494	memset(mask, 0, IFNAMSIZ);
495	memset(vianame, 0, IFNAMSIZ);
496
497	if (vialen + 1 > IFNAMSIZ)
498		xt_params->exit_err(PARAMETER_PROBLEM,
499			   "interface name `%s' must be shorter than IFNAMSIZ"
500			   " (%i)", arg, IFNAMSIZ-1);
501
502	strcpy(vianame, arg);
503	if (vialen == 0)
504		memset(mask, 0, IFNAMSIZ);
505	else if (vianame[vialen - 1] == '+') {
506		memset(mask, 0xFF, vialen - 1);
507		memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
508		/* Don't remove `+' here! -HW */
509	} else {
510		/* Include nul-terminator in match */
511		memset(mask, 0xFF, vialen + 1);
512		memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
513		for (i = 0; vianame[i]; i++) {
514			if (vianame[i] == '/' ||
515			    vianame[i] == ' ') {
516				fprintf(stderr,
517					"Warning: weird character in interface"
518					" `%s' ('/' and ' ' are not allowed by the kernel).\n",
519					vianame);
520				break;
521			}
522		}
523	}
524}
525
526#ifndef NO_SHARED_LIBS
527static void *load_extension(const char *search_path, const char *af_prefix,
528    const char *name, bool is_target)
529{
530	const char *all_prefixes[] = {"libxt_", af_prefix, NULL};
531	const char **prefix;
532	const char *dir = search_path, *next;
533	void *ptr = NULL;
534	struct stat sb;
535	char path[256];
536
537	do {
538		next = strchr(dir, ':');
539		if (next == NULL)
540			next = dir + strlen(dir);
541
542		for (prefix = all_prefixes; *prefix != NULL; ++prefix) {
543			snprintf(path, sizeof(path), "%.*s/%s%s.so",
544			         (unsigned int)(next - dir), dir,
545			         *prefix, name);
546
547			if (stat(path, &sb) != 0) {
548				if (errno == ENOENT)
549					continue;
550				fprintf(stderr, "%s: %s\n", path,
551					strerror(errno));
552				return NULL;
553			}
554			if (dlopen(path, RTLD_NOW) == NULL) {
555				fprintf(stderr, "%s: %s\n", path, dlerror());
556				break;
557			}
558
559			if (is_target)
560				ptr = xtables_find_target(name, XTF_DONT_LOAD);
561			else
562				ptr = xtables_find_match(name,
563				      XTF_DONT_LOAD, NULL);
564
565			if (ptr != NULL)
566				return ptr;
567
568			fprintf(stderr, "%s: no \"%s\" extension found for "
569				"this protocol\n", path, name);
570			errno = ENOENT;
571			return NULL;
572		}
573		dir = next + 1;
574	} while (*next != '\0');
575
576	return NULL;
577}
578#endif
579
580struct xtables_match *
581xtables_find_match(const char *name, enum xtables_tryload tryload,
582		   struct xtables_rule_match **matches)
583{
584	struct xtables_match **dptr;
585	struct xtables_match *ptr;
586	const char *icmp6 = "icmp6";
587
588	if (strlen(name) >= XT_EXTENSION_MAXNAMELEN)
589		xtables_error(PARAMETER_PROBLEM,
590			   "Invalid match name \"%s\" (%u chars max)",
591			   name, XT_EXTENSION_MAXNAMELEN - 1);
592
593	/* This is ugly as hell. Nonetheless, there is no way of changing
594	 * this without hurting backwards compatibility */
595	if ( (strcmp(name,"icmpv6") == 0) ||
596	     (strcmp(name,"ipv6-icmp") == 0) ||
597	     (strcmp(name,"icmp6") == 0) )
598		name = icmp6;
599
600	/* Trigger delayed initialization */
601	for (dptr = &xtables_pending_matches; *dptr; ) {
602		if (strcmp(name, (*dptr)->name) == 0) {
603			ptr = *dptr;
604			*dptr = (*dptr)->next;
605			ptr->next = NULL;
606			xtables_fully_register_pending_match(ptr);
607		} else {
608			dptr = &((*dptr)->next);
609		}
610	}
611
612	for (ptr = xtables_matches; ptr; ptr = ptr->next) {
613		if (strcmp(name, ptr->name) == 0) {
614			struct xtables_match *clone;
615
616			/* First match of this type: */
617			if (ptr->m == NULL)
618				break;
619
620			/* Second and subsequent clones */
621			clone = xtables_malloc(sizeof(struct xtables_match));
622			memcpy(clone, ptr, sizeof(struct xtables_match));
623			clone->mflags = 0;
624			/* This is a clone: */
625			clone->next = clone;
626
627			ptr = clone;
628			break;
629		}
630	}
631
632#ifndef NO_SHARED_LIBS
633	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
634		ptr = load_extension(xtables_libdir, afinfo->libprefix,
635		      name, false);
636
637		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
638			xt_params->exit_err(PARAMETER_PROBLEM,
639				   "Couldn't load match `%s':%s\n",
640				   name, strerror(errno));
641	}
642#else
643	if (ptr && !ptr->loaded) {
644		if (tryload != XTF_DONT_LOAD)
645			ptr->loaded = 1;
646		else
647			ptr = NULL;
648	}
649	if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) {
650		xt_params->exit_err(PARAMETER_PROBLEM,
651			   "Couldn't find match `%s'\n", name);
652	}
653#endif
654
655	if (ptr && matches) {
656		struct xtables_rule_match **i;
657		struct xtables_rule_match *newentry;
658
659		newentry = xtables_malloc(sizeof(struct xtables_rule_match));
660
661		for (i = matches; *i; i = &(*i)->next) {
662			if (strcmp(name, (*i)->match->name) == 0)
663				(*i)->completed = true;
664		}
665		newentry->match = ptr;
666		newentry->completed = false;
667		newentry->next = NULL;
668		*i = newentry;
669	}
670
671	return ptr;
672}
673
674struct xtables_target *
675xtables_find_target(const char *name, enum xtables_tryload tryload)
676{
677	struct xtables_target **dptr;
678	struct xtables_target *ptr;
679
680	/* Standard target? */
681	if (strcmp(name, "") == 0
682	    || strcmp(name, XTC_LABEL_ACCEPT) == 0
683	    || strcmp(name, XTC_LABEL_DROP) == 0
684	    || strcmp(name, XTC_LABEL_QUEUE) == 0
685	    || strcmp(name, XTC_LABEL_RETURN) == 0)
686		name = "standard";
687
688	/* Trigger delayed initialization */
689	for (dptr = &xtables_pending_targets; *dptr; ) {
690		if (strcmp(name, (*dptr)->name) == 0) {
691			ptr = *dptr;
692			*dptr = (*dptr)->next;
693			ptr->next = NULL;
694			xtables_fully_register_pending_target(ptr);
695		} else {
696			dptr = &((*dptr)->next);
697		}
698	}
699
700	for (ptr = xtables_targets; ptr; ptr = ptr->next) {
701		if (strcmp(name, ptr->name) == 0)
702			break;
703	}
704
705#ifndef NO_SHARED_LIBS
706	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
707		ptr = load_extension(xtables_libdir, afinfo->libprefix,
708		      name, true);
709
710		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
711			xt_params->exit_err(PARAMETER_PROBLEM,
712				   "Couldn't load target `%s':%s\n",
713				   name, strerror(errno));
714	}
715#else
716	if (ptr && !ptr->loaded) {
717		if (tryload != XTF_DONT_LOAD)
718			ptr->loaded = 1;
719		else
720			ptr = NULL;
721	}
722	if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) {
723		xt_params->exit_err(PARAMETER_PROBLEM,
724			   "Couldn't find target `%s'\n", name);
725	}
726#endif
727
728	if (ptr)
729		ptr->used = 1;
730
731	return ptr;
732}
733
734static int compatible_revision(const char *name, uint8_t revision, int opt)
735{
736	struct xt_get_revision rev;
737	socklen_t s = sizeof(rev);
738	int max_rev, sockfd;
739
740	sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);
741	if (sockfd < 0) {
742		if (errno == EPERM) {
743			/* revision 0 is always supported. */
744			if (revision != 0)
745				fprintf(stderr, "Could not determine whether "
746						"revision %u is supported, "
747						"assuming it is.\n",
748					revision);
749			return 1;
750		}
751		fprintf(stderr, "Could not open socket to kernel: %s\n",
752			strerror(errno));
753		exit(1);
754	}
755
756	if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) {
757		fprintf(stderr, "Could not set close on exec: %s\n",
758			strerror(errno));
759		exit(1);
760	}
761
762	xtables_load_ko(xtables_modprobe_program, true);
763
764	strcpy(rev.name, name);
765	rev.revision = revision;
766
767	max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s);
768	if (max_rev < 0) {
769		/* Definitely don't support this? */
770		if (errno == ENOENT || errno == EPROTONOSUPPORT) {
771			close(sockfd);
772			return 0;
773		} else if (errno == ENOPROTOOPT) {
774			close(sockfd);
775			/* Assume only revision 0 support (old kernel) */
776			return (revision == 0);
777		} else {
778			fprintf(stderr, "getsockopt failed strangely: %s\n",
779				strerror(errno));
780			exit(1);
781		}
782	}
783	close(sockfd);
784	return 1;
785}
786
787
788static int compatible_match_revision(const char *name, uint8_t revision)
789{
790	return compatible_revision(name, revision, afinfo->so_rev_match);
791}
792
793static int compatible_target_revision(const char *name, uint8_t revision)
794{
795	return compatible_revision(name, revision, afinfo->so_rev_target);
796}
797
798static void xtables_check_options(const char *name, const struct option *opt)
799{
800	for (; opt->name != NULL; ++opt)
801		if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) {
802			fprintf(stderr, "%s: Extension %s uses invalid "
803			        "option value %d\n",xt_params->program_name,
804			        name, opt->val);
805			exit(1);
806		}
807}
808
809void xtables_register_match(struct xtables_match *me)
810{
811	if (me->version == NULL) {
812		fprintf(stderr, "%s: match %s<%u> is missing a version\n",
813		        xt_params->program_name, me->name, me->revision);
814		exit(1);
815	}
816	if (strcmp(me->version, XTABLES_VERSION) != 0) {
817		fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
818		        "but \"%s\" is required.\n",
819			xt_params->program_name, me->name,
820			me->version, XTABLES_VERSION);
821		exit(1);
822	}
823
824	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
825		fprintf(stderr, "%s: match `%s' has invalid name\n",
826			xt_params->program_name, me->name);
827		exit(1);
828	}
829
830	if (me->family >= NPROTO) {
831		fprintf(stderr,
832			"%s: BUG: match %s has invalid protocol family\n",
833			xt_params->program_name, me->name);
834		exit(1);
835	}
836
837	if (me->x6_options != NULL)
838		xtables_option_metavalidate(me->name, me->x6_options);
839	if (me->extra_opts != NULL)
840		xtables_check_options(me->name, me->extra_opts);
841
842	/* ignore not interested match */
843	if (me->family != afinfo->family && me->family != AF_UNSPEC)
844		return;
845
846	/* place on linked list of matches pending full registration */
847	me->next = xtables_pending_matches;
848	xtables_pending_matches = me;
849}
850
851static void xtables_fully_register_pending_match(struct xtables_match *me)
852{
853	struct xtables_match **i, *old;
854
855	old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
856	if (old) {
857		if (old->revision == me->revision &&
858		    old->family == me->family) {
859			fprintf(stderr,
860				"%s: match `%s' already registered.\n",
861				xt_params->program_name, me->name);
862			exit(1);
863		}
864
865		/* Now we have two (or more) options, check compatibility. */
866		if (compatible_match_revision(old->name, old->revision)
867		    && old->revision > me->revision)
868			return;
869
870		/* See if new match can be used. */
871		if (!compatible_match_revision(me->name, me->revision))
872			return;
873
874		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
875		if (old->revision == me->revision && me->family == AF_UNSPEC)
876			return;
877
878		/* Delete old one. */
879		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
880		*i = old->next;
881	}
882
883	if (me->size != XT_ALIGN(me->size)) {
884		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
885		        xt_params->program_name, me->name,
886		        (unsigned int)me->size);
887		exit(1);
888	}
889
890	/* Append to list. */
891	for (i = &xtables_matches; *i; i = &(*i)->next);
892	me->next = NULL;
893	*i = me;
894
895	me->m = NULL;
896	me->mflags = 0;
897}
898
899void xtables_register_matches(struct xtables_match *match, unsigned int n)
900{
901	do {
902		xtables_register_match(&match[--n]);
903	} while (n > 0);
904}
905
906void xtables_register_target(struct xtables_target *me)
907{
908	if (me->version == NULL) {
909		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
910		        xt_params->program_name, me->name, me->revision);
911		exit(1);
912	}
913	if (strcmp(me->version, XTABLES_VERSION) != 0) {
914		fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
915		        "but \"%s\" is required.\n",
916			xt_params->program_name, me->name,
917			me->version, XTABLES_VERSION);
918		exit(1);
919	}
920
921	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
922		fprintf(stderr, "%s: target `%s' has invalid name\n",
923			xt_params->program_name, me->name);
924		exit(1);
925	}
926
927	if (me->family >= NPROTO) {
928		fprintf(stderr,
929			"%s: BUG: target %s has invalid protocol family\n",
930			xt_params->program_name, me->name);
931		exit(1);
932	}
933
934	if (me->x6_options != NULL)
935		xtables_option_metavalidate(me->name, me->x6_options);
936	if (me->extra_opts != NULL)
937		xtables_check_options(me->name, me->extra_opts);
938
939	/* ignore not interested target */
940	if (me->family != afinfo->family && me->family != AF_UNSPEC)
941		return;
942
943	/* place on linked list of targets pending full registration */
944	me->next = xtables_pending_targets;
945	xtables_pending_targets = me;
946}
947
948static void xtables_fully_register_pending_target(struct xtables_target *me)
949{
950	struct xtables_target *old;
951
952	old = xtables_find_target(me->name, XTF_DURING_LOAD);
953	if (old) {
954		struct xtables_target **i;
955
956		if (old->revision == me->revision &&
957		    old->family == me->family) {
958			fprintf(stderr,
959				"%s: target `%s' already registered.\n",
960				xt_params->program_name, me->name);
961			exit(1);
962		}
963
964		/* Now we have two (or more) options, check compatibility. */
965		if (compatible_target_revision(old->name, old->revision)
966		    && old->revision > me->revision)
967			return;
968
969		/* See if new target can be used. */
970		if (!compatible_target_revision(me->name, me->revision))
971			return;
972
973		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
974		if (old->revision == me->revision && me->family == AF_UNSPEC)
975			return;
976
977		/* Delete old one. */
978		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
979		*i = old->next;
980	}
981
982	if (me->size != XT_ALIGN(me->size)) {
983		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
984		        xt_params->program_name, me->name,
985		        (unsigned int)me->size);
986		exit(1);
987	}
988
989	/* Prepend to list. */
990	me->next = xtables_targets;
991	xtables_targets = me;
992	me->t = NULL;
993	me->tflags = 0;
994}
995
996void xtables_register_targets(struct xtables_target *target, unsigned int n)
997{
998	do {
999		xtables_register_target(&target[--n]);
1000	} while (n > 0);
1001}
1002
1003/**
1004 * xtables_param_act - act on condition
1005 * @status:	a constant from enum xtables_exittype
1006 *
1007 * %XTF_ONLY_ONCE: print error message that option may only be used once.
1008 * @p1:		module name (e.g. "mark")
1009 * @p2(...):	option in conflict (e.g. "--mark")
1010 * @p3(...):	condition to match on (see extensions/ for examples)
1011 *
1012 * %XTF_NO_INVERT: option does not support inversion
1013 * @p1:		module name
1014 * @p2:		option in conflict
1015 * @p3:		condition to match on
1016 *
1017 * %XTF_BAD_VALUE: bad value for option
1018 * @p1:		module name
1019 * @p2:		option with which the problem occured (e.g. "--mark")
1020 * @p3:		string the user passed in (e.g. "99999999999999")
1021 *
1022 * %XTF_ONE_ACTION: two mutually exclusive actions have been specified
1023 * @p1:		module name
1024 *
1025 * Displays an error message and exits the program.
1026 */
1027void xtables_param_act(unsigned int status, const char *p1, ...)
1028{
1029	const char *p2, *p3;
1030	va_list args;
1031	bool b;
1032
1033	va_start(args, p1);
1034
1035	switch (status) {
1036	case XTF_ONLY_ONCE:
1037		p2 = va_arg(args, const char *);
1038		b  = va_arg(args, unsigned int);
1039		if (!b)
1040			return;
1041		xt_params->exit_err(PARAMETER_PROBLEM,
1042		           "%s: \"%s\" option may only be specified once",
1043		           p1, p2);
1044		break;
1045	case XTF_NO_INVERT:
1046		p2 = va_arg(args, const char *);
1047		b  = va_arg(args, unsigned int);
1048		if (!b)
1049			return;
1050		xt_params->exit_err(PARAMETER_PROBLEM,
1051		           "%s: \"%s\" option cannot be inverted", p1, p2);
1052		break;
1053	case XTF_BAD_VALUE:
1054		p2 = va_arg(args, const char *);
1055		p3 = va_arg(args, const char *);
1056		xt_params->exit_err(PARAMETER_PROBLEM,
1057		           "%s: Bad value for \"%s\" option: \"%s\"",
1058		           p1, p2, p3);
1059		break;
1060	case XTF_ONE_ACTION:
1061		b = va_arg(args, unsigned int);
1062		if (!b)
1063			return;
1064		xt_params->exit_err(PARAMETER_PROBLEM,
1065		           "%s: At most one action is possible", p1);
1066		break;
1067	default:
1068		xt_params->exit_err(status, p1, args);
1069		break;
1070	}
1071
1072	va_end(args);
1073}
1074
1075const char *xtables_ipaddr_to_numeric(const struct in_addr *addrp)
1076{
1077	static char buf[20];
1078	const unsigned char *bytep = (const void *)&addrp->s_addr;
1079
1080	sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
1081	return buf;
1082}
1083
1084static const char *ipaddr_to_host(const struct in_addr *addr)
1085{
1086	struct hostent *host;
1087
1088	host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET);
1089	if (host == NULL)
1090		return NULL;
1091
1092	return host->h_name;
1093}
1094
1095static const char *ipaddr_to_network(const struct in_addr *addr)
1096{
1097	struct netent *net;
1098
1099	if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL)
1100		return net->n_name;
1101
1102	return NULL;
1103}
1104
1105const char *xtables_ipaddr_to_anyname(const struct in_addr *addr)
1106{
1107	const char *name;
1108
1109	if ((name = ipaddr_to_host(addr)) != NULL ||
1110	    (name = ipaddr_to_network(addr)) != NULL)
1111		return name;
1112
1113	return xtables_ipaddr_to_numeric(addr);
1114}
1115
1116const char *xtables_ipmask_to_numeric(const struct in_addr *mask)
1117{
1118	static char buf[20];
1119	uint32_t maskaddr, bits;
1120	int i;
1121
1122	maskaddr = ntohl(mask->s_addr);
1123
1124	if (maskaddr == 0xFFFFFFFFL)
1125		/* we don't want to see "/32" */
1126		return "";
1127
1128	i = 32;
1129	bits = 0xFFFFFFFEL;
1130	while (--i >= 0 && maskaddr != bits)
1131		bits <<= 1;
1132	if (i >= 0)
1133		sprintf(buf, "/%d", i);
1134	else
1135		/* mask was not a decent combination of 1's and 0's */
1136		sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
1137
1138	return buf;
1139}
1140
1141static struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask)
1142{
1143	static struct in_addr addr;
1144	unsigned char *addrp;
1145	unsigned int onebyte;
1146	char buf[20], *p, *q;
1147	int i;
1148
1149	/* copy dotted string, because we need to modify it */
1150	strncpy(buf, dotted, sizeof(buf) - 1);
1151	buf[sizeof(buf) - 1] = '\0';
1152	addrp = (void *)&addr.s_addr;
1153
1154	p = buf;
1155	for (i = 0; i < 3; ++i) {
1156		if ((q = strchr(p, '.')) == NULL) {
1157			if (is_mask)
1158				return NULL;
1159
1160			/* autocomplete, this is a network address */
1161			if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1162				return NULL;
1163
1164			addrp[i] = onebyte;
1165			while (i < 3)
1166				addrp[++i] = 0;
1167
1168			return &addr;
1169		}
1170
1171		*q = '\0';
1172		if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1173			return NULL;
1174
1175		addrp[i] = onebyte;
1176		p = q + 1;
1177	}
1178
1179	/* we have checked 3 bytes, now we check the last one */
1180	if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1181		return NULL;
1182
1183	addrp[3] = onebyte;
1184	return &addr;
1185}
1186
1187struct in_addr *xtables_numeric_to_ipaddr(const char *dotted)
1188{
1189	return __numeric_to_ipaddr(dotted, false);
1190}
1191
1192struct in_addr *xtables_numeric_to_ipmask(const char *dotted)
1193{
1194	return __numeric_to_ipaddr(dotted, true);
1195}
1196
1197static struct in_addr *network_to_ipaddr(const char *name)
1198{
1199	static struct in_addr addr;
1200	struct netent *net;
1201
1202	if ((net = getnetbyname(name)) != NULL) {
1203		if (net->n_addrtype != AF_INET)
1204			return NULL;
1205		addr.s_addr = htonl(net->n_net);
1206		return &addr;
1207	}
1208
1209	return NULL;
1210}
1211
1212static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
1213{
1214	struct hostent *host;
1215	struct in_addr *addr;
1216	unsigned int i;
1217
1218	*naddr = 0;
1219	if ((host = gethostbyname(name)) != NULL) {
1220		if (host->h_addrtype != AF_INET ||
1221		    host->h_length != sizeof(struct in_addr))
1222			return NULL;
1223
1224		while (host->h_addr_list[*naddr] != NULL)
1225			++*naddr;
1226		addr = xtables_calloc(*naddr, sizeof(struct in_addr));
1227		for (i = 0; i < *naddr; i++)
1228			memcpy(&addr[i], host->h_addr_list[i],
1229			       sizeof(struct in_addr));
1230		return addr;
1231	}
1232
1233	return NULL;
1234}
1235
1236static struct in_addr *
1237ipparse_hostnetwork(const char *name, unsigned int *naddrs)
1238{
1239	struct in_addr *addrptmp, *addrp;
1240
1241	if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL ||
1242	    (addrptmp = network_to_ipaddr(name)) != NULL) {
1243		addrp = xtables_malloc(sizeof(struct in_addr));
1244		memcpy(addrp, addrptmp, sizeof(*addrp));
1245		*naddrs = 1;
1246		return addrp;
1247	}
1248	if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL)
1249		return addrptmp;
1250
1251	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1252}
1253
1254static struct in_addr *parse_ipmask(const char *mask)
1255{
1256	static struct in_addr maskaddr;
1257	struct in_addr *addrp;
1258	unsigned int bits;
1259
1260	if (mask == NULL) {
1261		/* no mask at all defaults to 32 bits */
1262		maskaddr.s_addr = 0xFFFFFFFF;
1263		return &maskaddr;
1264	}
1265	if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL)
1266		/* dotted_to_addr already returns a network byte order addr */
1267		return addrp;
1268	if (!xtables_strtoui(mask, NULL, &bits, 0, 32))
1269		xt_params->exit_err(PARAMETER_PROBLEM,
1270			   "invalid mask `%s' specified", mask);
1271	if (bits != 0) {
1272		maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
1273		return &maskaddr;
1274	}
1275
1276	maskaddr.s_addr = 0U;
1277	return &maskaddr;
1278}
1279
1280void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
1281                              struct in_addr **maskpp, unsigned int *naddrs)
1282{
1283	struct in_addr *addrp;
1284	char buf[256], *p;
1285	unsigned int len, i, j, n, count = 1;
1286	const char *loop = name;
1287
1288	while ((loop = strchr(loop, ',')) != NULL) {
1289		++count;
1290		++loop; /* skip ',' */
1291	}
1292
1293	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
1294	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
1295
1296	loop = name;
1297
1298	for (i = 0; i < count; ++i) {
1299		if (loop == NULL)
1300			break;
1301		if (*loop == ',')
1302			++loop;
1303		if (*loop == '\0')
1304			break;
1305		p = strchr(loop, ',');
1306		if (p != NULL)
1307			len = p - loop;
1308		else
1309			len = strlen(loop);
1310		if (len == 0 || sizeof(buf) - 1 < len)
1311			break;
1312
1313		strncpy(buf, loop, len);
1314		buf[len] = '\0';
1315		loop += len;
1316		if ((p = strrchr(buf, '/')) != NULL) {
1317			*p = '\0';
1318			addrp = parse_ipmask(p + 1);
1319		} else {
1320			addrp = parse_ipmask(NULL);
1321		}
1322		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1323
1324		/* if a null mask is given, the name is ignored, like in "any/0" */
1325		if ((*maskpp + i)->s_addr == 0)
1326			/*
1327			 * A bit pointless to process multiple addresses
1328			 * in this case...
1329			 */
1330			strcpy(buf, "0.0.0.0");
1331
1332		addrp = ipparse_hostnetwork(buf, &n);
1333		if (n > 1) {
1334			count += n - 1;
1335			*addrpp = xtables_realloc(*addrpp,
1336			          sizeof(struct in_addr) * count);
1337			*maskpp = xtables_realloc(*maskpp,
1338			          sizeof(struct in_addr) * count);
1339			for (j = 0; j < n; ++j)
1340				/* for each new addr */
1341				memcpy(*addrpp + i + j, addrp + j,
1342				       sizeof(*addrp));
1343			for (j = 1; j < n; ++j)
1344				/* for each new mask */
1345				memcpy(*maskpp + i + j, *maskpp + i,
1346				       sizeof(*addrp));
1347			i += n - 1;
1348		} else {
1349			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1350		}
1351		/* free what ipparse_hostnetwork had allocated: */
1352		free(addrp);
1353	}
1354	*naddrs = count;
1355	for (i = 0; i < count; ++i)
1356		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
1357}
1358
1359
1360/**
1361 * xtables_ipparse_any - transform arbitrary name to in_addr
1362 *
1363 * Possible inputs (pseudo regex):
1364 * 	m{^($hostname|$networkname|$ipaddr)(/$mask)?}
1365 * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname"
1366 */
1367void xtables_ipparse_any(const char *name, struct in_addr **addrpp,
1368                         struct in_addr *maskp, unsigned int *naddrs)
1369{
1370	unsigned int i, j, k, n;
1371	struct in_addr *addrp;
1372	char buf[256], *p;
1373
1374	strncpy(buf, name, sizeof(buf) - 1);
1375	buf[sizeof(buf) - 1] = '\0';
1376	if ((p = strrchr(buf, '/')) != NULL) {
1377		*p = '\0';
1378		addrp = parse_ipmask(p + 1);
1379	} else {
1380		addrp = parse_ipmask(NULL);
1381	}
1382	memcpy(maskp, addrp, sizeof(*maskp));
1383
1384	/* if a null mask is given, the name is ignored, like in "any/0" */
1385	if (maskp->s_addr == 0U)
1386		strcpy(buf, "0.0.0.0");
1387
1388	addrp = *addrpp = ipparse_hostnetwork(buf, naddrs);
1389	n = *naddrs;
1390	for (i = 0, j = 0; i < n; ++i) {
1391		addrp[j++].s_addr &= maskp->s_addr;
1392		for (k = 0; k < j - 1; ++k)
1393			if (addrp[k].s_addr == addrp[j-1].s_addr) {
1394				/*
1395				 * Nuke the dup by copying an address from the
1396				 * tail here, and check the current position
1397				 * again (--j).
1398				 */
1399				memcpy(&addrp[--j], &addrp[--*naddrs],
1400				       sizeof(struct in_addr));
1401				break;
1402			}
1403	}
1404}
1405
1406const char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp)
1407{
1408	/* 0000:0000:0000:0000:0000:0000:000.000.000.000
1409	 * 0000:0000:0000:0000:0000:0000:0000:0000 */
1410	static char buf[50+1];
1411	return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
1412}
1413
1414static const char *ip6addr_to_host(const struct in6_addr *addr)
1415{
1416	static char hostname[NI_MAXHOST];
1417	struct sockaddr_in6 saddr;
1418	int err;
1419
1420	memset(&saddr, 0, sizeof(struct sockaddr_in6));
1421	memcpy(&saddr.sin6_addr, addr, sizeof(*addr));
1422	saddr.sin6_family = AF_INET6;
1423
1424	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6),
1425	      hostname, sizeof(hostname) - 1, NULL, 0, 0);
1426	if (err != 0) {
1427#ifdef DEBUG
1428		fprintf(stderr,"IP2Name: %s\n",gai_strerror(err));
1429#endif
1430		return NULL;
1431	}
1432
1433#ifdef DEBUG
1434	fprintf (stderr, "\naddr2host: %s\n", hostname);
1435#endif
1436	return hostname;
1437}
1438
1439const char *xtables_ip6addr_to_anyname(const struct in6_addr *addr)
1440{
1441	const char *name;
1442
1443	if ((name = ip6addr_to_host(addr)) != NULL)
1444		return name;
1445
1446	return xtables_ip6addr_to_numeric(addr);
1447}
1448
1449static int ip6addr_prefix_length(const struct in6_addr *k)
1450{
1451	unsigned int bits = 0;
1452	uint32_t a, b, c, d;
1453
1454	a = ntohl(k->s6_addr32[0]);
1455	b = ntohl(k->s6_addr32[1]);
1456	c = ntohl(k->s6_addr32[2]);
1457	d = ntohl(k->s6_addr32[3]);
1458	while (a & 0x80000000U) {
1459		++bits;
1460		a <<= 1;
1461		a  |= (b >> 31) & 1;
1462		b <<= 1;
1463		b  |= (c >> 31) & 1;
1464		c <<= 1;
1465		c  |= (d >> 31) & 1;
1466		d <<= 1;
1467	}
1468	if (a != 0 || b != 0 || c != 0 || d != 0)
1469		return -1;
1470	return bits;
1471}
1472
1473const char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
1474{
1475	static char buf[50+2];
1476	int l = ip6addr_prefix_length(addrp);
1477
1478	if (l == -1) {
1479		strcpy(buf, "/");
1480		strcat(buf, xtables_ip6addr_to_numeric(addrp));
1481		return buf;
1482	}
1483	sprintf(buf, "/%d", l);
1484	return buf;
1485}
1486
1487struct in6_addr *xtables_numeric_to_ip6addr(const char *num)
1488{
1489	static struct in6_addr ap;
1490	int err;
1491
1492	if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
1493		return &ap;
1494#ifdef DEBUG
1495	fprintf(stderr, "\nnumeric2addr: %d\n", err);
1496#endif
1497	return NULL;
1498}
1499
1500static struct in6_addr *
1501host_to_ip6addr(const char *name, unsigned int *naddr)
1502{
1503	struct in6_addr *addr;
1504	struct addrinfo hints;
1505	struct addrinfo *res, *p;
1506	int err;
1507	unsigned int i;
1508
1509	memset(&hints, 0, sizeof(hints));
1510	hints.ai_flags    = AI_CANONNAME;
1511	hints.ai_family   = AF_INET6;
1512	hints.ai_socktype = SOCK_RAW;
1513
1514	*naddr = 0;
1515	if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
1516#ifdef DEBUG
1517		fprintf(stderr,"Name2IP: %s\n",gai_strerror(err));
1518#endif
1519		return NULL;
1520	} else {
1521		/* Find length of address chain */
1522		for (p = res; p != NULL; p = p->ai_next)
1523			++*naddr;
1524#ifdef DEBUG
1525		fprintf(stderr, "resolved: len=%d  %s ", res->ai_addrlen,
1526		        xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr));
1527#endif
1528		/* Copy each element of the address chain */
1529		addr = xtables_calloc(*naddr, sizeof(struct in6_addr));
1530		for (i = 0, p = res; p != NULL; p = p->ai_next)
1531			memcpy(&addr[i++],
1532			       &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr,
1533			       sizeof(struct in6_addr));
1534		freeaddrinfo(res);
1535		return addr;
1536	}
1537
1538	return NULL;
1539}
1540
1541static struct in6_addr *network_to_ip6addr(const char *name)
1542{
1543	/*	abort();*/
1544	/* TODO: not implemented yet, but the exception breaks the
1545	 *       name resolvation */
1546	return NULL;
1547}
1548
1549static struct in6_addr *
1550ip6parse_hostnetwork(const char *name, unsigned int *naddrs)
1551{
1552	struct in6_addr *addrp, *addrptmp;
1553
1554	if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL ||
1555	    (addrptmp = network_to_ip6addr(name)) != NULL) {
1556		addrp = xtables_malloc(sizeof(struct in6_addr));
1557		memcpy(addrp, addrptmp, sizeof(*addrp));
1558		*naddrs = 1;
1559		return addrp;
1560	}
1561	if ((addrp = host_to_ip6addr(name, naddrs)) != NULL)
1562		return addrp;
1563
1564	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1565}
1566
1567static struct in6_addr *parse_ip6mask(char *mask)
1568{
1569	static struct in6_addr maskaddr;
1570	struct in6_addr *addrp;
1571	unsigned int bits;
1572
1573	if (mask == NULL) {
1574		/* no mask at all defaults to 128 bits */
1575		memset(&maskaddr, 0xff, sizeof maskaddr);
1576		return &maskaddr;
1577	}
1578	if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL)
1579		return addrp;
1580	if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
1581		xt_params->exit_err(PARAMETER_PROBLEM,
1582			   "invalid mask `%s' specified", mask);
1583	if (bits != 0) {
1584		char *p = (void *)&maskaddr;
1585		memset(p, 0xff, bits / 8);
1586		memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
1587		p[bits/8] = 0xff << (8 - (bits & 7));
1588		return &maskaddr;
1589	}
1590
1591	memset(&maskaddr, 0, sizeof(maskaddr));
1592	return &maskaddr;
1593}
1594
1595void
1596xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
1597		      struct in6_addr **maskpp, unsigned int *naddrs)
1598{
1599	static const struct in6_addr zero_addr;
1600	struct in6_addr *addrp;
1601	char buf[256], *p;
1602	unsigned int len, i, j, n, count = 1;
1603	const char *loop = name;
1604
1605	while ((loop = strchr(loop, ',')) != NULL) {
1606		++count;
1607		++loop; /* skip ',' */
1608	}
1609
1610	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
1611	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
1612
1613	loop = name;
1614
1615	for (i = 0; i < count /*NB: count can grow*/; ++i) {
1616		if (loop == NULL)
1617			break;
1618		if (*loop == ',')
1619			++loop;
1620		if (*loop == '\0')
1621			break;
1622		p = strchr(loop, ',');
1623		if (p != NULL)
1624			len = p - loop;
1625		else
1626			len = strlen(loop);
1627		if (len == 0 || sizeof(buf) - 1 < len)
1628			break;
1629
1630		strncpy(buf, loop, len);
1631		buf[len] = '\0';
1632		loop += len;
1633		if ((p = strrchr(buf, '/')) != NULL) {
1634			*p = '\0';
1635			addrp = parse_ip6mask(p + 1);
1636		} else {
1637			addrp = parse_ip6mask(NULL);
1638		}
1639		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1640
1641		/* if a null mask is given, the name is ignored, like in "any/0" */
1642		if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0)
1643			strcpy(buf, "::");
1644
1645		addrp = ip6parse_hostnetwork(buf, &n);
1646		if (n > 1) {
1647			count += n - 1;
1648			*addrpp = xtables_realloc(*addrpp,
1649			          sizeof(struct in6_addr) * count);
1650			*maskpp = xtables_realloc(*maskpp,
1651			          sizeof(struct in6_addr) * count);
1652			for (j = 0; j < n; ++j)
1653				/* for each new addr */
1654				memcpy(*addrpp + i + j, addrp + j,
1655				       sizeof(*addrp));
1656			for (j = 1; j < n; ++j)
1657				/* for each new mask */
1658				memcpy(*maskpp + i + j, *maskpp + i,
1659				       sizeof(*addrp));
1660			i += n - 1;
1661		} else {
1662			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1663		}
1664		/* free what ip6parse_hostnetwork had allocated: */
1665		free(addrp);
1666	}
1667	*naddrs = count;
1668	for (i = 0; i < count; ++i)
1669		for (j = 0; j < 4; ++j)
1670			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
1671}
1672
1673void xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
1674                          struct in6_addr *maskp, unsigned int *naddrs)
1675{
1676	static const struct in6_addr zero_addr;
1677	struct in6_addr *addrp;
1678	unsigned int i, j, k, n;
1679	char buf[256], *p;
1680
1681	strncpy(buf, name, sizeof(buf) - 1);
1682	buf[sizeof(buf)-1] = '\0';
1683	if ((p = strrchr(buf, '/')) != NULL) {
1684		*p = '\0';
1685		addrp = parse_ip6mask(p + 1);
1686	} else {
1687		addrp = parse_ip6mask(NULL);
1688	}
1689	memcpy(maskp, addrp, sizeof(*maskp));
1690
1691	/* if a null mask is given, the name is ignored, like in "any/0" */
1692	if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0)
1693		strcpy(buf, "::");
1694
1695	addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs);
1696	n = *naddrs;
1697	for (i = 0, j = 0; i < n; ++i) {
1698		for (k = 0; k < 4; ++k)
1699			addrp[j].s6_addr32[k] &= maskp->s6_addr32[k];
1700		++j;
1701		for (k = 0; k < j - 1; ++k)
1702			if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
1703				/*
1704				 * Nuke the dup by copying an address from the
1705				 * tail here, and check the current position
1706				 * again (--j).
1707				 */
1708				memcpy(&addrp[--j], &addrp[--*naddrs],
1709				       sizeof(struct in_addr));
1710				break;
1711			}
1712	}
1713}
1714
1715void xtables_save_string(const char *value)
1716{
1717	static const char no_quote_chars[] = "_-0123456789"
1718		"abcdefghijklmnopqrstuvwxyz"
1719		"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1720	static const char escape_chars[] = "\"\\'";
1721	size_t length;
1722	const char *p;
1723
1724	length = strspn(value, no_quote_chars);
1725	if (length > 0 && value[length] == 0) {
1726		/* no quoting required */
1727		putchar(' ');
1728		fputs(value, stdout);
1729	} else {
1730		/* there is at least one dangerous character in the
1731		   value, which we have to quote.  Write double quotes
1732		   around the value and escape special characters with
1733		   a backslash */
1734		printf(" \"");
1735
1736		for (p = strpbrk(value, escape_chars); p != NULL;
1737		     p = strpbrk(value, escape_chars)) {
1738			if (p > value)
1739				fwrite(value, 1, p - value, stdout);
1740			putchar('\\');
1741			putchar(*p);
1742			value = p + 1;
1743		}
1744
1745		/* print the rest and finish the double quoted
1746		   string */
1747		fputs(value, stdout);
1748		putchar('\"');
1749	}
1750}
1751
1752/**
1753 * Check for option-intrapositional negation.
1754 * Do not use in new code.
1755 */
1756int xtables_check_inverse(const char option[], int *invert,
1757			  int *my_optind, int argc, char **argv)
1758{
1759	if (option == NULL || strcmp(option, "!") != 0)
1760		return false;
1761
1762	fprintf(stderr, "Using intrapositioned negation "
1763	        "(`--option ! this`) is deprecated in favor of "
1764	        "extrapositioned (`! --option this`).\n");
1765
1766	if (*invert)
1767		xt_params->exit_err(PARAMETER_PROBLEM,
1768			   "Multiple `!' flags not allowed");
1769	*invert = true;
1770	if (my_optind != NULL) {
1771		optarg = argv[*my_optind];
1772		++*my_optind;
1773		if (argc && *my_optind > argc)
1774			xt_params->exit_err(PARAMETER_PROBLEM,
1775				   "no argument following `!'");
1776	}
1777
1778	return true;
1779}
1780
1781const struct xtables_pprot xtables_chain_protos[] = {
1782	{"tcp",       IPPROTO_TCP},
1783	{"sctp",      IPPROTO_SCTP},
1784	{"udp",       IPPROTO_UDP},
1785	{"udplite",   IPPROTO_UDPLITE},
1786	{"icmp",      IPPROTO_ICMP},
1787	{"icmpv6",    IPPROTO_ICMPV6},
1788	{"ipv6-icmp", IPPROTO_ICMPV6},
1789	{"esp",       IPPROTO_ESP},
1790	{"ah",        IPPROTO_AH},
1791	{"ipv6-mh",   IPPROTO_MH},
1792	{"mh",        IPPROTO_MH},
1793	{"all",       0},
1794	{NULL},
1795};
1796
1797uint16_t
1798xtables_parse_protocol(const char *s)
1799{
1800	unsigned int proto;
1801
1802	if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) {
1803		struct protoent *pent;
1804
1805		/* first deal with the special case of 'all' to prevent
1806		 * people from being able to redefine 'all' in nsswitch
1807		 * and/or provoke expensive [not working] ldap/nis/...
1808		 * lookups */
1809		if (!strcmp(s, "all"))
1810			return 0;
1811
1812		if ((pent = getprotobyname(s)))
1813			proto = pent->p_proto;
1814		else {
1815			unsigned int i;
1816			for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
1817				if (xtables_chain_protos[i].name == NULL)
1818					continue;
1819
1820				if (strcmp(s, xtables_chain_protos[i].name) == 0) {
1821					proto = xtables_chain_protos[i].num;
1822					break;
1823				}
1824			}
1825			if (i == ARRAY_SIZE(xtables_chain_protos))
1826				xt_params->exit_err(PARAMETER_PROBLEM,
1827					   "unknown protocol `%s' specified",
1828					   s);
1829		}
1830	}
1831
1832	return proto;
1833}
1834