xtables.c revision 1e128bd804b676ee91beca48312de9b251845d09
15208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI/*
25208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * (C) 2000-2006 by the netfilter coreteam <coreteam@netfilter.org>:
35208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *
45208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	This program is free software; you can redistribute it and/or modify
55208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	it under the terms of the GNU General Public License as published by
65208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	the Free Software Foundation; either version 2 of the License, or
75208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	(at your option) any later version.
85208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *
95208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	This program is distributed in the hope that it will be useful,
105208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	but WITHOUT ANY WARRANTY; without even the implied warranty of
115208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
125208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	GNU General Public License for more details.
135208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *
145208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	You should have received a copy of the GNU General Public License
155208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	along with this program; if not, write to the Free Software
165208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
175208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI */
185208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI
193dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <errno.h>
200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <fcntl.h>
2104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI#include <netdb.h>
22aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt#include <stdarg.h>
23cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt#include <stdbool.h>
243dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdio.h>
253dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdlib.h>
260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <string.h>
270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <unistd.h>
280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#include <sys/socket.h>
290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/stat.h>
300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/types.h>
310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/wait.h>
3208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#include <arpa/inet.h>
333dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
345208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI#include <xtables.h>
354e41854423b529d3107c23b85434d50a75d08057Jan Engelhardt#include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */
3677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt#include <linux/netfilter_ipv4/ip_tables.h>
3777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt#include <linux/netfilter_ipv6/ip6_tables.h>
38ef18e8147903885708d1c264904129af4fb636d6Jan Engelhardt#include <libiptc/libxtc.h>
393dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
405a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#ifndef NO_SHARED_LIBS
415a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#include <dlfcn.h>
425a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#endif
43c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */
44c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IPT_SO_GET_REVISION_MATCH	(IPT_BASE_CTL + 2)
45c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IPT_SO_GET_REVISION_TARGET	(IPT_BASE_CTL + 3)
46c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#endif
47c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */
48c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IP6T_SO_GET_REVISION_MATCH	68
49c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IP6T_SO_GET_REVISION_TARGET	69
50c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#endif
5170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim#include <getopt.h>
521e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt#include "xshared.h"
535a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger
540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#define NPROTO	255
550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
560b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#ifndef PROC_SYS_MODPROBE
570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#endif
590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
608b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
618b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim
6240a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salimstruct xtables_globals *xt_params = NULL;
6340a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim
648b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...)
6540a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim{
6640a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	va_list args;
6740a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim
6840a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	va_start(args, msg);
6940a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version);
7040a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	vfprintf(stderr, msg, args);
7140a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	va_end(args);
7240a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	fprintf(stderr, "\n");
7340a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	exit(status);
7440a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim}
7540a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim
76600f38db82548a683775fd89b6e136673e924097Jan Engelhardtvoid xtables_free_opts(int unused)
7784c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim{
7859e8114c6792242e80785f4461d5e663fb9a3d64Jan Engelhardt	if (xt_params->opts != xt_params->orig_opts)
7959e8114c6792242e80785f4461d5e663fb9a3d64Jan Engelhardt		free(xt_params->opts);
8084c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim}
8184c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim
82600f38db82548a683775fd89b6e136673e924097Jan Engelhardtstruct option *xtables_merge_options(struct option *orig_opts,
83600f38db82548a683775fd89b6e136673e924097Jan Engelhardt				     struct option *oldopts,
8470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim				     const struct option *newopts,
8570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim				     unsigned int *option_offset)
8670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim{
87600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	unsigned int num_oold = 0, num_old = 0, num_new = 0, i;
88600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	struct option *merge, *mp;
8970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
9070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	if (newopts == NULL)
9170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim		return oldopts;
9270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
93600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ;
94600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	if (oldopts != NULL)
95600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		for (num_old = 0; oldopts[num_old].name; num_old++) ;
9670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	for (num_new = 0; newopts[num_new].name; num_new++) ;
9770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
981dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	/*
991dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 * Since @oldopts also has @orig_opts already (and does so at the
1001dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 * start), skip these entries.
1011dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 */
1021dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	oldopts += num_oold;
1031dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	num_old -= num_oold;
1041dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt
105600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1));
106600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	if (merge == NULL)
107600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		return NULL;
108600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
109600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Let the base options -[ADI...] have precedence over everything */
110600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(merge, orig_opts, sizeof(*mp) * num_oold);
111600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	mp = merge + num_oold;
112600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
113600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Second, the new options */
1141e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt	xt_params->option_offset += XT_OPTION_OFFSET_SCALE;
11570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	*option_offset = xt_params->option_offset;
116600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(mp, newopts, sizeof(*mp) * num_new);
11770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
118600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	for (i = 0; i < num_new; ++i, ++mp)
119600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		mp->val += *option_offset;
120600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
121600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Third, the old options */
122600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(mp, oldopts, sizeof(*mp) * num_old);
123600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	mp += num_old;
124600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	xtables_free_opts(0);
12570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
126600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Clear trailing entry */
127600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memset(mp, 0, sizeof(*mp));
12870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	return merge;
12970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim}
13070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
131dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt/**
13277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * xtables_afinfo - protocol family dependent information
13377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @kmod:		kernel module basename (e.g. "ip_tables")
13477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @libprefix:		prefix of .so library name (e.g. "libipt_")
13577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @family:		nfproto family
13677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @ipproto:		used by setsockopt (e.g. IPPROTO_IP)
13777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @so_rev_match:	optname to check revision support of match
13877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @so_rev_target:	optname to check revision support of target
13977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt */
14077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstruct xtables_afinfo {
14177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	const char *kmod;
14277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	const char *libprefix;
14377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	uint8_t family;
14477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	uint8_t ipproto;
14577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	int so_rev_match;
14677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	int so_rev_target;
14777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
14877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
14977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv4 = {
15077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.kmod          = "ip_tables",
15177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.libprefix     = "libipt_",
15277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.family	       = NFPROTO_IPV4,
15377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.ipproto       = IPPROTO_IP,
15477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_match  = IPT_SO_GET_REVISION_MATCH,
15577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_target = IPT_SO_GET_REVISION_TARGET,
15677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
15777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
15877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv6 = {
15977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.kmod          = "ip6_tables",
16077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.libprefix     = "libip6t_",
16177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.family        = NFPROTO_IPV6,
16277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.ipproto       = IPPROTO_IPV6,
16377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_match  = IP6T_SO_GET_REVISION_MATCH,
16477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_target = IP6T_SO_GET_REVISION_TARGET,
16577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
16677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
16777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo *afinfo;
16877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
16939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt/* Search path for Xtables .so files */
17039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtstatic const char *xtables_libdir;
1710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1720b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */
173c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtconst char *xtables_modprobe_program;
1740b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI/* Keeping track of external matches and targets: linked lists.  */
1760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches;
1770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets;
1780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
17939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtvoid xtables_init(void)
18039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt{
18139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = getenv("XTABLES_LIBDIR");
18239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	if (xtables_libdir != NULL)
18339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		return;
18439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = getenv("IPTABLES_LIB_DIR");
18539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	if (xtables_libdir != NULL) {
18639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, "
18739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		        "use XTABLES_LIBDIR.\n");
18839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		return;
18939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	}
190ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	/*
191ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * Well yes, IP6TABLES_LIB_DIR is of lower priority over
192ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok
193ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * for these env vars are deprecated anyhow, and in light of the
194ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * (shared) libxt_*.so files, makes less sense to have
195ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR.
196ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 */
197ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	xtables_libdir = getenv("IP6TABLES_LIB_DIR");
198ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	if (xtables_libdir != NULL) {
199ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, "
200ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		        "use XTABLES_LIBDIR.\n");
201ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		return;
202ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	}
20339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = XTABLES_LIBDIR;
20439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt}
20539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt
20677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtvoid xtables_set_nfproto(uint8_t nfproto)
20777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt{
20877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	switch (nfproto) {
20977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	case NFPROTO_IPV4:
21077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		afinfo = &afinfo_ipv4;
21177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		break;
21277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	case NFPROTO_IPV6:
21377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		afinfo = &afinfo_ipv6;
21477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		break;
21577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	default:
21677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n",
21777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		        __func__);
21877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	}
21977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}
22077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
221630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt/**
2227e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * xtables_set_params - set the global parameters used by xtables
2237e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp:	input xtables_globals structure
2247e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim *
2257e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * The app is expected to pass a valid xtables_globals data-filled
2267e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * with proper values
2277e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp cannot be NULL
2287e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim *
2297e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * Returns -1 on failure to set and 0 on success
2307e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim */
2317e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_set_params(struct xtables_globals *xtp)
2327e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{
2337e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	if (!xtp) {
2347e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		fprintf(stderr, "%s: Illegal global params\n",__func__);
2357e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		return -1;
2367e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	}
2377e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2387e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xt_params = xtp;
2397e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2407e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	if (!xt_params->exit_err)
2417e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		xt_params->exit_err = basic_exit_err;
2427e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2437e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	return 0;
2447e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim}
2457e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2467e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto)
2477e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{
2487e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xtables_init();
2497e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xtables_set_nfproto(nfproto);
2507e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	return xtables_set_params(xtp);
2517e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim}
2527e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2537e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim/**
254630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt * xtables_*alloc - wrappers that exit on failure
255630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt */
256630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_calloc(size_t count, size_t size)
2573dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
2583dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
2593dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2603dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = calloc(count, size)) == NULL) {
2613dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: calloc failed");
2623dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
2633dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
2643dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2653dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
2663dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
2673dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
268630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_malloc(size_t size)
2693dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
2703dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
2713dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2723dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = malloc(size)) == NULL) {
2733dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: malloc failed");
2743dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
2753dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
2763dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2773dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
2783dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
2790b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
280332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid *xtables_realloc(void *ptr, size_t size)
281332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
282332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	void *p;
283332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
284332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	if ((p = realloc(ptr, size)) == NULL) {
285332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		perror("ip[6]tables: realloc failed");
286332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		exit(1);
287332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
288332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
289332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	return p;
290332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
291332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
2920b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void)
2930b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
2940b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int procfile;
2950b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *ret;
2960b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
2970b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ	1024
2980b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
2990b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (procfile < 0)
3000b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return NULL;
3010b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
302371cea299f0b2eb100b9fc9fb99089640d2d606fJan Engelhardt	ret = malloc(PROCFILE_BUFSIZ);
3030b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (ret) {
3040b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		memset(ret, 0, PROCFILE_BUFSIZ);
3050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
3060b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case -1: goto fail;
3070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
3080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
3090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (ret[strlen(ret)-1]=='\n')
3100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			ret[strlen(ret)-1]=0;
3110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		close(procfile);
3120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return ret;
3130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail:
3150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(ret);
3160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	close(procfile);
3170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return NULL;
3180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
320c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_insmod(const char *modname, const char *modprobe, bool quiet)
3210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
3220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *buf = NULL;
3230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *argv[4];
3240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int status;
3250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	/* If they don't explicitly set it, read out of kernel */
3270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (!modprobe) {
3280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		buf = get_modprobe();
3290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (!buf)
3300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			return -1;
3310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		modprobe = buf;
3320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
334c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	/*
335c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * Need to flush the buffer, or the child may output it again
336c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * when switching the program thru execv.
337c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 */
338c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	fflush(stdout);
339c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt
34094aa2ea67d7b8a669e8541f094661a1dc89722a3Jan Engelhardt	switch (vfork()) {
3410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case 0:
3420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[0] = (char *)modprobe;
3430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[1] = (char *)modname;
3440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (quiet) {
3450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = "-q";
3460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3470b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		} else {
3480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = NULL;
3490b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
3510b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		execv(argv[0], argv);
3520b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3530b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		/* not usually reached */
3540b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		exit(1);
3550b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case -1:
3560b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return -1;
3570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	default: /* parent */
3590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		wait(&status);
3600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3610b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3620b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(buf);
3630b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
3640b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return 0;
3650b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return -1;
3660b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3670b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
368c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_load_ko(const char *modprobe, bool quiet)
3690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
370c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	static bool loaded = false;
3710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	static int ret = -1;
3720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (!loaded) {
37477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ret = xtables_insmod(afinfo->kmod, modprobe, quiet);
3750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		loaded = (ret == 0);
3760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ret;
3790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
3800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3815f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt/**
3825f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * xtables_strtou{i,l} - string to number conversion
3835f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @s:	input string
3845f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @end:	like strtoul's "end" pointer
3855f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @value:	pointer for result
3865f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @min:	minimum accepted value
3875f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @max:	maximum accepted value
3885f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt *
3895f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * If @end is NULL, we assume the caller wants a "strict strtoul", and hence
3905f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * "15a" is rejected.
3915f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * In either case, the value obtained is compared for min-max compliance.
3925f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Base is always 0, i.e. autodetect depending on @s.
393cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *
3945f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Returns true/false whether number was accepted. On failure, *value has
3955f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * undefined contents.
396cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */
3975f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoul(const char *s, char **end, unsigned long *value,
3985f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt                     unsigned long min, unsigned long max)
399cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
400cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	unsigned long v;
401cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	char *my_end;
402cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
403cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	errno = 0;
404cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	v = strtoul(s, &my_end, 0);
405cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
406cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (my_end == s)
407cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return false;
408cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (end != NULL)
409cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*end = my_end;
410cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
411cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (errno != ERANGE && min <= v && (max == 0 || v <= max)) {
412cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (value != NULL)
413cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			*value = v;
414cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (end == NULL)
415cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			return *my_end == '\0';
416cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return true;
417cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	}
418cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
419cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return false;
420cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
421cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4225f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoui(const char *s, char **end, unsigned int *value,
4235f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt                     unsigned int min, unsigned int max)
424cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
425cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	unsigned long v;
426cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	bool ret;
427cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4285f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	ret = xtables_strtoul(s, end, &v, min, max);
429cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (value != NULL)
430cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*value = v;
431cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return ret;
432cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
433cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
434aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtint xtables_service_to_port(const char *name, const char *proto)
43504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
43604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	struct servent *service;
43704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
43804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((service = getservbyname(name, proto)) != NULL)
43904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		return ntohs((unsigned short) service->s_port);
44004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
44104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return -1;
44204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
44304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4447ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t xtables_parse_port(const char *port, const char *proto)
44504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
4467a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt	unsigned int portnum;
44704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4485f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) ||
449aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt	    (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1)
450213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt		return portnum;
45104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4528b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM,
45304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		   "invalid port/service `%s' specified", port);
45404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
45504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
456aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtvoid xtables_parse_interface(const char *arg, char *vianame,
457aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt			     unsigned char *mask)
45804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
459fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	unsigned int vialen = strlen(arg);
46004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned int i;
46104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
46204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(mask, 0, IFNAMSIZ);
46304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(vianame, 0, IFNAMSIZ);
46404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
46504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if (vialen + 1 > IFNAMSIZ)
4668b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
46704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   "interface name `%s' must be shorter than IFNAMSIZ"
46804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   " (%i)", arg, IFNAMSIZ-1);
46904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
47004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	strcpy(vianame, arg);
471fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	if (vialen == 0)
47204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0, IFNAMSIZ);
47304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	else if (vianame[vialen - 1] == '+') {
47404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen - 1);
47504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
47604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Don't remove `+' here! -HW */
47704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	} else {
47804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Include nul-terminator in match */
47904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen + 1);
48004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
48104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		for (i = 0; vianame[i]; i++) {
482fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			if (vianame[i] == '/' ||
483fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			    vianame[i] == ' ') {
484aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann				fprintf(stderr,
485aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					"Warning: weird character in interface"
486fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt					" `%s' ('/' and ' ' are not allowed by the kernel).\n",
487aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					vianame);
48804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI				break;
48904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			}
49004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		}
49104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	}
49204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
49304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
494cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS
49521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardtstatic void *load_extension(const char *search_path, const char *prefix,
49621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt    const char *name, bool is_target)
49721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{
49821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	const char *dir = search_path, *next;
49921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	void *ptr = NULL;
50021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	struct stat sb;
50121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	char path[256];
50221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
50321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	do {
50421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		next = strchr(dir, ':');
50521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (next == NULL)
50621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			next = dir + strlen(dir);
50721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		snprintf(path, sizeof(path), "%.*s/libxt_%s.so",
5082c0a0c9eba1d1ab39dcde54bc822d4788f9531fcJan Engelhardt		         (unsigned int)(next - dir), dir, name);
50921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
51021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (dlopen(path, RTLD_NOW) != NULL) {
51121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			/* Found library.  If it didn't register itself,
51221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			   maybe they specified target as match. */
51321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			if (is_target)
5142338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_target(name, XTF_DONT_LOAD);
51521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			else
5162338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_match(name,
5172338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				      XTF_DONT_LOAD, NULL);
51821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		} else if (stat(path, &sb) == 0) {
51921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			fprintf(stderr, "%s: %s\n", path, dlerror());
52021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		}
52121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
52221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (ptr != NULL)
52321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			return ptr;
52421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
52521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		snprintf(path, sizeof(path), "%.*s/%s%s.so",
5262c0a0c9eba1d1ab39dcde54bc822d4788f9531fcJan Engelhardt		         (unsigned int)(next - dir), dir, prefix, name);
52721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (dlopen(path, RTLD_NOW) != NULL) {
52821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			if (is_target)
5292338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_target(name, XTF_DONT_LOAD);
53021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			else
5312338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_match(name,
5322338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				      XTF_DONT_LOAD, NULL);
53321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		} else if (stat(path, &sb) == 0) {
53421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			fprintf(stderr, "%s: %s\n", path, dlerror());
53521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		}
53621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
53721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (ptr != NULL)
53821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			return ptr;
53921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
54021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		dir = next + 1;
54121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	} while (*next != '\0');
54221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
54321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	return NULL;
54421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt}
545cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif
54621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
5472338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_match *
5482338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_match(const char *name, enum xtables_tryload tryload,
5492338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		   struct xtables_rule_match **matches)
5500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
5510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match *ptr;
5520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	const char *icmp6 = "icmp6";
5530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5540cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(name) >= XT_EXTENSION_MAXNAMELEN)
55521d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt		xtables_error(PARAMETER_PROBLEM,
55621d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt			   "Invalid match name \"%s\" (%u chars max)",
5570cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt			   name, XT_EXTENSION_MAXNAMELEN - 1);
55821d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt
5590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* This is ugly as hell. Nonetheless, there is no way of changing
5600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	 * this without hurting backwards compatibility */
5610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if ( (strcmp(name,"icmpv6") == 0) ||
5620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"ipv6-icmp") == 0) ||
5630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"icmp6") == 0) )
5640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = icmp6;
5650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_matches; ptr; ptr = ptr->next) {
5670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0) {
5680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			struct xtables_match *clone;
5690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* First match of this type: */
5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (ptr->m == NULL)
5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				break;
5730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Second and subsequent clones */
575630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt			clone = xtables_malloc(sizeof(struct xtables_match));
5760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			memcpy(clone, ptr, sizeof(struct xtables_match));
5770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->mflags = 0;
5780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* This is a clone: */
5790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->next = clone;
5800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = clone;
5820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
5830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
5840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
5872338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
58877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
58939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, false);
590170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
5912338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
5928b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
5930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load match `%s':%s\n",
5940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   name, dlerror());
5950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
5970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
5982338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
5990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
6000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
6010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
6020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6032338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) {
6048b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
6050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find match `%s'\n", name);
6060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && matches) {
6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match **i;
6110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match *newentry;
6120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
613630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		newentry = xtables_malloc(sizeof(struct xtables_rule_match));
6140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = matches; *i; i = &(*i)->next) {
6160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (strcmp(name, (*i)->match->name) == 0)
6172338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				(*i)->completed = true;
6180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
6190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->match = ptr;
6202338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		newentry->completed = false;
6210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->next = NULL;
6220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = newentry;
6230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6282338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_target *
6292338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_target(const char *name, enum xtables_tryload tryload)
6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *ptr;
6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Standard target? */
6340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(name, "") == 0
6350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_ACCEPT) == 0
6360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_DROP) == 0
6370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_QUEUE) == 0
6380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_RETURN) == 0)
6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = "standard";
6400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_targets; ptr; ptr = ptr->next) {
6420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0)
6430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
6440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
6472338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
64877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
64939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, true);
650170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
6512338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
6528b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
6530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load target `%s':%s\n",
6540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   name, dlerror());
6550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
6570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
6582338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
6590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
6600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
6610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
6620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
663854d2d9bd7556cfd8a676b0bc18dc059a9a2dd25Peter Volkov	if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) {
6648b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
6650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find target `%s'\n", name);
6660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
6680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr)
6700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		ptr->used = 1;
6710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
6730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
6740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6757ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_revision(const char *name, uint8_t revision, int opt)
6760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
6770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xt_get_revision rev;
6780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	socklen_t s = sizeof(rev);
6790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	int max_rev, sockfd;
6800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
68177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);
6820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (sockfd < 0) {
683df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		if (errno == EPERM) {
684df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			/* revision 0 is always supported. */
685df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			if (revision != 0)
686df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy				fprintf(stderr, "Could not determine whether "
687df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"revision %u is supported, "
688df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"assuming it is.\n",
689df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy					revision);
690df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			return 1;
691df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		}
6920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "Could not open socket to kernel: %s\n",
6930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			strerror(errno));
6940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
6950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
697c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	xtables_load_ko(xtables_modprobe_program, true);
6980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	strcpy(rev.name, name);
7000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	rev.revision = revision;
7010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
70277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s);
7030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (max_rev < 0) {
7040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Definitely don't support this? */
7050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (errno == ENOENT || errno == EPROTONOSUPPORT) {
7060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
7070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return 0;
7080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else if (errno == ENOPROTOOPT) {
7090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
7100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Assume only revision 0 support (old kernel) */
7110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return (revision == 0);
7120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else {
7130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr, "getsockopt failed strangely: %s\n",
7140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				strerror(errno));
7150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
7160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
7170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	close(sockfd);
7190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return 1;
7200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7237ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_match_revision(const char *name, uint8_t revision)
7240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
72577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_match);
7260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7287ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_target_revision(const char *name, uint8_t revision)
7290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
73077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_target);
7310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me)
7340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
7350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match **i, *old;
7360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
737c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
738c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: match %s<%u> is missing a version\n",
739c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
740c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
741c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
742dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
743dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
744dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
7455dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
746dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
7470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7500cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
7510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
7525dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
7530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
7570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
7580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: match %s has invalid protocol family\n",
7595dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
7600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested match */
76477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
7650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
7660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7672338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
7680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
76923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision &&
77023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		    old->family == me->family) {
7710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
7720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: match `%s' already registered.\n",
7735dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
7740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
7750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
7760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
7780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_match_revision(old->name, old->revision)
7790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
7800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
7810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
78223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new match can be used. */
7830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_match_revision(me->name, me->revision))
7840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
7850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
78623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
78723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision && me->family == AF_UNSPEC)
78823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt			return;
78923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt
7900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
7910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
7920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
7930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
7960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
7975dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
7985dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
7990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Append to list. */
8030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (i = &xtables_matches; *i; i = &(*i)->next);
8040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = NULL;
8050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	*i = me;
8060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->m = NULL;
8080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->mflags = 0;
8090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
8100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8119a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_matches(struct xtables_match *match, unsigned int n)
8129a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
8139a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
8149a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_match(&match[--n]);
8159a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
8169a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
8179a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
8180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me)
8190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
8200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *old;
8210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
822c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
823c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
824c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
825c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
826c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
827dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
828dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
829dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
8305dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
831dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
8320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8350cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
8360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
8375dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
8420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
8430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: target %s has invalid protocol family\n",
8445dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested target */
84977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
8500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
8510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8522338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_target(me->name, XTF_DURING_LOAD);
8530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
8540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_target **i;
8550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
85623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision &&
85723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		    old->family == me->family) {
8580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
8590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: target `%s' already registered.\n",
8605dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
8610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
8620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
8630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
8650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_target_revision(old->name, old->revision)
8660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
8670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
86923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new target can be used. */
8700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_target_revision(me->name, me->revision))
8710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
87323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
87423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision && me->family == AF_UNSPEC)
87523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt			return;
87623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt
8770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
8780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
8790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
8800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
8830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
8845dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
8855dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
8860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Prepend to list. */
8900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = xtables_targets;
8910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	xtables_targets = me;
8920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->t = NULL;
8930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->tflags = 0;
8940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
895aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
8969a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_targets(struct xtables_target *target, unsigned int n)
8979a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
8989a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
8999a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_target(&target[--n]);
9009a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
9019a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
9029a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
903a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt/**
904a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * xtables_param_act - act on condition
905a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @status:	a constant from enum xtables_exittype
906a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
907a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONLY_ONCE: print error message that option may only be used once.
908a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name (e.g. "mark")
909a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2(...):	option in conflict (e.g. "--mark")
910a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3(...):	condition to match on (see extensions/ for examples)
911a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
912a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_NO_INVERT: option does not support inversion
913a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
914a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option in conflict
915a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		condition to match on
916a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
917a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_BAD_VALUE: bad value for option
918a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
919a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option with which the problem occured (e.g. "--mark")
920a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		string the user passed in (e.g. "99999999999999")
921a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
922a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONE_ACTION: two mutually exclusive actions have been specified
923a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
924a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
925a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * Displays an error message and exits the program.
926a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt */
927a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardtvoid xtables_param_act(unsigned int status, const char *p1, ...)
928aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{
929aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	const char *p2, *p3;
930aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_list args;
931aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	bool b;
932aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
933aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_start(args, p1);
934aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
935aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	switch (status) {
936a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONLY_ONCE:
937aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
938aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
939aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
940aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9418b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
942aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option may only be specified once",
943aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2);
944aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
945a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_NO_INVERT:
946aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
947aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
948aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
949aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9508b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
951aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option cannot be inverted", p1, p2);
952aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
953a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_BAD_VALUE:
954aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
955aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p3 = va_arg(args, const char *);
9568b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
957aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: Bad value for \"%s\" option: \"%s\"",
958aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2, p3);
959aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
960a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONE_ACTION:
961aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b = va_arg(args, unsigned int);
962aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
963aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9648b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
965aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: At most one action is possible", p1);
966aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
967aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	default:
9688b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(status, p1, args);
969aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
970aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	}
971aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
972aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_end(args);
973aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt}
97408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
975e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp)
97608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
97708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[20];
97808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const unsigned char *bytep = (const void *)&addrp->s_addr;
97908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
98008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
98108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
98208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
98308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
98408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr)
98508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
98608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct hostent *host;
98708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
98808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET);
98908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (host == NULL)
99008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
99108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
99208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return host->h_name;
99308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
99408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
99508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr)
99608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
99708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct netent *net;
99808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
99908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL)
100008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return net->n_name;
100108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
100208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return NULL;
100308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
100408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1005e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr)
100608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
100708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
100808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
100908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ipaddr_to_host(addr)) != NULL ||
101008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	    (name = ipaddr_to_network(addr)) != NULL)
101108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
101208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1013e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ipaddr_to_numeric(addr);
101408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
101508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1016e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipmask_to_numeric(const struct in_addr *mask)
101708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
101808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[20];
101908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t maskaddr, bits;
102008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int i;
102108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
102208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	maskaddr = ntohl(mask->s_addr);
102308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
102408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (maskaddr == 0xFFFFFFFFL)
102508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		/* we don't want to see "/32" */
102608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return "";
102708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
102808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	i = 32;
102908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	bits = 0xFFFFFFFEL;
103008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (--i >= 0 && maskaddr != bits)
103108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		bits <<= 1;
103208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (i >= 0)
103308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		sprintf(buf, "/%d", i);
103408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	else
103508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		/* mask was not a decent combination of 1's and 0's */
1036e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
103708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
103808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
103908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
104008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1041bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask)
1042bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1043bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1044bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned char *addrp;
1045bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int onebyte;
1046bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[20], *p, *q;
1047bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int i;
1048bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1049bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* copy dotted string, because we need to modify it */
1050bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, dotted, sizeof(buf) - 1);
1051bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1052bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = (void *)&addr.s_addr;
1053bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1054bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	p = buf;
1055bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0; i < 3; ++i) {
1056bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if ((q = strchr(p, '.')) == NULL) {
1057bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (is_mask)
1058bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1059bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1060bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			/* autocomplete, this is a network address */
10615f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt			if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1062bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1063bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1064bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			addrp[i] = onebyte;
1065bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			while (i < 3)
1066bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				addrp[++i] = 0;
1067bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1068bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return &addr;
1069bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		}
1070bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1071bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*q = '\0';
10725f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt		if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1073bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1074bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1075bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[i] = onebyte;
1076bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p = q + 1;
1077bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1078bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1079bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* we have checked 3 bytes, now we check the last one */
10805f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1081bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1082bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1083bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp[3] = onebyte;
1084bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &addr;
1085bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1086bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
10871e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted)
1088bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1089bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, false);
1090bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1091bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
10921e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipmask(const char *dotted)
1093bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1094bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, true);
1095bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1096bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1097bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name)
1098bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1099bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1100bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct netent *net;
1101bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1102bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((net = getnetbyname(name)) != NULL) {
1103bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (net->n_addrtype != AF_INET)
1104bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1105bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addr.s_addr = htonl(net->n_net);
1106bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &addr;
1107bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1108bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1109bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1110bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1111bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1112bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
1113bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1114bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct hostent *host;
1115bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addr;
1116bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i;
1117bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1118bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1119bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((host = gethostbyname(name)) != NULL) {
1120bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (host->h_addrtype != AF_INET ||
1121bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		    host->h_length != sizeof(struct in_addr))
1122bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1123bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1124bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		while (host->h_addr_list[*naddr] != NULL)
1125bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			++*naddr;
1126630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addr = xtables_calloc(*naddr, sizeof(struct in_addr) * *naddr);
1127bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (i = 0; i < *naddr; i++)
1128bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			memcpy(&addr[i], host->h_addr_list[i],
1129bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			       sizeof(struct in_addr));
1130bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1131bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1132bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1133bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1134bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1135bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1136bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *
1137bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs)
1138bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1139bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrptmp, *addrp;
1140bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11411e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL ||
1142bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ipaddr(name)) != NULL) {
1143630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in_addr));
1144bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1145bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1146bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1147bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1148bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL)
1149bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrptmp;
1150bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11518b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1152bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1153bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1154bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask)
1155bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1156bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr maskaddr;
1157bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1158bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1159bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1160bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1161bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 32 bits */
1162bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = 0xFFFFFFFF;
1163bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1164bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
11651e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL)
1166bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* dotted_to_addr already returns a network byte order addr */
1167bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
11685f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 32))
11698b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1170bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1171bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1172bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
1173bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1174bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1175bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1176bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	maskaddr.s_addr = 0U;
1177bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1178bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1179bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1180332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
1181332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow                              struct in_addr **maskpp, unsigned int *naddrs)
1182332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
1183332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in_addr *addrp;
1184332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	char buf[256], *p;
1185332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1186332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1187332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1188332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1189332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1190332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1191332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1192332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1193332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
1194332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
1195332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1196332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1197332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1198332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count; ++i) {
1199332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (loop == NULL)
1200332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1201332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == ',')
1202332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			++loop;
1203332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == '\0')
1204332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1205332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		p = strchr(loop, ',');
1206332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (p != NULL)
1207332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = p - loop;
1208332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1209332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1210332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (len == 0 || sizeof(buf) - 1 < len)
1211332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1212332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1213332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1214332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1215332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		loop += len;
1216332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1217332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1218332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(p + 1);
1219332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1220332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(NULL);
1221332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1222332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1223332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1224332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
1225332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((*maskpp + i)->s_addr == 0)
1226332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			/*
1227332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * A bit pointless to process multiple addresses
1228332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * in this case...
1229332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 */
1230332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "0.0.0.0");
1231332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1232332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ipparse_hostnetwork(buf, &n);
1233332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1234332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1235332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1236332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1237332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1238332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1239332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1240332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1241332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1242332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1243332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1244332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1245332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1246332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1247332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1248332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1249332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1250332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1251332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ipparse_hostnetwork had allocated: */
1252332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1253332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1254332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
1255332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < n; ++i)
1256332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
1257332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1258332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1259332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1260a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt/**
1261a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * xtables_ipparse_any - transform arbitrary name to in_addr
1262a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt *
1263a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * Possible inputs (pseudo regex):
1264a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * 	m{^($hostname|$networkname|$ipaddr)(/$mask)?}
1265a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname"
1266a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt */
1267a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp,
1268a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                         struct in_addr *maskp, unsigned int *naddrs)
1269bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1270bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1271bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1272bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1273bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1274bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1275bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1276bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1277bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1278bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(p + 1);
1279bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1280bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(NULL);
1281bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1282bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1283bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1284bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
1285bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (maskp->s_addr == 0U)
1286bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "0.0.0.0");
1287bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1288bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ipparse_hostnetwork(buf, naddrs);
1289bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1290bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1291bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[j++].s_addr &= maskp->s_addr;
1292bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1293bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (addrp[k].s_addr == addrp[j-1].s_addr) {
1294bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				--*naddrs;
1295bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				--j;
1296bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1297bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1298bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1299bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1300bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1301e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp)
130208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
130308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	/* 0000:0000:0000:0000:0000:000.000.000.000
130408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	 * 0000:0000:0000:0000:0000:0000:0000:0000 */
130508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+1];
130608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
130708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
130808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
130908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr)
131008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
131108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char hostname[NI_MAXHOST];
131208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct sockaddr_in6 saddr;
131308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int err;
131408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
131508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memset(&saddr, 0, sizeof(struct sockaddr_in6));
131608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memcpy(&saddr.sin6_addr, addr, sizeof(*addr));
131708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	saddr.sin6_family = AF_INET6;
131808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
131908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6),
132008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	      hostname, sizeof(hostname) - 1, NULL, 0, 0);
132108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (err != 0) {
132208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
132308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		fprintf(stderr,"IP2Name: %s\n",gai_strerror(err));
132408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
132508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
132608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
132708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
132808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
132908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	fprintf (stderr, "\naddr2host: %s\n", hostname);
133008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
133108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return hostname;
133208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
133308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1334e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr)
133508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
133608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
133708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
133808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ip6addr_to_host(addr)) != NULL)
133908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
134008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1341e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ip6addr_to_numeric(addr);
134208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
134308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
134408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic int ip6addr_prefix_length(const struct in6_addr *k)
134508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
134608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	unsigned int bits = 0;
134708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t a, b, c, d;
134808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
134948607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	a = ntohl(k->s6_addr32[0]);
135048607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	b = ntohl(k->s6_addr32[1]);
135148607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	c = ntohl(k->s6_addr32[2]);
135248607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	d = ntohl(k->s6_addr32[3]);
135308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (a & 0x80000000U) {
135408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		++bits;
135508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a <<= 1;
135608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a  |= (b >> 31) & 1;
135708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b <<= 1;
135808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b  |= (c >> 31) & 1;
135908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c <<= 1;
136008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c  |= (d >> 31) & 1;
136108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		d <<= 1;
136208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
136308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (a != 0 || b != 0 || c != 0 || d != 0)
136408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return -1;
136508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return bits;
136608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
136708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1368e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
136908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
137008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+2];
137108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int l = ip6addr_prefix_length(addrp);
137208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
137308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (l == -1) {
137408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		strcpy(buf, "/");
1375e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		strcat(buf, xtables_ip6addr_to_numeric(addrp));
137608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return buf;
137708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
137808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "/%d", l);
137908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
138008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
1381bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
13821e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in6_addr *xtables_numeric_to_ip6addr(const char *num)
1383bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1384bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr ap;
1385bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
1386bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1387bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
1388bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &ap;
1389bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1390bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	fprintf(stderr, "\nnumeric2addr: %d\n", err);
1391bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1392bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1393bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1394bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1395bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1396bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr)
1397bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1398bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr *addr;
1399bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct addrinfo hints;
1400bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct addrinfo *res;
1401bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
1402bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1403bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&hints, 0, sizeof(hints));
1404bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_flags    = AI_CANONNAME;
1405bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_family   = AF_INET6;
1406bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_socktype = SOCK_RAW;
1407bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_protocol = IPPROTO_IPV6;
1408bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_next     = NULL;
1409bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1410bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1411bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
1412bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1413bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr,"Name2IP: %s\n",gai_strerror(err));
1414bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1415bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1416bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1417bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (res->ai_family != AF_INET6 ||
1418bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		    res->ai_addrlen != sizeof(struct sockaddr_in6))
1419bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1420bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1421bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1422bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr, "resolved: len=%d  %s ", res->ai_addrlen,
142330290aea009cf3fd76f27336fb4370be3467c4daPatrick McHardy		        xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr));
1424bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1425bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* Get the first element of the address-chain */
1426630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addr = xtables_malloc(sizeof(struct in6_addr));
1427bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addr, &((const struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
1428bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		       sizeof(struct in6_addr));
1429bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		freeaddrinfo(res);
1430bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddr = 1;
1431bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1432bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1433bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1434bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1435bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1436bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1437bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name)
1438bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1439bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/*	abort();*/
1440bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* TODO: not implemented yet, but the exception breaks the
1441bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	 *       name resolvation */
1442bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1443bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1444bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1445bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1446bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs)
1447bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1448bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp, *addrptmp;
1449bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
14501e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL ||
1451bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ip6addr(name)) != NULL) {
1452630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in6_addr));
1453bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1454bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1455bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1456bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1457bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrp = host_to_ip6addr(name, naddrs)) != NULL)
1458bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1459bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
14608b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1461bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1462bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1463bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask)
1464bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1465bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr maskaddr;
1466bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1467bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1468bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1469bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1470bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 128 bits */
1471bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(&maskaddr, 0xff, sizeof maskaddr);
1472bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1473bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
14741e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL)
1475bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
14765f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
14778b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1478bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1479bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1480bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		char *p = (void *)&maskaddr;
1481bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p, 0xff, bits / 8);
1482bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
1483bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p[bits/8] = 0xff << (8 - (bits & 7));
1484bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1485bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1486bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1487bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&maskaddr, 0, sizeof(maskaddr));
1488bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1489bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1490bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1491332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid
1492332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowxtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
1493332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		      struct in6_addr **maskpp, unsigned int *naddrs)
1494332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
149558df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel	static const struct in6_addr zero_addr;
1496332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in6_addr *addrp;
1497332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	char buf[256], *p;
1498332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1499332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1500332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1501332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1502332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1503332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1504332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1505332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1506332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
1507332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
1508332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1509332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1510332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1511332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count /*NB: count can grow*/; ++i) {
1512332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (loop == NULL)
1513332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1514332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == ',')
1515332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			++loop;
1516332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == '\0')
1517332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1518332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		p = strchr(loop, ',');
1519332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (p != NULL)
1520332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = p - loop;
1521332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1522332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1523332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (len == 0 || sizeof(buf) - 1 < len)
1524332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1525332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1526332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1527332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1528332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		loop += len;
1529332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1530332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1531332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(p + 1);
1532332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1533332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(NULL);
1534332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1535332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1536332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1537332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
153858df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel		if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0)
1539332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "::");
1540332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1541332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ip6parse_hostnetwork(buf, &n);
1542332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* ip6parse_hostnetwork only ever returns one IP
1543332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		address (it exits if the resolution fails).
1544332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		Therefore, n will always be 1 here.  Leaving the
1545332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		code below in anyway in case ip6parse_hostnetwork
1546332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		is improved some day to behave like
1547332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		ipparse_hostnetwork: */
1548332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1549332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1550332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1551332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1552332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1553332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1554332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1555332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1556332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1557332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1558332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1559332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1560332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1561332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1562332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1563332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1564332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1565332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1566332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ip6parse_hostnetwork had allocated: */
1567332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1568332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1569332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
1570332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < n; ++i)
1571332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		for (j = 0; j < 4; ++j)
1572332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
1573332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1574332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1575a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
1576a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                          struct in6_addr *maskp, unsigned int *naddrs)
1577bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
15789c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	static const struct in6_addr zero_addr;
1579bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1580bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1581bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1582bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1583bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1584bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf)-1] = '\0';
1585bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1586bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1587bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(p + 1);
1588bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1589bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(NULL);
1590bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1591bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1592bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1593bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
15949c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0)
1595bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "::");
1596bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1597bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs);
1598bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1599bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1600bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < 4; ++k)
16015a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai			addrp[j].s6_addr32[k] &= maskp->s6_addr32[k];
1602bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		++j;
1603bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1604bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
1605bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				--*naddrs;
1606bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				--j;
1607bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1608bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1609bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1610bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1611a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1612a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_save_string(const char *value)
1613a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{
1614a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char no_quote_chars[] = "_-0123456789"
1615a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"abcdefghijklmnopqrstuvwxyz"
1616a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1617a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char escape_chars[] = "\"\\'";
1618a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	size_t length;
1619a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	const char *p;
1620a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1621a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	length = strcspn(value, no_quote_chars);
1622a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	if (length > 0 && value[length] == 0) {
1623a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* no quoting required */
1624a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		fputs(value, stdout);
1625a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		putchar(' ');
1626a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	} else {
1627a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* there is at least one dangerous character in the
1628a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   value, which we have to quote.  Write double quotes
1629a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   around the value and escape special characters with
1630a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   a backslash */
1631a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		putchar('"');
1632a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1633a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		for (p = strpbrk(value, escape_chars); p != NULL;
1634a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		     p = strpbrk(value, escape_chars)) {
1635a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			if (p > value)
1636a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann				fwrite(value, 1, p - value, stdout);
1637a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar('\\');
1638a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar(*p);
1639a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			value = p + 1;
1640a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		}
1641a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1642a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* print the rest and finish the double quoted
1643a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   string */
1644a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		fputs(value, stdout);
1645a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		printf("\" ");
1646a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	}
1647a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann}
16480f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16490f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt/**
16500f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Check for option-intrapositional negation.
16510f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Do not use in new code.
16520f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt */
16530f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardtint xtables_check_inverse(const char option[], int *invert,
1654bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt			  int *my_optind, int argc, char **argv)
16550f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt{
16562be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (option == NULL || strcmp(option, "!") != 0)
16572be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		return false;
16580f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16592be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	fprintf(stderr, "Using intrapositioned negation "
16602be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	        "(`--option ! this`) is deprecated in favor of "
16612be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	        "extrapositioned (`! --option this`).\n");
16620f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16632be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (*invert)
16642be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
16652be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt			   "Multiple `!' flags not allowed");
16662be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	*invert = true;
16672be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (my_optind != NULL) {
1668bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt		optarg = argv[*my_optind];
16692be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		++*my_optind;
16702be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		if (argc && *my_optind > argc)
16712be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
16722be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt				   "no argument following `!'");
16730f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt	}
16742be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt
16752be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	return true;
16760f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt}
16771de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
16781de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtconst struct xtables_pprot xtables_chain_protos[] = {
16791de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"tcp",       IPPROTO_TCP},
16801de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"sctp",      IPPROTO_SCTP},
16811de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udp",       IPPROTO_UDP},
16821de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udplite",   IPPROTO_UDPLITE},
16831de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmp",      IPPROTO_ICMP},
16841de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmpv6",    IPPROTO_ICMPV6},
16851de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-icmp", IPPROTO_ICMPV6},
16861de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"esp",       IPPROTO_ESP},
16871de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ah",        IPPROTO_AH},
16881de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-mh",   IPPROTO_MH},
16891de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"mh",        IPPROTO_MH},
16901de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"all",       0},
16911de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{NULL},
16921de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt};
16931de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
16947ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t
16951de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtxtables_parse_protocol(const char *s)
16961de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt{
16971de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	unsigned int proto;
16981de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
16991de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) {
17001de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		struct protoent *pent;
17011de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17021de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		/* first deal with the special case of 'all' to prevent
17031de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * people from being able to redefine 'all' in nsswitch
17041de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * and/or provoke expensive [not working] ldap/nis/...
17051de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * lookups */
17061de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		if (!strcmp(s, "all"))
17071de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			return 0;
17081de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17091de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		if ((pent = getprotobyname(s)))
17101de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			proto = pent->p_proto;
17111de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		else {
17121de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			unsigned int i;
17131de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
1714e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso				if (xtables_chain_protos[i].name == NULL)
1715e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso					continue;
1716e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso
17171de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt				if (strcmp(s, xtables_chain_protos[i].name) == 0) {
17181de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					proto = xtables_chain_protos[i].num;
17191de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					break;
17201de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt				}
17211de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			}
17221de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			if (i == ARRAY_SIZE(xtables_chain_protos))
17238b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim				xt_params->exit_err(PARAMETER_PROBLEM,
17241de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					   "unknown protocol `%s' specified",
17251de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					   s);
17261de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		}
17271de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	}
17281de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17291de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	return proto;
17301de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt}
1731