xtables.c revision cf3e52d00b7d3fedf98ef7710c337c441270d936
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;
303a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) {
304a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		fprintf(stderr, "Could not set close on exec: %s\n",
305a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski			strerror(errno));
306a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		exit(1);
307a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	}
3080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
309371cea299f0b2eb100b9fc9fb99089640d2d606fJan Engelhardt	ret = malloc(PROCFILE_BUFSIZ);
3100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (ret) {
3110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		memset(ret, 0, PROCFILE_BUFSIZ);
3120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
3130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case -1: goto fail;
3140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
3150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
3160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (ret[strlen(ret)-1]=='\n')
3170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			ret[strlen(ret)-1]=0;
3180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		close(procfile);
3190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return ret;
3200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail:
3220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(ret);
3230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	close(procfile);
3240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return NULL;
3250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
327c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_insmod(const char *modname, const char *modprobe, bool quiet)
3280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
3290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *buf = NULL;
3300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *argv[4];
3310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int status;
3320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	/* If they don't explicitly set it, read out of kernel */
3340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (!modprobe) {
3350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		buf = get_modprobe();
3360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (!buf)
3370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			return -1;
3380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		modprobe = buf;
3390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
341c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	/*
342c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * Need to flush the buffer, or the child may output it again
343c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * when switching the program thru execv.
344c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 */
345c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	fflush(stdout);
346c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt
34794aa2ea67d7b8a669e8541f094661a1dc89722a3Jan Engelhardt	switch (vfork()) {
3480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case 0:
3490b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[0] = (char *)modprobe;
3500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[1] = (char *)modname;
3510b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (quiet) {
3520b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = "-q";
3530b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3540b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		} else {
3550b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = NULL;
3560b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
3580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		execv(argv[0], argv);
3590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		/* not usually reached */
3610b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		exit(1);
3620b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case -1:
3630b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return -1;
3640b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3650b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	default: /* parent */
3660b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		wait(&status);
3670b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3680b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3690b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(buf);
3700b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
3710b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return 0;
3720b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return -1;
3730b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3740b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
375c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_load_ko(const char *modprobe, bool quiet)
3760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
377c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	static bool loaded = false;
3780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	static int ret = -1;
3790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (!loaded) {
38177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ret = xtables_insmod(afinfo->kmod, modprobe, quiet);
3820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		loaded = (ret == 0);
3830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ret;
3860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
3870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3885f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt/**
3895f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * xtables_strtou{i,l} - string to number conversion
3905f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @s:	input string
3915f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @end:	like strtoul's "end" pointer
3925f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @value:	pointer for result
3935f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @min:	minimum accepted value
3945f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @max:	maximum accepted value
3955f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt *
3965f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * If @end is NULL, we assume the caller wants a "strict strtoul", and hence
3975f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * "15a" is rejected.
3985f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * In either case, the value obtained is compared for min-max compliance.
3995f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Base is always 0, i.e. autodetect depending on @s.
400cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *
4015f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Returns true/false whether number was accepted. On failure, *value has
4025f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * undefined contents.
403cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */
4045f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoul(const char *s, char **end, unsigned long *value,
4055f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt                     unsigned long min, unsigned long max)
406cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
407cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	unsigned long v;
408cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	char *my_end;
409cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
410cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	errno = 0;
411cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	v = strtoul(s, &my_end, 0);
412cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
413cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (my_end == s)
414cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return false;
415cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (end != NULL)
416cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*end = my_end;
417cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
418cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (errno != ERANGE && min <= v && (max == 0 || v <= max)) {
419cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (value != NULL)
420cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			*value = v;
421cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (end == NULL)
422cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			return *my_end == '\0';
423cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return true;
424cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	}
425cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
426cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return false;
427cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
428cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4295f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoui(const char *s, char **end, unsigned int *value,
4305f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt                     unsigned int min, unsigned int max)
431cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
432cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	unsigned long v;
433cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	bool ret;
434cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4355f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	ret = xtables_strtoul(s, end, &v, min, max);
436cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (value != NULL)
437cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*value = v;
438cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return ret;
439cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
440cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
441aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtint xtables_service_to_port(const char *name, const char *proto)
44204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
44304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	struct servent *service;
44404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
44504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((service = getservbyname(name, proto)) != NULL)
44604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		return ntohs((unsigned short) service->s_port);
44704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
44804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return -1;
44904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
45004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4517ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t xtables_parse_port(const char *port, const char *proto)
45204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
4537a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt	unsigned int portnum;
45404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4555f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) ||
456aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt	    (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1)
457213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt		return portnum;
45804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4598b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM,
46004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		   "invalid port/service `%s' specified", port);
46104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
46204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
463aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtvoid xtables_parse_interface(const char *arg, char *vianame,
464aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt			     unsigned char *mask)
46504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
466fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	unsigned int vialen = strlen(arg);
46704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned int i;
46804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
46904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(mask, 0, IFNAMSIZ);
47004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(vianame, 0, IFNAMSIZ);
47104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
47204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if (vialen + 1 > IFNAMSIZ)
4738b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
47404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   "interface name `%s' must be shorter than IFNAMSIZ"
47504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   " (%i)", arg, IFNAMSIZ-1);
47604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
47704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	strcpy(vianame, arg);
478fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	if (vialen == 0)
47904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0, IFNAMSIZ);
48004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	else if (vianame[vialen - 1] == '+') {
48104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen - 1);
48204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
48304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Don't remove `+' here! -HW */
48404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	} else {
48504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Include nul-terminator in match */
48604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen + 1);
48704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
48804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		for (i = 0; vianame[i]; i++) {
489fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			if (vianame[i] == '/' ||
490fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			    vianame[i] == ' ') {
491aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann				fprintf(stderr,
492aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					"Warning: weird character in interface"
493fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt					" `%s' ('/' and ' ' are not allowed by the kernel).\n",
494aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					vianame);
49504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI				break;
49604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			}
49704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		}
49804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	}
49904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
50004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
501cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS
502927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardtstatic void *load_extension(const char *search_path, const char *af_prefix,
50321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt    const char *name, bool is_target)
50421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{
505927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt	const char *all_prefixes[] = {"libxt_", af_prefix, NULL};
506927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt	const char **prefix;
50721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	const char *dir = search_path, *next;
50821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	void *ptr = NULL;
50921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	struct stat sb;
51021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	char path[256];
51121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
51221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	do {
51321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		next = strchr(dir, ':');
51421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (next == NULL)
51521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			next = dir + strlen(dir);
51621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
517927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt		for (prefix = all_prefixes; *prefix != NULL; ++prefix) {
518927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			snprintf(path, sizeof(path), "%.*s/%s%s.so",
519927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			         (unsigned int)(next - dir), dir,
520927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			         *prefix, name);
521927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt
522927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (stat(path, &sb) != 0) {
523927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				if (errno == ENOENT)
524927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt					continue;
525927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				fprintf(stderr, "%s: %s\n", path,
526927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt					strerror(errno));
527927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				return NULL;
528927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			}
529927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (dlopen(path, RTLD_NOW) == NULL) {
530927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				fprintf(stderr, "%s: %s\n", path, dlerror());
531927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				break;
532927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			}
53321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
53421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			if (is_target)
5352338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_target(name, XTF_DONT_LOAD);
53621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			else
5372338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_match(name,
5382338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				      XTF_DONT_LOAD, NULL);
53921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
540927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (ptr != NULL)
541927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				return ptr;
54221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
543927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			fprintf(stderr, "%s: no \"%s\" extension found for "
544927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				"this protocol\n", path, name);
545927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			errno = ENOENT;
546927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			return NULL;
547927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt		}
54821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		dir = next + 1;
54921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	} while (*next != '\0');
55021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
55121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	return NULL;
55221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt}
553cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif
55421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
5552338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_match *
5562338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_match(const char *name, enum xtables_tryload tryload,
5572338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		   struct xtables_rule_match **matches)
5580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
5590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match *ptr;
5600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	const char *icmp6 = "icmp6";
5610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5620cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(name) >= XT_EXTENSION_MAXNAMELEN)
56321d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt		xtables_error(PARAMETER_PROBLEM,
56421d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt			   "Invalid match name \"%s\" (%u chars max)",
5650cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt			   name, XT_EXTENSION_MAXNAMELEN - 1);
56621d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt
5670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* This is ugly as hell. Nonetheless, there is no way of changing
5680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	 * this without hurting backwards compatibility */
5690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if ( (strcmp(name,"icmpv6") == 0) ||
5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"ipv6-icmp") == 0) ||
5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"icmp6") == 0) )
5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = icmp6;
5730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_matches; ptr; ptr = ptr->next) {
5750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0) {
5760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			struct xtables_match *clone;
5770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* First match of this type: */
5790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (ptr->m == NULL)
5800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				break;
5810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Second and subsequent clones */
583630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt			clone = xtables_malloc(sizeof(struct xtables_match));
5840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			memcpy(clone, ptr, sizeof(struct xtables_match));
5850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->mflags = 0;
5860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* This is a clone: */
5870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->next = clone;
5880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = clone;
5900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
5910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
5920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
5952338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
59677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
59739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, false);
598170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
5992338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
6008b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
6010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load match `%s':%s\n",
602927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				   name, strerror(errno));
6030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
6050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
6062338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
6070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6112338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) {
6128b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
6130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find match `%s'\n", name);
6140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
6160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && matches) {
6180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match **i;
6190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match *newentry;
6200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
621630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		newentry = xtables_malloc(sizeof(struct xtables_rule_match));
6220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = matches; *i; i = &(*i)->next) {
6240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (strcmp(name, (*i)->match->name) == 0)
6252338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				(*i)->completed = true;
6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->match = ptr;
6282338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		newentry->completed = false;
6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->next = NULL;
6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = newentry;
6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
6340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
6350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6362338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_target *
6372338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_target(const char *name, enum xtables_tryload tryload)
6380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *ptr;
6400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Standard target? */
6420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(name, "") == 0
6430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_ACCEPT) == 0
6440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_DROP) == 0
6450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_QUEUE) == 0
6460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_RETURN) == 0)
6470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = "standard";
6480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_targets; ptr; ptr = ptr->next) {
6500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0)
6510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
6520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
6552338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
65677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
65739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, true);
658170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
6592338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
6608b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
6610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load target `%s':%s\n",
662927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				   name, strerror(errno));
6630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
6650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
6662338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
6670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
6680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
6690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
6700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
671854d2d9bd7556cfd8a676b0bc18dc059a9a2dd25Peter Volkov	if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) {
6728b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
6730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find target `%s'\n", name);
6740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
6760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr)
6780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		ptr->used = 1;
6790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
6810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
6820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6837ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_revision(const char *name, uint8_t revision, int opt)
6840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
6850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xt_get_revision rev;
6860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	socklen_t s = sizeof(rev);
6870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	int max_rev, sockfd;
6880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
68977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);
6900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (sockfd < 0) {
691df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		if (errno == EPERM) {
692df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			/* revision 0 is always supported. */
693df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			if (revision != 0)
694df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy				fprintf(stderr, "Could not determine whether "
695df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"revision %u is supported, "
696df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"assuming it is.\n",
697df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy					revision);
698df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			return 1;
699df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		}
7000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "Could not open socket to kernel: %s\n",
7010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			strerror(errno));
7020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
705a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) {
706a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		fprintf(stderr, "Could not set close on exec: %s\n",
707a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski			strerror(errno));
708a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		exit(1);
709a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	}
710a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski
711c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	xtables_load_ko(xtables_modprobe_program, true);
7120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	strcpy(rev.name, name);
7140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	rev.revision = revision;
7150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
71677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s);
7170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (max_rev < 0) {
7180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Definitely don't support this? */
7190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (errno == ENOENT || errno == EPROTONOSUPPORT) {
7200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
7210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return 0;
7220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else if (errno == ENOPROTOOPT) {
7230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
7240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Assume only revision 0 support (old kernel) */
7250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return (revision == 0);
7260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else {
7270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr, "getsockopt failed strangely: %s\n",
7280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				strerror(errno));
7290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
7300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
7310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	close(sockfd);
7330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return 1;
7340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7377ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_match_revision(const char *name, uint8_t revision)
7380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
73977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_match);
7400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7427ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_target_revision(const char *name, uint8_t revision)
7430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
74477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_target);
7450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
747dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardtstatic void xtables_check_options(const char *name, const struct option *opt)
748dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt{
749dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	for (; opt->name != NULL; ++opt)
750dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) {
751dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			fprintf(stderr, "%s: Extension %s uses invalid "
752dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			        "option value %d\n",xt_params->program_name,
753dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			        name, opt->val);
754dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			exit(1);
755dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		}
756dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt}
757dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
7580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me)
7590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
7600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match **i, *old;
7610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
762c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
763c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: match %s<%u> is missing a version\n",
764c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
765c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
766c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
767dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
768dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
769dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
7705dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
771dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
7720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7750cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
776281439ba6b96b729ef1400a49ec53eda298bb9f8Li Yewang		fprintf(stderr, "%s: match `%s' has invalid name\n",
7775dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
7780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
7820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
7830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: match %s has invalid protocol family\n",
7845dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
7850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
788dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	if (me->extra_opts != NULL)
789dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		xtables_check_options(me->name, me->extra_opts);
790dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
7910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested match */
79277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
7930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
7940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7952338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
7960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
79723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision &&
79823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		    old->family == me->family) {
7990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
8000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: match `%s' already registered.\n",
8015dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
8020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
8030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
8040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
8060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_match_revision(old->name, old->revision)
8070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
8080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
81023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new match can be used. */
8110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_match_revision(me->name, me->revision))
8120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
81423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
81523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision && me->family == AF_UNSPEC)
81623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt			return;
81723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt
8180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
8190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
8200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
8210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
8240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
8255dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
8265dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
8270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Append to list. */
8310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (i = &xtables_matches; *i; i = &(*i)->next);
8320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = NULL;
8330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	*i = me;
8340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->m = NULL;
8360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->mflags = 0;
8370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
8380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8399a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_matches(struct xtables_match *match, unsigned int n)
8409a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
8419a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
8429a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_match(&match[--n]);
8439a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
8449a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
8459a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
8460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me)
8470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
8480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *old;
8490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
850c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
851c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
852c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
853c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
854c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
855dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
856dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
857dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
8585dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
859dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
8600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8630cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
8640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
8655dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
8700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
8710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: target %s has invalid protocol family\n",
8725dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
876dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	if (me->extra_opts != NULL)
877dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		xtables_check_options(me->name, me->extra_opts);
878dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
8790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested target */
88077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
8810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
8820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8832338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_target(me->name, XTF_DURING_LOAD);
8840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
8850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_target **i;
8860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
88723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision &&
88823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		    old->family == me->family) {
8890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
8900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: target `%s' already registered.\n",
8915dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
8920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
8930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
8940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
8960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_target_revision(old->name, old->revision)
8970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
8980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
90023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new target can be used. */
9010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_target_revision(me->name, me->revision))
9020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
9030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
90423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
90523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision && me->family == AF_UNSPEC)
90623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt			return;
90723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt
9080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
9090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
9100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
9110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
9140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
9155dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
9165dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
9170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Prepend to list. */
9210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = xtables_targets;
9220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	xtables_targets = me;
9230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->t = NULL;
9240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->tflags = 0;
9250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
926aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
9279a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_targets(struct xtables_target *target, unsigned int n)
9289a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
9299a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
9309a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_target(&target[--n]);
9319a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
9329a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
9339a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
934a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt/**
935a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * xtables_param_act - act on condition
936a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @status:	a constant from enum xtables_exittype
937a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
938a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONLY_ONCE: print error message that option may only be used once.
939a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name (e.g. "mark")
940a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2(...):	option in conflict (e.g. "--mark")
941a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3(...):	condition to match on (see extensions/ for examples)
942a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
943a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_NO_INVERT: option does not support inversion
944a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
945a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option in conflict
946a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		condition to match on
947a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
948a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_BAD_VALUE: bad value for option
949a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
950a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option with which the problem occured (e.g. "--mark")
951a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		string the user passed in (e.g. "99999999999999")
952a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
953a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONE_ACTION: two mutually exclusive actions have been specified
954a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
955a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
956a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * Displays an error message and exits the program.
957a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt */
958a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardtvoid xtables_param_act(unsigned int status, const char *p1, ...)
959aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{
960aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	const char *p2, *p3;
961aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_list args;
962aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	bool b;
963aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
964aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_start(args, p1);
965aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
966aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	switch (status) {
967a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONLY_ONCE:
968aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
969aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
970aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
971aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9728b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
973aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option may only be specified once",
974aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2);
975aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
976a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_NO_INVERT:
977aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
978aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
979aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
980aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9818b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
982aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option cannot be inverted", p1, p2);
983aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
984a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_BAD_VALUE:
985aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
986aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p3 = va_arg(args, const char *);
9878b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
988aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: Bad value for \"%s\" option: \"%s\"",
989aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2, p3);
990aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
991a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONE_ACTION:
992aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b = va_arg(args, unsigned int);
993aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
994aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9958b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
996aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: At most one action is possible", p1);
997aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
998aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	default:
9998b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(status, p1, args);
1000aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1001aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	}
1002aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
1003aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_end(args);
1004aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt}
100508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1006e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp)
100708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
100808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[20];
100908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const unsigned char *bytep = (const void *)&addrp->s_addr;
101008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
101108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
101208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
101308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
101408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
101508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr)
101608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
101708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct hostent *host;
101808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
101908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET);
102008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (host == NULL)
102108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
102208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
102308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return host->h_name;
102408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
102508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
102608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr)
102708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
102808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct netent *net;
102908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
103008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL)
103108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return net->n_name;
103208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
103308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return NULL;
103408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
103508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1036e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr)
103708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
103808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
103908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
104008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ipaddr_to_host(addr)) != NULL ||
104108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	    (name = ipaddr_to_network(addr)) != NULL)
104208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
104308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1044e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ipaddr_to_numeric(addr);
104508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
104608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1047e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipmask_to_numeric(const struct in_addr *mask)
104808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
104908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[20];
105008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t maskaddr, bits;
105108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int i;
105208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
105308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	maskaddr = ntohl(mask->s_addr);
105408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
105508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (maskaddr == 0xFFFFFFFFL)
105608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		/* we don't want to see "/32" */
105708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return "";
105808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
105908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	i = 32;
106008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	bits = 0xFFFFFFFEL;
106108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (--i >= 0 && maskaddr != bits)
106208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		bits <<= 1;
106308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (i >= 0)
106408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		sprintf(buf, "/%d", i);
106508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	else
106608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		/* mask was not a decent combination of 1's and 0's */
1067e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
106808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
106908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
107008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
107108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1072bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask)
1073bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1074bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1075bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned char *addrp;
1076bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int onebyte;
1077bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[20], *p, *q;
1078bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int i;
1079bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1080bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* copy dotted string, because we need to modify it */
1081bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, dotted, sizeof(buf) - 1);
1082bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1083bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = (void *)&addr.s_addr;
1084bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1085bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	p = buf;
1086bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0; i < 3; ++i) {
1087bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if ((q = strchr(p, '.')) == NULL) {
1088bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (is_mask)
1089bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1090bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1091bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			/* autocomplete, this is a network address */
10925f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt			if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1093bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1094bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1095bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			addrp[i] = onebyte;
1096bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			while (i < 3)
1097bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				addrp[++i] = 0;
1098bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1099bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return &addr;
1100bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		}
1101bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1102bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*q = '\0';
11035f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt		if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1104bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1105bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1106bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[i] = onebyte;
1107bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p = q + 1;
1108bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1109bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1110bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* we have checked 3 bytes, now we check the last one */
11115f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1112bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1113bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1114bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp[3] = onebyte;
1115bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &addr;
1116bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1117bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11181e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted)
1119bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1120bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, false);
1121bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1122bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11231e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipmask(const char *dotted)
1124bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1125bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, true);
1126bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1127bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1128bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name)
1129bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1130bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1131bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct netent *net;
1132bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1133bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((net = getnetbyname(name)) != NULL) {
1134bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (net->n_addrtype != AF_INET)
1135bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1136bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addr.s_addr = htonl(net->n_net);
1137bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &addr;
1138bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1139bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1140bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1141bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1142bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1143bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
1144bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1145bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct hostent *host;
1146bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addr;
1147bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i;
1148bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1149bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1150bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((host = gethostbyname(name)) != NULL) {
1151bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (host->h_addrtype != AF_INET ||
1152bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		    host->h_length != sizeof(struct in_addr))
1153bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1154bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1155bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		while (host->h_addr_list[*naddr] != NULL)
1156bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			++*naddr;
115711e250ba02349cb1e34058673db3d0b54eb56c44Wes Campaigne		addr = xtables_calloc(*naddr, sizeof(struct in_addr));
1158bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (i = 0; i < *naddr; i++)
1159bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			memcpy(&addr[i], host->h_addr_list[i],
1160bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			       sizeof(struct in_addr));
1161bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1162bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1163bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1164bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1165bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1166bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1167bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *
1168bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs)
1169bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1170bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrptmp, *addrp;
1171bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11721e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL ||
1173bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ipaddr(name)) != NULL) {
1174630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in_addr));
1175bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1176bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1177bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1178bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1179bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL)
1180bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrptmp;
1181bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11828b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1183bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1184bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1185bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask)
1186bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1187bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr maskaddr;
1188bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1189bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1190bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1191bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1192bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 32 bits */
1193bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = 0xFFFFFFFF;
1194bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1195bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
11961e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL)
1197bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* dotted_to_addr already returns a network byte order addr */
1198bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
11995f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 32))
12008b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1201bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1202bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1203bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
1204bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1205bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1206bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1207bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	maskaddr.s_addr = 0U;
1208bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1209bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1210bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1211332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
1212332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow                              struct in_addr **maskpp, unsigned int *naddrs)
1213332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
1214332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in_addr *addrp;
1215332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	char buf[256], *p;
1216332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1217332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1218332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1219332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1220332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1221332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1222332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1223332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1224332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
1225332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
1226332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1227332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1228332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1229332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count; ++i) {
1230332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (loop == NULL)
1231332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1232332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == ',')
1233332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			++loop;
1234332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == '\0')
1235332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1236332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		p = strchr(loop, ',');
1237332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (p != NULL)
1238332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = p - loop;
1239332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1240332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1241332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (len == 0 || sizeof(buf) - 1 < len)
1242332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1243332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1244332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1245332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1246332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		loop += len;
1247332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1248332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1249332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(p + 1);
1250332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1251332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(NULL);
1252332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1253332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1254332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1255332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
1256332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((*maskpp + i)->s_addr == 0)
1257332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			/*
1258332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * A bit pointless to process multiple addresses
1259332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * in this case...
1260332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 */
1261332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "0.0.0.0");
1262332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1263332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ipparse_hostnetwork(buf, &n);
1264332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1265332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1266332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1267332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1268332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1269332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1270332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1271332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1272332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1273332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1274332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1275332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1276332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1277332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1278332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1279332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1280332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1281332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1282332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ipparse_hostnetwork had allocated: */
1283332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1284332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1285332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
12864b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt	for (i = 0; i < count; ++i)
1287332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
1288332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1289332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1290332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1291a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt/**
1292a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * xtables_ipparse_any - transform arbitrary name to in_addr
1293a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt *
1294a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * Possible inputs (pseudo regex):
1295a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * 	m{^($hostname|$networkname|$ipaddr)(/$mask)?}
1296a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname"
1297a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt */
1298a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp,
1299a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                         struct in_addr *maskp, unsigned int *naddrs)
1300bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1301bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1302bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1303bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1304bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1305bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1306bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1307bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1308bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1309bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(p + 1);
1310bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1311bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(NULL);
1312bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1313bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1314bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1315bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
1316bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (maskp->s_addr == 0U)
1317bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "0.0.0.0");
1318bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1319bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ipparse_hostnetwork(buf, naddrs);
1320bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1321bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1322bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[j++].s_addr &= maskp->s_addr;
1323bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1324bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (addrp[k].s_addr == addrp[j-1].s_addr) {
1325adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				/*
1326adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * Nuke the dup by copying an address from the
1327adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * tail here, and check the current position
1328adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * again (--j).
1329adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 */
1330adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				memcpy(&addrp[--j], &addrp[--*naddrs],
1331adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				       sizeof(struct in_addr));
1332bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1333bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1334bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1335bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1336bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1337e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp)
133808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
1339cf3e52d00b7d3fedf98ef7710c337c441270d936Maciej Zenczykowski	/* 0000:0000:0000:0000:0000:0000:000.000.000.000
134008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	 * 0000:0000:0000:0000:0000:0000:0000:0000 */
134108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+1];
134208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
134308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
134408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
134508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr)
134608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
134708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char hostname[NI_MAXHOST];
134808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct sockaddr_in6 saddr;
134908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int err;
135008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
135108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memset(&saddr, 0, sizeof(struct sockaddr_in6));
135208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memcpy(&saddr.sin6_addr, addr, sizeof(*addr));
135308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	saddr.sin6_family = AF_INET6;
135408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
135508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6),
135608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	      hostname, sizeof(hostname) - 1, NULL, 0, 0);
135708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (err != 0) {
135808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
135908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		fprintf(stderr,"IP2Name: %s\n",gai_strerror(err));
136008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
136108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
136208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
136308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
136408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
136508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	fprintf (stderr, "\naddr2host: %s\n", hostname);
136608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
136708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return hostname;
136808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
136908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1370e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr)
137108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
137208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
137308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
137408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ip6addr_to_host(addr)) != NULL)
137508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
137608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1377e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ip6addr_to_numeric(addr);
137808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
137908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
138008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic int ip6addr_prefix_length(const struct in6_addr *k)
138108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
138208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	unsigned int bits = 0;
138308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t a, b, c, d;
138408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
138548607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	a = ntohl(k->s6_addr32[0]);
138648607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	b = ntohl(k->s6_addr32[1]);
138748607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	c = ntohl(k->s6_addr32[2]);
138848607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	d = ntohl(k->s6_addr32[3]);
138908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (a & 0x80000000U) {
139008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		++bits;
139108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a <<= 1;
139208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a  |= (b >> 31) & 1;
139308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b <<= 1;
139408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b  |= (c >> 31) & 1;
139508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c <<= 1;
139608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c  |= (d >> 31) & 1;
139708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		d <<= 1;
139808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
139908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (a != 0 || b != 0 || c != 0 || d != 0)
140008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return -1;
140108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return bits;
140208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
140308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1404e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
140508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
140608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+2];
140708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int l = ip6addr_prefix_length(addrp);
140808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
140908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (l == -1) {
141008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		strcpy(buf, "/");
1411e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		strcat(buf, xtables_ip6addr_to_numeric(addrp));
141208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return buf;
141308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
141408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "/%d", l);
141508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
141608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
1417bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
14181e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in6_addr *xtables_numeric_to_ip6addr(const char *num)
1419bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1420bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr ap;
1421bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
1422bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1423bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
1424bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &ap;
1425bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1426bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	fprintf(stderr, "\nnumeric2addr: %d\n", err);
1427bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1428bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1429bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1430bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1431bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1432bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr)
1433bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
14342ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	struct in6_addr *addr;
1435bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct addrinfo hints;
14362ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	struct addrinfo *res, *p;
1437bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
14382ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	unsigned int i;
1439bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1440bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&hints, 0, sizeof(hints));
1441bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_flags    = AI_CANONNAME;
1442bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_family   = AF_INET6;
1443bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_socktype = SOCK_RAW;
1444bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1445bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1446bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
1447bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1448bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr,"Name2IP: %s\n",gai_strerror(err));
1449bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1450bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1451bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
14522ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		/* Find length of address chain */
14532ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		for (p = res; p != NULL; p = p->ai_next)
14542ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			++*naddr;
1455bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1456bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr, "resolved: len=%d  %s ", res->ai_addrlen,
145730290aea009cf3fd76f27336fb4370be3467c4daPatrick McHardy		        xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr));
1458bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
14592ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		/* Copy each element of the address chain */
14602ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		addr = xtables_calloc(*naddr, sizeof(struct in6_addr));
14612ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		for (i = 0, p = res; p != NULL; p = p->ai_next)
14622ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			memcpy(&addr[i++],
14632ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			       &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr,
14642ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			       sizeof(struct in6_addr));
1465bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		freeaddrinfo(res);
1466bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1467bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1468bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1469bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1470bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1471bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1472bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name)
1473bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1474bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/*	abort();*/
1475bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* TODO: not implemented yet, but the exception breaks the
1476bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	 *       name resolvation */
1477bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1478bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1479bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1480bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1481bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs)
1482bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1483bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp, *addrptmp;
1484bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
14851e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL ||
1486bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ip6addr(name)) != NULL) {
1487630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in6_addr));
1488bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1489bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1490bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1491bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1492bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrp = host_to_ip6addr(name, naddrs)) != NULL)
1493bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1494bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
14958b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1496bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1497bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1498bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask)
1499bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1500bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr maskaddr;
1501bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1502bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1503bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1504bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1505bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 128 bits */
1506bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(&maskaddr, 0xff, sizeof maskaddr);
1507bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1508bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
15091e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL)
1510bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
15115f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
15128b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1513bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1514bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1515bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		char *p = (void *)&maskaddr;
1516bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p, 0xff, bits / 8);
1517bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
1518bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p[bits/8] = 0xff << (8 - (bits & 7));
1519bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1520bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1521bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1522bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&maskaddr, 0, sizeof(maskaddr));
1523bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1524bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1525bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1526332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid
1527332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowxtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
1528332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		      struct in6_addr **maskpp, unsigned int *naddrs)
1529332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
153058df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel	static const struct in6_addr zero_addr;
1531332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in6_addr *addrp;
1532332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	char buf[256], *p;
1533332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1534332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1535332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1536332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1537332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1538332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1539332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1540332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1541332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
1542332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
1543332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1544332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1545332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1546332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count /*NB: count can grow*/; ++i) {
1547332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (loop == NULL)
1548332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1549332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == ',')
1550332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			++loop;
1551332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == '\0')
1552332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1553332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		p = strchr(loop, ',');
1554332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (p != NULL)
1555332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = p - loop;
1556332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1557332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1558332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (len == 0 || sizeof(buf) - 1 < len)
1559332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1560332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1561332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1562332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1563332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		loop += len;
1564332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1565332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1566332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(p + 1);
1567332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1568332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(NULL);
1569332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1570332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1571332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1572332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
157358df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel		if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0)
1574332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "::");
1575332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1576332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ip6parse_hostnetwork(buf, &n);
1577332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1578332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1579332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1580332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1581332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1582332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1583332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1584332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1585332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1586332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1587332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1588332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1589332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1590332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1591332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1592332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1593332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1594332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1595332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ip6parse_hostnetwork had allocated: */
1596332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1597332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1598332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
15994b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt	for (i = 0; i < count; ++i)
1600332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		for (j = 0; j < 4; ++j)
1601332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
1602332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1603332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1604a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
1605a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                          struct in6_addr *maskp, unsigned int *naddrs)
1606bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
16079c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	static const struct in6_addr zero_addr;
1608bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1609bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1610bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1611bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1612bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1613bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf)-1] = '\0';
1614bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1615bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1616bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(p + 1);
1617bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1618bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(NULL);
1619bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1620bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1621bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1622bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
16239c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0)
1624bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "::");
1625bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1626bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs);
1627bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1628bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1629bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < 4; ++k)
16305a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai			addrp[j].s6_addr32[k] &= maskp->s6_addr32[k];
1631bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		++j;
1632bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1633bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
1634adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				/*
1635adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * Nuke the dup by copying an address from the
1636adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * tail here, and check the current position
1637adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * again (--j).
1638adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 */
1639adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				memcpy(&addrp[--j], &addrp[--*naddrs],
1640adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				       sizeof(struct in_addr));
1641bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1642bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1643bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1644bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1645a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1646a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_save_string(const char *value)
1647a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{
1648a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char no_quote_chars[] = "_-0123456789"
1649a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"abcdefghijklmnopqrstuvwxyz"
1650a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1651a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char escape_chars[] = "\"\\'";
1652a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	size_t length;
1653a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	const char *p;
1654a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
165587dc7c4c842deb1e2e3d38089ffcad9f238d98deMax Kellerman	length = strspn(value, no_quote_chars);
1656a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	if (length > 0 && value[length] == 0) {
1657a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* no quoting required */
1658a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		putchar(' ');
165973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		fputs(value, stdout);
1660a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	} else {
1661a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* there is at least one dangerous character in the
1662a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   value, which we have to quote.  Write double quotes
1663a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   around the value and escape special characters with
1664a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   a backslash */
166573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" \"");
1666a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1667a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		for (p = strpbrk(value, escape_chars); p != NULL;
1668a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		     p = strpbrk(value, escape_chars)) {
1669a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			if (p > value)
1670a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann				fwrite(value, 1, p - value, stdout);
1671a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar('\\');
1672a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar(*p);
1673a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			value = p + 1;
1674a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		}
1675a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1676a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* print the rest and finish the double quoted
1677a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   string */
1678a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		fputs(value, stdout);
167973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		putchar('\"');
1680a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	}
1681a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann}
16820f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16830f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt/**
16840f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Check for option-intrapositional negation.
16850f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Do not use in new code.
16860f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt */
16870f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardtint xtables_check_inverse(const char option[], int *invert,
1688bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt			  int *my_optind, int argc, char **argv)
16890f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt{
16902be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (option == NULL || strcmp(option, "!") != 0)
16912be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		return false;
16920f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16932be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	fprintf(stderr, "Using intrapositioned negation "
16942be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	        "(`--option ! this`) is deprecated in favor of "
16952be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	        "extrapositioned (`! --option this`).\n");
16960f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16972be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (*invert)
16982be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
16992be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt			   "Multiple `!' flags not allowed");
17002be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	*invert = true;
17012be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (my_optind != NULL) {
1702bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt		optarg = argv[*my_optind];
17032be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		++*my_optind;
17042be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		if (argc && *my_optind > argc)
17052be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
17062be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt				   "no argument following `!'");
17070f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt	}
17082be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt
17092be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	return true;
17100f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt}
17111de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17121de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtconst struct xtables_pprot xtables_chain_protos[] = {
17131de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"tcp",       IPPROTO_TCP},
17141de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"sctp",      IPPROTO_SCTP},
17151de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udp",       IPPROTO_UDP},
17161de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udplite",   IPPROTO_UDPLITE},
17171de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmp",      IPPROTO_ICMP},
17181de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmpv6",    IPPROTO_ICMPV6},
17191de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-icmp", IPPROTO_ICMPV6},
17201de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"esp",       IPPROTO_ESP},
17211de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ah",        IPPROTO_AH},
17221de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-mh",   IPPROTO_MH},
17231de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"mh",        IPPROTO_MH},
17241de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"all",       0},
17251de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{NULL},
17261de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt};
17271de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17287ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t
17291de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtxtables_parse_protocol(const char *s)
17301de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt{
17311de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	unsigned int proto;
17321de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17331de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) {
17341de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		struct protoent *pent;
17351de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17361de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		/* first deal with the special case of 'all' to prevent
17371de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * people from being able to redefine 'all' in nsswitch
17381de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * and/or provoke expensive [not working] ldap/nis/...
17391de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * lookups */
17401de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		if (!strcmp(s, "all"))
17411de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			return 0;
17421de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17431de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		if ((pent = getprotobyname(s)))
17441de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			proto = pent->p_proto;
17451de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		else {
17461de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			unsigned int i;
17471de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
1748e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso				if (xtables_chain_protos[i].name == NULL)
1749e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso					continue;
1750e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso
17511de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt				if (strcmp(s, xtables_chain_protos[i].name) == 0) {
17521de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					proto = xtables_chain_protos[i].num;
17531de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					break;
17541de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt				}
17551de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			}
17561de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			if (i == ARRAY_SIZE(xtables_chain_protos))
17578b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim				xt_params->exit_err(PARAMETER_PROBLEM,
17581de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					   "unknown protocol `%s' specified",
17591de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					   s);
17601de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		}
17611de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	}
17621de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17631de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	return proto;
17641de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt}
1765