xtables.c revision 2ad8dc895ec28a173c629c695c2e11c41b625b6e
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{
78df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt	if (xt_params->opts != xt_params->orig_opts) {
7959e8114c6792242e80785f4461d5e663fb9a3d64Jan Engelhardt		free(xt_params->opts);
80df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt		xt_params->opts = NULL;
81df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt	}
8284c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim}
8384c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim
84600f38db82548a683775fd89b6e136673e924097Jan Engelhardtstruct option *xtables_merge_options(struct option *orig_opts,
85600f38db82548a683775fd89b6e136673e924097Jan Engelhardt				     struct option *oldopts,
8670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim				     const struct option *newopts,
8770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim				     unsigned int *option_offset)
8870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim{
89600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	unsigned int num_oold = 0, num_old = 0, num_new = 0, i;
90600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	struct option *merge, *mp;
9170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
9270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	if (newopts == NULL)
9370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim		return oldopts;
9470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
95600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ;
96600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	if (oldopts != NULL)
97600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		for (num_old = 0; oldopts[num_old].name; num_old++) ;
9870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	for (num_new = 0; newopts[num_new].name; num_new++) ;
9970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
1001dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	/*
1011dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 * Since @oldopts also has @orig_opts already (and does so at the
1021dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 * start), skip these entries.
1031dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 */
1041dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	oldopts += num_oold;
1051dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	num_old -= num_oold;
1061dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt
107600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1));
108600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	if (merge == NULL)
109600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		return NULL;
110600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
111600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Let the base options -[ADI...] have precedence over everything */
112600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(merge, orig_opts, sizeof(*mp) * num_oold);
113600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	mp = merge + num_oold;
114600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
115600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Second, the new options */
1161e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt	xt_params->option_offset += XT_OPTION_OFFSET_SCALE;
11770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	*option_offset = xt_params->option_offset;
118600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(mp, newopts, sizeof(*mp) * num_new);
11970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
120600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	for (i = 0; i < num_new; ++i, ++mp)
121600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		mp->val += *option_offset;
122600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
123600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Third, the old options */
124600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(mp, oldopts, sizeof(*mp) * num_old);
125600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	mp += num_old;
126600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	xtables_free_opts(0);
12770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
128600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Clear trailing entry */
129600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memset(mp, 0, sizeof(*mp));
13070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	return merge;
13170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim}
13270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
133dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt/**
13477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * xtables_afinfo - protocol family dependent information
13577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @kmod:		kernel module basename (e.g. "ip_tables")
13677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @libprefix:		prefix of .so library name (e.g. "libipt_")
13777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @family:		nfproto family
13877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @ipproto:		used by setsockopt (e.g. IPPROTO_IP)
13977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @so_rev_match:	optname to check revision support of match
14077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @so_rev_target:	optname to check revision support of target
14177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt */
14277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstruct xtables_afinfo {
14377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	const char *kmod;
14477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	const char *libprefix;
14577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	uint8_t family;
14677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	uint8_t ipproto;
14777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	int so_rev_match;
14877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	int so_rev_target;
14977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
15077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
15177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv4 = {
15277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.kmod          = "ip_tables",
15377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.libprefix     = "libipt_",
15477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.family	       = NFPROTO_IPV4,
15577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.ipproto       = IPPROTO_IP,
15677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_match  = IPT_SO_GET_REVISION_MATCH,
15777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_target = IPT_SO_GET_REVISION_TARGET,
15877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
15977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
16077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv6 = {
16177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.kmod          = "ip6_tables",
16277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.libprefix     = "libip6t_",
16377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.family        = NFPROTO_IPV6,
16477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.ipproto       = IPPROTO_IPV6,
16577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_match  = IP6T_SO_GET_REVISION_MATCH,
16677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_target = IP6T_SO_GET_REVISION_TARGET,
16777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
16877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
16977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo *afinfo;
17077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
17139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt/* Search path for Xtables .so files */
17239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtstatic const char *xtables_libdir;
1730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1740b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */
175c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtconst char *xtables_modprobe_program;
1760b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI/* Keeping track of external matches and targets: linked lists.  */
1780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches;
1790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets;
1800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
18139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtvoid xtables_init(void)
18239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt{
18339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = getenv("XTABLES_LIBDIR");
18439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	if (xtables_libdir != NULL)
18539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		return;
18639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = getenv("IPTABLES_LIB_DIR");
18739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	if (xtables_libdir != NULL) {
18839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, "
18939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		        "use XTABLES_LIBDIR.\n");
19039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		return;
19139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	}
192ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	/*
193ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * Well yes, IP6TABLES_LIB_DIR is of lower priority over
194ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok
195ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * for these env vars are deprecated anyhow, and in light of the
196ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * (shared) libxt_*.so files, makes less sense to have
197ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR.
198ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 */
199ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	xtables_libdir = getenv("IP6TABLES_LIB_DIR");
200ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	if (xtables_libdir != NULL) {
201ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, "
202ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		        "use XTABLES_LIBDIR.\n");
203ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		return;
204ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	}
20539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = XTABLES_LIBDIR;
20639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt}
20739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt
20877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtvoid xtables_set_nfproto(uint8_t nfproto)
20977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt{
21077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	switch (nfproto) {
21177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	case NFPROTO_IPV4:
21277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		afinfo = &afinfo_ipv4;
21377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		break;
21477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	case NFPROTO_IPV6:
21577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		afinfo = &afinfo_ipv6;
21677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		break;
21777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	default:
21877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n",
21977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		        __func__);
22077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	}
22177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}
22277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
223630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt/**
2247e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * xtables_set_params - set the global parameters used by xtables
2257e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp:	input xtables_globals structure
2267e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim *
2277e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * The app is expected to pass a valid xtables_globals data-filled
2287e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * with proper values
2297e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp cannot be NULL
2307e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim *
2317e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * Returns -1 on failure to set and 0 on success
2327e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim */
2337e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_set_params(struct xtables_globals *xtp)
2347e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{
2357e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	if (!xtp) {
2367e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		fprintf(stderr, "%s: Illegal global params\n",__func__);
2377e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		return -1;
2387e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	}
2397e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2407e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xt_params = xtp;
2417e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2427e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	if (!xt_params->exit_err)
2437e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		xt_params->exit_err = basic_exit_err;
2447e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2457e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	return 0;
2467e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim}
2477e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2487e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto)
2497e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{
2507e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xtables_init();
2517e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xtables_set_nfproto(nfproto);
2527e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	return xtables_set_params(xtp);
2537e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim}
2547e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2557e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim/**
256630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt * xtables_*alloc - wrappers that exit on failure
257630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt */
258630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_calloc(size_t count, size_t size)
2593dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
2603dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
2613dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2623dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = calloc(count, size)) == NULL) {
2633dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: calloc failed");
2643dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
2653dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
2663dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2673dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
2683dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
2693dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
270630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_malloc(size_t size)
2713dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
2723dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
2733dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2743dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = malloc(size)) == NULL) {
2753dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: malloc failed");
2763dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
2773dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
2783dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2793dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
2803dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
2810b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
282332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid *xtables_realloc(void *ptr, size_t size)
283332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
284332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	void *p;
285332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
286332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	if ((p = realloc(ptr, size)) == NULL) {
287332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		perror("ip[6]tables: realloc failed");
288332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		exit(1);
289332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
290332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
291332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	return p;
292332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
293332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
2940b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void)
2950b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
2960b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int procfile;
2970b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *ret;
2980b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
2990b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ	1024
3000b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
3010b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (procfile < 0)
3020b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return NULL;
3030b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
304371cea299f0b2eb100b9fc9fb99089640d2d606fJan Engelhardt	ret = malloc(PROCFILE_BUFSIZ);
3050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (ret) {
3060b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		memset(ret, 0, PROCFILE_BUFSIZ);
3070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
3080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case -1: goto fail;
3090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
3100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
3110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (ret[strlen(ret)-1]=='\n')
3120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			ret[strlen(ret)-1]=0;
3130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		close(procfile);
3140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return ret;
3150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail:
3170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(ret);
3180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	close(procfile);
3190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return NULL;
3200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
322c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_insmod(const char *modname, const char *modprobe, bool quiet)
3230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
3240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *buf = NULL;
3250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *argv[4];
3260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int status;
3270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	/* If they don't explicitly set it, read out of kernel */
3290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (!modprobe) {
3300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		buf = get_modprobe();
3310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (!buf)
3320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			return -1;
3330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		modprobe = buf;
3340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
336c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	/*
337c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * Need to flush the buffer, or the child may output it again
338c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * when switching the program thru execv.
339c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 */
340c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	fflush(stdout);
341c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt
34294aa2ea67d7b8a669e8541f094661a1dc89722a3Jan Engelhardt	switch (vfork()) {
3430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case 0:
3440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[0] = (char *)modprobe;
3450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[1] = (char *)modname;
3460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (quiet) {
3470b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = "-q";
3480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3490b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		} else {
3500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = NULL;
3510b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3520b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
3530b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		execv(argv[0], argv);
3540b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3550b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		/* not usually reached */
3560b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		exit(1);
3570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case -1:
3580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return -1;
3590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	default: /* parent */
3610b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		wait(&status);
3620b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3630b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3640b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(buf);
3650b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
3660b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return 0;
3670b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return -1;
3680b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3690b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
370c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_load_ko(const char *modprobe, bool quiet)
3710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
372c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	static bool loaded = false;
3730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	static int ret = -1;
3740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (!loaded) {
37677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ret = xtables_insmod(afinfo->kmod, modprobe, quiet);
3770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		loaded = (ret == 0);
3780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ret;
3810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
3820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3835f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt/**
3845f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * xtables_strtou{i,l} - string to number conversion
3855f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @s:	input string
3865f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @end:	like strtoul's "end" pointer
3875f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @value:	pointer for result
3885f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @min:	minimum accepted value
3895f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @max:	maximum accepted value
3905f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt *
3915f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * If @end is NULL, we assume the caller wants a "strict strtoul", and hence
3925f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * "15a" is rejected.
3935f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * In either case, the value obtained is compared for min-max compliance.
3945f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Base is always 0, i.e. autodetect depending on @s.
395cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *
3965f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Returns true/false whether number was accepted. On failure, *value has
3975f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * undefined contents.
398cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */
3995f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoul(const char *s, char **end, unsigned long *value,
4005f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt                     unsigned long min, unsigned long max)
401cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
402cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	unsigned long v;
403cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	char *my_end;
404cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
405cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	errno = 0;
406cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	v = strtoul(s, &my_end, 0);
407cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
408cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (my_end == s)
409cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return false;
410cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (end != NULL)
411cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*end = my_end;
412cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
413cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (errno != ERANGE && min <= v && (max == 0 || v <= max)) {
414cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (value != NULL)
415cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			*value = v;
416cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (end == NULL)
417cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			return *my_end == '\0';
418cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return true;
419cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	}
420cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
421cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return false;
422cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
423cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4245f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoui(const char *s, char **end, unsigned int *value,
4255f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt                     unsigned int min, unsigned int max)
426cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
427cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	unsigned long v;
428cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	bool ret;
429cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4305f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	ret = xtables_strtoul(s, end, &v, min, max);
431cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (value != NULL)
432cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*value = v;
433cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return ret;
434cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
435cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
436aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtint xtables_service_to_port(const char *name, const char *proto)
43704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
43804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	struct servent *service;
43904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
44004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((service = getservbyname(name, proto)) != NULL)
44104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		return ntohs((unsigned short) service->s_port);
44204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
44304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return -1;
44404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
44504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4467ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t xtables_parse_port(const char *port, const char *proto)
44704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
4487a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt	unsigned int portnum;
44904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4505f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) ||
451aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt	    (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1)
452213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt		return portnum;
45304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4548b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM,
45504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		   "invalid port/service `%s' specified", port);
45604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
45704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
458aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtvoid xtables_parse_interface(const char *arg, char *vianame,
459aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt			     unsigned char *mask)
46004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
461fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	unsigned int vialen = strlen(arg);
46204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned int i;
46304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
46404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(mask, 0, IFNAMSIZ);
46504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(vianame, 0, IFNAMSIZ);
46604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
46704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if (vialen + 1 > IFNAMSIZ)
4688b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
46904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   "interface name `%s' must be shorter than IFNAMSIZ"
47004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   " (%i)", arg, IFNAMSIZ-1);
47104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
47204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	strcpy(vianame, arg);
473fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	if (vialen == 0)
47404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0, IFNAMSIZ);
47504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	else if (vianame[vialen - 1] == '+') {
47604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen - 1);
47704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
47804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Don't remove `+' here! -HW */
47904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	} else {
48004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Include nul-terminator in match */
48104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen + 1);
48204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
48304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		for (i = 0; vianame[i]; i++) {
484fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			if (vianame[i] == '/' ||
485fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			    vianame[i] == ' ') {
486aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann				fprintf(stderr,
487aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					"Warning: weird character in interface"
488fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt					" `%s' ('/' and ' ' are not allowed by the kernel).\n",
489aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					vianame);
49004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI				break;
49104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			}
49204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		}
49304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	}
49404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
49504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
496cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS
497927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardtstatic void *load_extension(const char *search_path, const char *af_prefix,
49821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt    const char *name, bool is_target)
49921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{
500927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt	const char *all_prefixes[] = {"libxt_", af_prefix, NULL};
501927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt	const char **prefix;
50221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	const char *dir = search_path, *next;
50321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	void *ptr = NULL;
50421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	struct stat sb;
50521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	char path[256];
50621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
50721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	do {
50821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		next = strchr(dir, ':');
50921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (next == NULL)
51021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			next = dir + strlen(dir);
51121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
512927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt		for (prefix = all_prefixes; *prefix != NULL; ++prefix) {
513927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			snprintf(path, sizeof(path), "%.*s/%s%s.so",
514927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			         (unsigned int)(next - dir), dir,
515927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			         *prefix, name);
516927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt
517927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (stat(path, &sb) != 0) {
518927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				if (errno == ENOENT)
519927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt					continue;
520927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				fprintf(stderr, "%s: %s\n", path,
521927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt					strerror(errno));
522927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				return NULL;
523927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			}
524927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (dlopen(path, RTLD_NOW) == NULL) {
525927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				fprintf(stderr, "%s: %s\n", path, dlerror());
526927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				break;
527927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			}
52821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
52921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			if (is_target)
5302338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_target(name, XTF_DONT_LOAD);
53121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			else
5322338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_match(name,
5332338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				      XTF_DONT_LOAD, NULL);
53421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
535927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (ptr != NULL)
536927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				return ptr;
53721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
538927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			fprintf(stderr, "%s: no \"%s\" extension found for "
539927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				"this protocol\n", path, name);
540927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			errno = ENOENT;
541927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			return NULL;
542927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt		}
54321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		dir = next + 1;
54421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	} while (*next != '\0');
54521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
54621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	return NULL;
54721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt}
548cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif
54921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
5502338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_match *
5512338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_match(const char *name, enum xtables_tryload tryload,
5522338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		   struct xtables_rule_match **matches)
5530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
5540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match *ptr;
5550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	const char *icmp6 = "icmp6";
5560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5570cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(name) >= XT_EXTENSION_MAXNAMELEN)
55821d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt		xtables_error(PARAMETER_PROBLEM,
55921d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt			   "Invalid match name \"%s\" (%u chars max)",
5600cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt			   name, XT_EXTENSION_MAXNAMELEN - 1);
56121d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt
5620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* This is ugly as hell. Nonetheless, there is no way of changing
5630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	 * this without hurting backwards compatibility */
5640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if ( (strcmp(name,"icmpv6") == 0) ||
5650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"ipv6-icmp") == 0) ||
5660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"icmp6") == 0) )
5670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = icmp6;
5680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_matches; ptr; ptr = ptr->next) {
5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0) {
5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			struct xtables_match *clone;
5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* First match of this type: */
5740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (ptr->m == NULL)
5750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				break;
5760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Second and subsequent clones */
578630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt			clone = xtables_malloc(sizeof(struct xtables_match));
5790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			memcpy(clone, ptr, sizeof(struct xtables_match));
5800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->mflags = 0;
5810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* This is a clone: */
5820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->next = clone;
5830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = clone;
5850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
5860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
5870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
5902338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
59177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
59239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, false);
593170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
5942338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
5958b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load match `%s':%s\n",
597927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				   name, strerror(errno));
5980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
6000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
6012338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
6020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
6030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
6040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
6050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6062338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) {
6078b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find match `%s'\n", name);
6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
6110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && matches) {
6130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match **i;
6140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match *newentry;
6150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
616630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		newentry = xtables_malloc(sizeof(struct xtables_rule_match));
6170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = matches; *i; i = &(*i)->next) {
6190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (strcmp(name, (*i)->match->name) == 0)
6202338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				(*i)->completed = true;
6210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
6220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->match = ptr;
6232338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		newentry->completed = false;
6240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->next = NULL;
6250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = newentry;
6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6312338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_target *
6322338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_target(const char *name, enum xtables_tryload tryload)
6330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
6340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *ptr;
6350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Standard target? */
6370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(name, "") == 0
6380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_ACCEPT) == 0
6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_DROP) == 0
6400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_QUEUE) == 0
6410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_RETURN) == 0)
6420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = "standard";
6430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_targets; ptr; ptr = ptr->next) {
6450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0)
6460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
6470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
6502338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
65177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
65239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, true);
653170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
6542338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
6558b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
6560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load target `%s':%s\n",
657927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				   name, strerror(errno));
6580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
6600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
6612338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
6620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
6630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
6640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
6650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
666854d2d9bd7556cfd8a676b0bc18dc059a9a2dd25Peter Volkov	if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) {
6678b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
6680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find target `%s'\n", name);
6690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
6710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr)
6730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		ptr->used = 1;
6740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
6760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
6770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6787ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_revision(const char *name, uint8_t revision, int opt)
6790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
6800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xt_get_revision rev;
6810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	socklen_t s = sizeof(rev);
6820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	int max_rev, sockfd;
6830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
68477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);
6850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (sockfd < 0) {
686df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		if (errno == EPERM) {
687df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			/* revision 0 is always supported. */
688df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			if (revision != 0)
689df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy				fprintf(stderr, "Could not determine whether "
690df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"revision %u is supported, "
691df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"assuming it is.\n",
692df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy					revision);
693df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			return 1;
694df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		}
6950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "Could not open socket to kernel: %s\n",
6960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			strerror(errno));
6970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
6980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
700c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	xtables_load_ko(xtables_modprobe_program, true);
7010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	strcpy(rev.name, name);
7030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	rev.revision = revision;
7040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
70577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s);
7060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (max_rev < 0) {
7070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Definitely don't support this? */
7080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (errno == ENOENT || errno == EPROTONOSUPPORT) {
7090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
7100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return 0;
7110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else if (errno == ENOPROTOOPT) {
7120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
7130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Assume only revision 0 support (old kernel) */
7140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return (revision == 0);
7150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else {
7160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr, "getsockopt failed strangely: %s\n",
7170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				strerror(errno));
7180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
7190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
7200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	close(sockfd);
7220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return 1;
7230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7267ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_match_revision(const char *name, uint8_t revision)
7270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
72877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_match);
7290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7317ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_target_revision(const char *name, uint8_t revision)
7320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
73377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_target);
7340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
736dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardtstatic void xtables_check_options(const char *name, const struct option *opt)
737dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt{
738dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	for (; opt->name != NULL; ++opt)
739dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) {
740dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			fprintf(stderr, "%s: Extension %s uses invalid "
741dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			        "option value %d\n",xt_params->program_name,
742dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			        name, opt->val);
743dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			exit(1);
744dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		}
745dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt}
746dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
7470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me)
7480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
7490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match **i, *old;
7500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
751c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
752c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: match %s<%u> is missing a version\n",
753c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
754c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
755c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
756dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
757dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
758dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
7595dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
760dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
7610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7640cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
765281439ba6b96b729ef1400a49ec53eda298bb9f8Li Yewang		fprintf(stderr, "%s: match `%s' has invalid name\n",
7665dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
7670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
7710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
7720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: match %s has invalid protocol family\n",
7735dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
7740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
777dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	if (me->extra_opts != NULL)
778dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		xtables_check_options(me->name, me->extra_opts);
779dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
7800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested match */
78177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
7820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
7830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7842338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
7850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
78623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision &&
78723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		    old->family == me->family) {
7880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
7890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: match `%s' already registered.\n",
7905dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
7910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
7920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
7930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
7950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_match_revision(old->name, old->revision)
7960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
7970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
7980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
79923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new match can be used. */
8000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_match_revision(me->name, me->revision))
8010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
80323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
80423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision && me->family == AF_UNSPEC)
80523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt			return;
80623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt
8070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
8080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
8090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
8100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
8130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
8145dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
8155dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
8160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Append to list. */
8200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (i = &xtables_matches; *i; i = &(*i)->next);
8210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = NULL;
8220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	*i = me;
8230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->m = NULL;
8250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->mflags = 0;
8260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
8270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8289a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_matches(struct xtables_match *match, unsigned int n)
8299a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
8309a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
8319a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_match(&match[--n]);
8329a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
8339a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
8349a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
8350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me)
8360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
8370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *old;
8380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
839c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
840c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
841c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
842c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
843c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
844dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
845dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
846dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
8475dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
848dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
8490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8520cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
8530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
8545dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
8590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
8600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: target %s has invalid protocol family\n",
8615dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
865dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	if (me->extra_opts != NULL)
866dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		xtables_check_options(me->name, me->extra_opts);
867dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
8680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested target */
86977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
8700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
8710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8722338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_target(me->name, XTF_DURING_LOAD);
8730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
8740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_target **i;
8750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
87623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision &&
87723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		    old->family == me->family) {
8780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
8790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: target `%s' already registered.\n",
8805dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
8810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
8820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
8830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
8850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_target_revision(old->name, old->revision)
8860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
8870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
88923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new target can be used. */
8900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_target_revision(me->name, me->revision))
8910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
89323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
89423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision && me->family == AF_UNSPEC)
89523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt			return;
89623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt
8970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
8980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
8990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
9000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
9030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
9045dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
9055dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
9060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Prepend to list. */
9100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = xtables_targets;
9110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	xtables_targets = me;
9120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->t = NULL;
9130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->tflags = 0;
9140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
915aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
9169a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_targets(struct xtables_target *target, unsigned int n)
9179a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
9189a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
9199a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_target(&target[--n]);
9209a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
9219a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
9229a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
923a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt/**
924a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * xtables_param_act - act on condition
925a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @status:	a constant from enum xtables_exittype
926a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
927a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONLY_ONCE: print error message that option may only be used once.
928a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name (e.g. "mark")
929a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2(...):	option in conflict (e.g. "--mark")
930a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3(...):	condition to match on (see extensions/ for examples)
931a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
932a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_NO_INVERT: option does not support inversion
933a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
934a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option in conflict
935a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		condition to match on
936a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
937a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_BAD_VALUE: bad value for option
938a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
939a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option with which the problem occured (e.g. "--mark")
940a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		string the user passed in (e.g. "99999999999999")
941a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
942a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONE_ACTION: two mutually exclusive actions have been specified
943a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
944a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
945a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * Displays an error message and exits the program.
946a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt */
947a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardtvoid xtables_param_act(unsigned int status, const char *p1, ...)
948aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{
949aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	const char *p2, *p3;
950aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_list args;
951aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	bool b;
952aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
953aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_start(args, p1);
954aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
955aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	switch (status) {
956a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONLY_ONCE:
957aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
958aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
959aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
960aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9618b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
962aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option may only be specified once",
963aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2);
964aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
965a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_NO_INVERT:
966aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
967aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
968aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
969aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9708b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
971aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option cannot be inverted", p1, p2);
972aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
973a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_BAD_VALUE:
974aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
975aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p3 = va_arg(args, const char *);
9768b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
977aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: Bad value for \"%s\" option: \"%s\"",
978aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2, p3);
979aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
980a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONE_ACTION:
981aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b = va_arg(args, unsigned int);
982aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
983aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9848b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
985aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: At most one action is possible", p1);
986aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
987aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	default:
9888b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(status, p1, args);
989aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
990aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	}
991aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
992aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_end(args);
993aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt}
99408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
995e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp)
99608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
99708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[20];
99808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const unsigned char *bytep = (const void *)&addrp->s_addr;
99908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
100008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
100108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
100208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
100308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
100408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr)
100508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
100608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct hostent *host;
100708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
100808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET);
100908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (host == NULL)
101008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
101108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
101208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return host->h_name;
101308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
101408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
101508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr)
101608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
101708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct netent *net;
101808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
101908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL)
102008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return net->n_name;
102108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
102208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return NULL;
102308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
102408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1025e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr)
102608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
102708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
102808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
102908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ipaddr_to_host(addr)) != NULL ||
103008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	    (name = ipaddr_to_network(addr)) != NULL)
103108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
103208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1033e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ipaddr_to_numeric(addr);
103408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
103508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1036e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipmask_to_numeric(const struct in_addr *mask)
103708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
103808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[20];
103908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t maskaddr, bits;
104008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int i;
104108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
104208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	maskaddr = ntohl(mask->s_addr);
104308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
104408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (maskaddr == 0xFFFFFFFFL)
104508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		/* we don't want to see "/32" */
104608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return "";
104708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
104808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	i = 32;
104908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	bits = 0xFFFFFFFEL;
105008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (--i >= 0 && maskaddr != bits)
105108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		bits <<= 1;
105208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (i >= 0)
105308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		sprintf(buf, "/%d", i);
105408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	else
105508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		/* mask was not a decent combination of 1's and 0's */
1056e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
105708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
105808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
105908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
106008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1061bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask)
1062bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1063bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1064bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned char *addrp;
1065bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int onebyte;
1066bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[20], *p, *q;
1067bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int i;
1068bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1069bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* copy dotted string, because we need to modify it */
1070bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, dotted, sizeof(buf) - 1);
1071bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1072bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = (void *)&addr.s_addr;
1073bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1074bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	p = buf;
1075bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0; i < 3; ++i) {
1076bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if ((q = strchr(p, '.')) == NULL) {
1077bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (is_mask)
1078bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1079bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1080bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			/* autocomplete, this is a network address */
10815f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt			if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1082bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1083bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1084bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			addrp[i] = onebyte;
1085bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			while (i < 3)
1086bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				addrp[++i] = 0;
1087bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1088bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return &addr;
1089bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		}
1090bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1091bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*q = '\0';
10925f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt		if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1093bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1094bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1095bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[i] = onebyte;
1096bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p = q + 1;
1097bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1098bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1099bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* we have checked 3 bytes, now we check the last one */
11005f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1101bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1102bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1103bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp[3] = onebyte;
1104bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &addr;
1105bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1106bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11071e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted)
1108bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1109bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, false);
1110bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1111bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11121e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipmask(const char *dotted)
1113bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1114bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, true);
1115bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1116bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1117bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name)
1118bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1119bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1120bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct netent *net;
1121bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1122bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((net = getnetbyname(name)) != NULL) {
1123bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (net->n_addrtype != AF_INET)
1124bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1125bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addr.s_addr = htonl(net->n_net);
1126bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &addr;
1127bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1128bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1129bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1130bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1131bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1132bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
1133bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1134bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct hostent *host;
1135bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addr;
1136bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i;
1137bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1138bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1139bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((host = gethostbyname(name)) != NULL) {
1140bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (host->h_addrtype != AF_INET ||
1141bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		    host->h_length != sizeof(struct in_addr))
1142bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1143bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1144bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		while (host->h_addr_list[*naddr] != NULL)
1145bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			++*naddr;
114611e250ba02349cb1e34058673db3d0b54eb56c44Wes Campaigne		addr = xtables_calloc(*naddr, sizeof(struct in_addr));
1147bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (i = 0; i < *naddr; i++)
1148bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			memcpy(&addr[i], host->h_addr_list[i],
1149bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			       sizeof(struct in_addr));
1150bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1151bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1152bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1153bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1154bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1155bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1156bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *
1157bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs)
1158bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1159bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrptmp, *addrp;
1160bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11611e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL ||
1162bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ipaddr(name)) != NULL) {
1163630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in_addr));
1164bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1165bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1166bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1167bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1168bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL)
1169bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrptmp;
1170bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11718b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1172bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1173bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1174bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask)
1175bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1176bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr maskaddr;
1177bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1178bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1179bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1180bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1181bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 32 bits */
1182bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = 0xFFFFFFFF;
1183bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1184bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
11851e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL)
1186bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* dotted_to_addr already returns a network byte order addr */
1187bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
11885f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 32))
11898b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1190bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1191bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1192bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
1193bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1194bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1195bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1196bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	maskaddr.s_addr = 0U;
1197bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1198bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1199bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1200332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
1201332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow                              struct in_addr **maskpp, unsigned int *naddrs)
1202332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
1203332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in_addr *addrp;
1204332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	char buf[256], *p;
1205332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1206332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1207332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1208332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1209332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1210332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1211332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1212332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1213332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
1214332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
1215332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1216332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1217332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1218332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count; ++i) {
1219332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (loop == NULL)
1220332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1221332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == ',')
1222332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			++loop;
1223332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == '\0')
1224332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1225332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		p = strchr(loop, ',');
1226332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (p != NULL)
1227332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = p - loop;
1228332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1229332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1230332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (len == 0 || sizeof(buf) - 1 < len)
1231332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1232332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1233332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1234332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1235332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		loop += len;
1236332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1237332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1238332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(p + 1);
1239332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1240332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(NULL);
1241332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1242332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1243332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1244332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
1245332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((*maskpp + i)->s_addr == 0)
1246332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			/*
1247332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * A bit pointless to process multiple addresses
1248332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * in this case...
1249332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 */
1250332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "0.0.0.0");
1251332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1252332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ipparse_hostnetwork(buf, &n);
1253332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1254332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1255332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1256332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1257332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1258332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1259332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1260332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1261332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1262332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1263332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1264332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1265332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1266332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1267332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1268332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1269332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1270332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1271332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ipparse_hostnetwork had allocated: */
1272332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1273332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1274332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
12754b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt	for (i = 0; i < count; ++i)
1276332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
1277332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1278332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1279332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1280a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt/**
1281a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * xtables_ipparse_any - transform arbitrary name to in_addr
1282a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt *
1283a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * Possible inputs (pseudo regex):
1284a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * 	m{^($hostname|$networkname|$ipaddr)(/$mask)?}
1285a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname"
1286a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt */
1287a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp,
1288a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                         struct in_addr *maskp, unsigned int *naddrs)
1289bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1290bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1291bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1292bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1293bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1294bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1295bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1296bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1297bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1298bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(p + 1);
1299bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1300bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(NULL);
1301bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1302bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1303bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1304bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
1305bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (maskp->s_addr == 0U)
1306bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "0.0.0.0");
1307bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1308bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ipparse_hostnetwork(buf, naddrs);
1309bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1310bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1311bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[j++].s_addr &= maskp->s_addr;
1312bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1313bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (addrp[k].s_addr == addrp[j-1].s_addr) {
1314adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				/*
1315adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * Nuke the dup by copying an address from the
1316adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * tail here, and check the current position
1317adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * again (--j).
1318adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 */
1319adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				memcpy(&addrp[--j], &addrp[--*naddrs],
1320adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				       sizeof(struct in_addr));
1321bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1322bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1323bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1324bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1325bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1326e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp)
132708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
132808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	/* 0000:0000:0000:0000:0000:000.000.000.000
132908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	 * 0000:0000:0000:0000:0000:0000:0000:0000 */
133008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+1];
133108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
133208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
133308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
133408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr)
133508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
133608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char hostname[NI_MAXHOST];
133708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct sockaddr_in6 saddr;
133808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int err;
133908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
134008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memset(&saddr, 0, sizeof(struct sockaddr_in6));
134108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memcpy(&saddr.sin6_addr, addr, sizeof(*addr));
134208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	saddr.sin6_family = AF_INET6;
134308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
134408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6),
134508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	      hostname, sizeof(hostname) - 1, NULL, 0, 0);
134608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (err != 0) {
134708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
134808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		fprintf(stderr,"IP2Name: %s\n",gai_strerror(err));
134908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
135008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
135108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
135208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
135308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
135408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	fprintf (stderr, "\naddr2host: %s\n", hostname);
135508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
135608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return hostname;
135708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
135808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1359e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr)
136008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
136108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
136208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
136308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ip6addr_to_host(addr)) != NULL)
136408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
136508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1366e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ip6addr_to_numeric(addr);
136708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
136808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
136908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic int ip6addr_prefix_length(const struct in6_addr *k)
137008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
137108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	unsigned int bits = 0;
137208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t a, b, c, d;
137308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
137448607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	a = ntohl(k->s6_addr32[0]);
137548607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	b = ntohl(k->s6_addr32[1]);
137648607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	c = ntohl(k->s6_addr32[2]);
137748607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	d = ntohl(k->s6_addr32[3]);
137808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (a & 0x80000000U) {
137908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		++bits;
138008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a <<= 1;
138108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a  |= (b >> 31) & 1;
138208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b <<= 1;
138308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b  |= (c >> 31) & 1;
138408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c <<= 1;
138508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c  |= (d >> 31) & 1;
138608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		d <<= 1;
138708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
138808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (a != 0 || b != 0 || c != 0 || d != 0)
138908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return -1;
139008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return bits;
139108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
139208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1393e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
139408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
139508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+2];
139608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int l = ip6addr_prefix_length(addrp);
139708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
139808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (l == -1) {
139908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		strcpy(buf, "/");
1400e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		strcat(buf, xtables_ip6addr_to_numeric(addrp));
140108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return buf;
140208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
140308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "/%d", l);
140408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
140508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
1406bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
14071e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in6_addr *xtables_numeric_to_ip6addr(const char *num)
1408bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1409bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr ap;
1410bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
1411bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1412bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
1413bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &ap;
1414bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1415bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	fprintf(stderr, "\nnumeric2addr: %d\n", err);
1416bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1417bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1418bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1419bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1420bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1421bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr)
1422bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
14232ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	struct in6_addr *addr;
1424bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct addrinfo hints;
14252ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	struct addrinfo *res, *p;
1426bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
14272ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	unsigned int i;
1428bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1429bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&hints, 0, sizeof(hints));
1430bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_flags    = AI_CANONNAME;
1431bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_family   = AF_INET6;
1432bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_socktype = SOCK_RAW;
1433bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1434bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1435bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
1436bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1437bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr,"Name2IP: %s\n",gai_strerror(err));
1438bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1439bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1440bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
14412ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		/* Find length of address chain */
14422ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		for (p = res; p != NULL; p = p->ai_next)
14432ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			++*naddr;
1444bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1445bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr, "resolved: len=%d  %s ", res->ai_addrlen,
144630290aea009cf3fd76f27336fb4370be3467c4daPatrick McHardy		        xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr));
1447bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
14482ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		/* Copy each element of the address chain */
14492ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		addr = xtables_calloc(*naddr, sizeof(struct in6_addr));
14502ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		for (i = 0, p = res; p != NULL; p = p->ai_next)
14512ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			memcpy(&addr[i++],
14522ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			       &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr,
14532ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			       sizeof(struct in6_addr));
1454bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		freeaddrinfo(res);
1455bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1456bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1457bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1458bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1459bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1460bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1461bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name)
1462bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1463bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/*	abort();*/
1464bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* TODO: not implemented yet, but the exception breaks the
1465bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	 *       name resolvation */
1466bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1467bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1468bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1469bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1470bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs)
1471bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1472bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp, *addrptmp;
1473bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
14741e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL ||
1475bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ip6addr(name)) != NULL) {
1476630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in6_addr));
1477bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1478bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1479bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1480bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1481bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrp = host_to_ip6addr(name, naddrs)) != NULL)
1482bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1483bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
14848b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1485bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1486bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1487bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask)
1488bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1489bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr maskaddr;
1490bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1491bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1492bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1493bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1494bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 128 bits */
1495bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(&maskaddr, 0xff, sizeof maskaddr);
1496bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1497bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
14981e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL)
1499bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
15005f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
15018b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1502bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1503bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1504bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		char *p = (void *)&maskaddr;
1505bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p, 0xff, bits / 8);
1506bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
1507bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p[bits/8] = 0xff << (8 - (bits & 7));
1508bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1509bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1510bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1511bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&maskaddr, 0, sizeof(maskaddr));
1512bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1513bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1514bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1515332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid
1516332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowxtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
1517332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		      struct in6_addr **maskpp, unsigned int *naddrs)
1518332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
151958df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel	static const struct in6_addr zero_addr;
1520332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in6_addr *addrp;
1521332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	char buf[256], *p;
1522332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1523332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1524332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1525332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1526332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1527332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1528332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1529332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1530332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
1531332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
1532332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1533332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1534332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1535332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count /*NB: count can grow*/; ++i) {
1536332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (loop == NULL)
1537332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1538332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == ',')
1539332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			++loop;
1540332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == '\0')
1541332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1542332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		p = strchr(loop, ',');
1543332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (p != NULL)
1544332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = p - loop;
1545332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1546332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1547332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (len == 0 || sizeof(buf) - 1 < len)
1548332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1549332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1550332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1551332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1552332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		loop += len;
1553332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1554332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1555332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(p + 1);
1556332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1557332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(NULL);
1558332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1559332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1560332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1561332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
156258df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel		if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0)
1563332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "::");
1564332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1565332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ip6parse_hostnetwork(buf, &n);
1566332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1567332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1568332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1569332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1570332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1571332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1572332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1573332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1574332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1575332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1576332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1577332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1578332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1579332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1580332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1581332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1582332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1583332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1584332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ip6parse_hostnetwork had allocated: */
1585332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1586332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1587332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
15884b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt	for (i = 0; i < count; ++i)
1589332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		for (j = 0; j < 4; ++j)
1590332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
1591332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1592332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1593a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
1594a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                          struct in6_addr *maskp, unsigned int *naddrs)
1595bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
15969c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	static const struct in6_addr zero_addr;
1597bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1598bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1599bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1600bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1601bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1602bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf)-1] = '\0';
1603bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1604bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1605bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(p + 1);
1606bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1607bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(NULL);
1608bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1609bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1610bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1611bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
16129c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0)
1613bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "::");
1614bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1615bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs);
1616bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1617bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1618bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < 4; ++k)
16195a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai			addrp[j].s6_addr32[k] &= maskp->s6_addr32[k];
1620bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		++j;
1621bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1622bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
1623adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				/*
1624adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * Nuke the dup by copying an address from the
1625adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * tail here, and check the current position
1626adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * again (--j).
1627adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 */
1628adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				memcpy(&addrp[--j], &addrp[--*naddrs],
1629adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				       sizeof(struct in_addr));
1630bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1631bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1632bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1633bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1634a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1635a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_save_string(const char *value)
1636a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{
1637a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char no_quote_chars[] = "_-0123456789"
1638a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"abcdefghijklmnopqrstuvwxyz"
1639a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1640a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char escape_chars[] = "\"\\'";
1641a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	size_t length;
1642a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	const char *p;
1643a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
164487dc7c4c842deb1e2e3d38089ffcad9f238d98deMax Kellerman	length = strspn(value, no_quote_chars);
1645a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	if (length > 0 && value[length] == 0) {
1646a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* no quoting required */
1647a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		putchar(' ');
164873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		fputs(value, stdout);
1649a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	} else {
1650a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* there is at least one dangerous character in the
1651a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   value, which we have to quote.  Write double quotes
1652a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   around the value and escape special characters with
1653a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   a backslash */
165473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" \"");
1655a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1656a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		for (p = strpbrk(value, escape_chars); p != NULL;
1657a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		     p = strpbrk(value, escape_chars)) {
1658a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			if (p > value)
1659a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann				fwrite(value, 1, p - value, stdout);
1660a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar('\\');
1661a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar(*p);
1662a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			value = p + 1;
1663a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		}
1664a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1665a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* print the rest and finish the double quoted
1666a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   string */
1667a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		fputs(value, stdout);
166873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		putchar('\"');
1669a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	}
1670a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann}
16710f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16720f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt/**
16730f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Check for option-intrapositional negation.
16740f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Do not use in new code.
16750f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt */
16760f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardtint xtables_check_inverse(const char option[], int *invert,
1677bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt			  int *my_optind, int argc, char **argv)
16780f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt{
16792be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (option == NULL || strcmp(option, "!") != 0)
16802be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		return false;
16810f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16822be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	fprintf(stderr, "Using intrapositioned negation "
16832be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	        "(`--option ! this`) is deprecated in favor of "
16842be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	        "extrapositioned (`! --option this`).\n");
16850f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16862be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (*invert)
16872be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
16882be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt			   "Multiple `!' flags not allowed");
16892be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	*invert = true;
16902be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (my_optind != NULL) {
1691bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt		optarg = argv[*my_optind];
16922be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		++*my_optind;
16932be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		if (argc && *my_optind > argc)
16942be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
16952be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt				   "no argument following `!'");
16960f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt	}
16972be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt
16982be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	return true;
16990f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt}
17001de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17011de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtconst struct xtables_pprot xtables_chain_protos[] = {
17021de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"tcp",       IPPROTO_TCP},
17031de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"sctp",      IPPROTO_SCTP},
17041de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udp",       IPPROTO_UDP},
17051de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udplite",   IPPROTO_UDPLITE},
17061de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmp",      IPPROTO_ICMP},
17071de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmpv6",    IPPROTO_ICMPV6},
17081de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-icmp", IPPROTO_ICMPV6},
17091de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"esp",       IPPROTO_ESP},
17101de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ah",        IPPROTO_AH},
17111de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-mh",   IPPROTO_MH},
17121de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"mh",        IPPROTO_MH},
17131de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"all",       0},
17141de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{NULL},
17151de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt};
17161de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17177ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t
17181de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtxtables_parse_protocol(const char *s)
17191de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt{
17201de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	unsigned int proto;
17211de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17221de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) {
17231de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		struct protoent *pent;
17241de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17251de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		/* first deal with the special case of 'all' to prevent
17261de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * people from being able to redefine 'all' in nsswitch
17271de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * and/or provoke expensive [not working] ldap/nis/...
17281de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * lookups */
17291de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		if (!strcmp(s, "all"))
17301de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			return 0;
17311de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17321de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		if ((pent = getprotobyname(s)))
17331de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			proto = pent->p_proto;
17341de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		else {
17351de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			unsigned int i;
17361de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
1737e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso				if (xtables_chain_protos[i].name == NULL)
1738e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso					continue;
1739e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso
17401de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt				if (strcmp(s, xtables_chain_protos[i].name) == 0) {
17411de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					proto = xtables_chain_protos[i].num;
17421de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					break;
17431de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt				}
17441de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			}
17451de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			if (i == ARRAY_SIZE(xtables_chain_protos))
17468b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim				xt_params->exit_err(PARAMETER_PROBLEM,
17471de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					   "unknown protocol `%s' specified",
17481de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					   s);
17491de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		}
17501de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	}
17511de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17521de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	return proto;
17531de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt}
1754