xtables.c revision 371cea299f0b2eb100b9fc9fb99089640d2d606f
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>
52c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt
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
768b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim
77139b3fe4bd5121501e60fe07963ea527d7f0bd36Jamal Hadi Salimvoid xtables_free_opts(int reset_offset)
7884c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim{
79139b3fe4bd5121501e60fe07963ea527d7f0bd36Jamal Hadi Salim	if (xt_params->opts != xt_params->orig_opts) {
80139b3fe4bd5121501e60fe07963ea527d7f0bd36Jamal Hadi Salim		free(xt_params->opts);
81139b3fe4bd5121501e60fe07963ea527d7f0bd36Jamal Hadi Salim		xt_params->opts = xt_params->orig_opts;
8284c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim		if (reset_offset)
8384c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim			xt_params->option_offset = 0;
8484c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim	}
8584c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim}
8684c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim
8770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salimstruct option *xtables_merge_options(struct option *oldopts,
8870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim				     const struct option *newopts,
8970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim				     unsigned int *option_offset)
9070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim{
9170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	unsigned int num_old, num_new, i;
9270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	struct option *merge;
9370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
9470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	if (newopts == NULL)
9570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim		return oldopts;
9670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
9770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	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
100bddcb92d1f0f76d21c4469b1667c8199c9fab126Jan Engelhardt	xt_params->option_offset += 256;
10170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	*option_offset = xt_params->option_offset;
10270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
10370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
10470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	if (merge == NULL)
10570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim		return NULL;
10670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	memcpy(merge, oldopts, num_old * sizeof(struct option));
10770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	xtables_free_opts(0);	/* Release any old options merged  */
10870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	for (i = 0; i < num_new; i++) {
10970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim		merge[num_old + i] = newopts[i];
11070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim		merge[num_old + i].val += *option_offset;
11170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	}
11270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	memset(merge + num_old + num_new, 0, sizeof(struct option));
11370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
11470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	return merge;
11570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim}
11670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
117dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt/**
11877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * xtables_afinfo - protocol family dependent information
11977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @kmod:		kernel module basename (e.g. "ip_tables")
12077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @libprefix:		prefix of .so library name (e.g. "libipt_")
12177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @family:		nfproto family
12277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @ipproto:		used by setsockopt (e.g. IPPROTO_IP)
12377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @so_rev_match:	optname to check revision support of match
12477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @so_rev_target:	optname to check revision support of target
12577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt */
12677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstruct xtables_afinfo {
12777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	const char *kmod;
12877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	const char *libprefix;
12977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	uint8_t family;
13077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	uint8_t ipproto;
13177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	int so_rev_match;
13277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	int so_rev_target;
13377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
13477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
13577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv4 = {
13677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.kmod          = "ip_tables",
13777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.libprefix     = "libipt_",
13877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.family	       = NFPROTO_IPV4,
13977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.ipproto       = IPPROTO_IP,
14077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_match  = IPT_SO_GET_REVISION_MATCH,
14177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_target = IPT_SO_GET_REVISION_TARGET,
14277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
14377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
14477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv6 = {
14577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.kmod          = "ip6_tables",
14677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.libprefix     = "libip6t_",
14777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.family        = NFPROTO_IPV6,
14877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.ipproto       = IPPROTO_IPV6,
14977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_match  = IP6T_SO_GET_REVISION_MATCH,
15077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_target = IP6T_SO_GET_REVISION_TARGET,
15177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
15277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
15377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo *afinfo;
15477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
15539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt/* Search path for Xtables .so files */
15639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtstatic const char *xtables_libdir;
1570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */
159c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtconst char *xtables_modprobe_program;
1600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI/* Keeping track of external matches and targets: linked lists.  */
1620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches;
1630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets;
1640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
16539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtvoid xtables_init(void)
16639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt{
16739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = getenv("XTABLES_LIBDIR");
16839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	if (xtables_libdir != NULL)
16939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		return;
17039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = getenv("IPTABLES_LIB_DIR");
17139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	if (xtables_libdir != NULL) {
17239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, "
17339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		        "use XTABLES_LIBDIR.\n");
17439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		return;
17539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	}
176ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	/*
177ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * Well yes, IP6TABLES_LIB_DIR is of lower priority over
178ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok
179ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * for these env vars are deprecated anyhow, and in light of the
180ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * (shared) libxt_*.so files, makes less sense to have
181ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR.
182ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 */
183ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	xtables_libdir = getenv("IP6TABLES_LIB_DIR");
184ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	if (xtables_libdir != NULL) {
185ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, "
186ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		        "use XTABLES_LIBDIR.\n");
187ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		return;
188ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	}
18939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = XTABLES_LIBDIR;
19039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt}
19139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt
19277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtvoid xtables_set_nfproto(uint8_t nfproto)
19377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt{
19477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	switch (nfproto) {
19577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	case NFPROTO_IPV4:
19677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		afinfo = &afinfo_ipv4;
19777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		break;
19877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	case NFPROTO_IPV6:
19977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		afinfo = &afinfo_ipv6;
20077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		break;
20177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	default:
20277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n",
20377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		        __func__);
20477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	}
20577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}
20677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
207630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt/**
2087e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * xtables_set_params - set the global parameters used by xtables
2097e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp:	input xtables_globals structure
2107e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim *
2117e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * The app is expected to pass a valid xtables_globals data-filled
2127e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * with proper values
2137e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp cannot be NULL
2147e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim *
2157e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * Returns -1 on failure to set and 0 on success
2167e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim */
2177e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_set_params(struct xtables_globals *xtp)
2187e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{
2197e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	if (!xtp) {
2207e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		fprintf(stderr, "%s: Illegal global params\n",__func__);
2217e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		return -1;
2227e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	}
2237e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2247e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xt_params = xtp;
2257e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2267e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	if (!xt_params->exit_err)
2277e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		xt_params->exit_err = basic_exit_err;
2287e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2297e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	return 0;
2307e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim}
2317e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2327e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto)
2337e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{
2347e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xtables_init();
2357e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xtables_set_nfproto(nfproto);
2367e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	return xtables_set_params(xtp);
2377e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim}
2387e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2397e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim/**
240630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt * xtables_*alloc - wrappers that exit on failure
241630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt */
242630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_calloc(size_t count, size_t size)
2433dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
2443dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
2453dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2463dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = calloc(count, size)) == NULL) {
2473dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: calloc failed");
2483dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
2493dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
2503dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2513dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
2523dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
2533dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
254630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_malloc(size_t size)
2553dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
2563dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
2573dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2583dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = malloc(size)) == NULL) {
2593dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: malloc failed");
2603dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
2613dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
2623dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2633dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
2643dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
2650b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
266332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid *xtables_realloc(void *ptr, size_t size)
267332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
268332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	void *p;
269332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
270332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	if ((p = realloc(ptr, size)) == NULL) {
271332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		perror("ip[6]tables: realloc failed");
272332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		exit(1);
273332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
274332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
275332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	return p;
276332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
277332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
2780b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void)
2790b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
2800b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int procfile;
2810b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *ret;
2820b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
2830b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ	1024
2840b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
2850b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (procfile < 0)
2860b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return NULL;
2870b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
288371cea299f0b2eb100b9fc9fb99089640d2d606fJan Engelhardt	ret = malloc(PROCFILE_BUFSIZ);
2890b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (ret) {
2900b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		memset(ret, 0, PROCFILE_BUFSIZ);
2910b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
2920b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case -1: goto fail;
2930b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
2940b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
2950b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (ret[strlen(ret)-1]=='\n')
2960b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			ret[strlen(ret)-1]=0;
2970b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		close(procfile);
2980b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return ret;
2990b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3000b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail:
3010b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(ret);
3020b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	close(procfile);
3030b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return NULL;
3040b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
306c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_insmod(const char *modname, const char *modprobe, bool quiet)
3070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
3080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *buf = NULL;
3090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *argv[4];
3100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int status;
3110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	/* If they don't explicitly set it, read out of kernel */
3130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (!modprobe) {
3140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		buf = get_modprobe();
3150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (!buf)
3160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			return -1;
3170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		modprobe = buf;
3180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
320c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	/*
321c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * Need to flush the buffer, or the child may output it again
322c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * when switching the program thru execv.
323c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 */
324c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	fflush(stdout);
325c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt
32694aa2ea67d7b8a669e8541f094661a1dc89722a3Jan Engelhardt	switch (vfork()) {
3270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case 0:
3280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[0] = (char *)modprobe;
3290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[1] = (char *)modname;
3300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (quiet) {
3310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = "-q";
3320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		} else {
3340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = NULL;
3350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
3370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		execv(argv[0], argv);
3380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		/* not usually reached */
3400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		exit(1);
3410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case -1:
3420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return -1;
3430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	default: /* parent */
3450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		wait(&status);
3460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3470b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(buf);
3490b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
3500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return 0;
3510b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return -1;
3520b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3530b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
354c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_load_ko(const char *modprobe, bool quiet)
3550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
356c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	static bool loaded = false;
3570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	static int ret = -1;
3580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (!loaded) {
36077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ret = xtables_insmod(afinfo->kmod, modprobe, quiet);
3610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		loaded = (ret == 0);
3620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ret;
3650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
3660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3675f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt/**
3685f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * xtables_strtou{i,l} - string to number conversion
3695f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @s:	input string
3705f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @end:	like strtoul's "end" pointer
3715f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @value:	pointer for result
3725f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @min:	minimum accepted value
3735f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @max:	maximum accepted value
3745f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt *
3755f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * If @end is NULL, we assume the caller wants a "strict strtoul", and hence
3765f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * "15a" is rejected.
3775f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * In either case, the value obtained is compared for min-max compliance.
3785f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Base is always 0, i.e. autodetect depending on @s.
379cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *
3805f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Returns true/false whether number was accepted. On failure, *value has
3815f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * undefined contents.
382cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */
3835f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoul(const char *s, char **end, unsigned long *value,
3845f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt                     unsigned long min, unsigned long max)
385cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
386cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	unsigned long v;
387cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	char *my_end;
388cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
389cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	errno = 0;
390cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	v = strtoul(s, &my_end, 0);
391cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
392cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (my_end == s)
393cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return false;
394cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (end != NULL)
395cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*end = my_end;
396cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
397cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (errno != ERANGE && min <= v && (max == 0 || v <= max)) {
398cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (value != NULL)
399cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			*value = v;
400cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (end == NULL)
401cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			return *my_end == '\0';
402cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return true;
403cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	}
404cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
405cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return false;
406cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
407cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4085f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoui(const char *s, char **end, unsigned int *value,
4095f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt                     unsigned int min, unsigned int max)
410cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
411cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	unsigned long v;
412cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	bool ret;
413cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4145f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	ret = xtables_strtoul(s, end, &v, min, max);
415cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (value != NULL)
416cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*value = v;
417cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return ret;
418cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
419cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
420aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtint xtables_service_to_port(const char *name, const char *proto)
42104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
42204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	struct servent *service;
42304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
42404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((service = getservbyname(name, proto)) != NULL)
42504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		return ntohs((unsigned short) service->s_port);
42604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
42704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return -1;
42804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
42904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
430aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtu_int16_t xtables_parse_port(const char *port, const char *proto)
43104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
4327a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt	unsigned int portnum;
43304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4345f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) ||
435aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt	    (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1)
436213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt		return portnum;
43704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4388b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM,
43904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		   "invalid port/service `%s' specified", port);
44004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
44104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
442aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtvoid xtables_parse_interface(const char *arg, char *vianame,
443aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt			     unsigned char *mask)
44404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
445fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	unsigned int vialen = strlen(arg);
44604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned int i;
44704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
44804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(mask, 0, IFNAMSIZ);
44904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(vianame, 0, IFNAMSIZ);
45004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
45104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if (vialen + 1 > IFNAMSIZ)
4528b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
45304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   "interface name `%s' must be shorter than IFNAMSIZ"
45404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   " (%i)", arg, IFNAMSIZ-1);
45504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
45604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	strcpy(vianame, arg);
457fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	if (vialen == 0)
45804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0, IFNAMSIZ);
45904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	else if (vianame[vialen - 1] == '+') {
46004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen - 1);
46104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
46204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Don't remove `+' here! -HW */
46304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	} else {
46404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Include nul-terminator in match */
46504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen + 1);
46604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
46704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		for (i = 0; vianame[i]; i++) {
468fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			if (vianame[i] == '/' ||
469fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			    vianame[i] == ' ') {
470aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann				fprintf(stderr,
471aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					"Warning: weird character in interface"
472fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt					" `%s' ('/' and ' ' are not allowed by the kernel).\n",
473aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					vianame);
47404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI				break;
47504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			}
47604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		}
47704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	}
47804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
47904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
480cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS
48121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardtstatic void *load_extension(const char *search_path, const char *prefix,
48221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt    const char *name, bool is_target)
48321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{
48421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	const char *dir = search_path, *next;
48521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	void *ptr = NULL;
48621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	struct stat sb;
48721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	char path[256];
48821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
48921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	do {
49021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		next = strchr(dir, ':');
49121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (next == NULL)
49221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			next = dir + strlen(dir);
49321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		snprintf(path, sizeof(path), "%.*s/libxt_%s.so",
4942c0a0c9eba1d1ab39dcde54bc822d4788f9531fcJan Engelhardt		         (unsigned int)(next - dir), dir, name);
49521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
49621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (dlopen(path, RTLD_NOW) != NULL) {
49721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			/* Found library.  If it didn't register itself,
49821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			   maybe they specified target as match. */
49921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			if (is_target)
5002338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_target(name, XTF_DONT_LOAD);
50121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			else
5022338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_match(name,
5032338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				      XTF_DONT_LOAD, NULL);
50421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		} else if (stat(path, &sb) == 0) {
50521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			fprintf(stderr, "%s: %s\n", path, dlerror());
50621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		}
50721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
50821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (ptr != NULL)
50921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			return ptr;
51021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
51121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		snprintf(path, sizeof(path), "%.*s/%s%s.so",
5122c0a0c9eba1d1ab39dcde54bc822d4788f9531fcJan Engelhardt		         (unsigned int)(next - dir), dir, prefix, name);
51321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (dlopen(path, RTLD_NOW) != NULL) {
51421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			if (is_target)
5152338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_target(name, XTF_DONT_LOAD);
51621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			else
5172338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_match(name,
5182338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				      XTF_DONT_LOAD, NULL);
51921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		} else if (stat(path, &sb) == 0) {
52021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			fprintf(stderr, "%s: %s\n", path, dlerror());
52121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		}
52221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
52321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (ptr != NULL)
52421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			return ptr;
52521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
52621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		dir = next + 1;
52721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	} while (*next != '\0');
52821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
52921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	return NULL;
53021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt}
531cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif
53221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
5332338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_match *
5342338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_match(const char *name, enum xtables_tryload tryload,
5352338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		   struct xtables_rule_match **matches)
5360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
5370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match *ptr;
5380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	const char *icmp6 = "icmp6";
5390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5400cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(name) >= XT_EXTENSION_MAXNAMELEN)
54121d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt		xtables_error(PARAMETER_PROBLEM,
54221d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt			   "Invalid match name \"%s\" (%u chars max)",
5430cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt			   name, XT_EXTENSION_MAXNAMELEN - 1);
54421d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt
5450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* This is ugly as hell. Nonetheless, there is no way of changing
5460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	 * this without hurting backwards compatibility */
5470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if ( (strcmp(name,"icmpv6") == 0) ||
5480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"ipv6-icmp") == 0) ||
5490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"icmp6") == 0) )
5500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = icmp6;
5510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_matches; ptr; ptr = ptr->next) {
5530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0) {
5540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			struct xtables_match *clone;
5550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* First match of this type: */
5570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (ptr->m == NULL)
5580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				break;
5590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Second and subsequent clones */
561630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt			clone = xtables_malloc(sizeof(struct xtables_match));
5620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			memcpy(clone, ptr, sizeof(struct xtables_match));
5630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->mflags = 0;
5640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* This is a clone: */
5650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->next = clone;
5660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = clone;
5680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
5690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
5732338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
57477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
57539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, false);
576170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
5772338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
5788b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
5790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load match `%s':%s\n",
5800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   name, dlerror());
5810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
5830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
5842338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
5850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
5860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
5870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
5880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5892338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) {
5908b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
5910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find match `%s'\n", name);
5920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
5940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && matches) {
5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match **i;
5970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match *newentry;
5980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
599630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		newentry = xtables_malloc(sizeof(struct xtables_rule_match));
6000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = matches; *i; i = &(*i)->next) {
6020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (strcmp(name, (*i)->match->name) == 0)
6032338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				(*i)->completed = true;
6040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
6050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->match = ptr;
6062338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		newentry->completed = false;
6070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->next = NULL;
6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = newentry;
6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
6120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
6130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6142338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_target *
6152338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_target(const char *name, enum xtables_tryload tryload)
6160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
6170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *ptr;
6180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Standard target? */
6200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(name, "") == 0
6210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_ACCEPT) == 0
6220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_DROP) == 0
6230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_QUEUE) == 0
6240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_RETURN) == 0)
6250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = "standard";
6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_targets; ptr; ptr = ptr->next) {
6280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0)
6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
6332338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
63477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
63539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, true);
636170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
6372338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
6388b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load target `%s':%s\n",
6400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   name, dlerror());
6410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
6430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
6442338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
6450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
6460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
6470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
6480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
649854d2d9bd7556cfd8a676b0bc18dc059a9a2dd25Peter Volkov	if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) {
6508b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
6510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find target `%s'\n", name);
6520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
6540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr)
6560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		ptr->used = 1;
6570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
6590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
6600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_revision(const char *name, u_int8_t revision, int opt)
6620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
6630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xt_get_revision rev;
6640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	socklen_t s = sizeof(rev);
6650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	int max_rev, sockfd;
6660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
66777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);
6680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (sockfd < 0) {
669df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		if (errno == EPERM) {
670df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			/* revision 0 is always supported. */
671df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			if (revision != 0)
672df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy				fprintf(stderr, "Could not determine whether "
673df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"revision %u is supported, "
674df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"assuming it is.\n",
675df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy					revision);
676df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			return 1;
677df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		}
6780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "Could not open socket to kernel: %s\n",
6790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			strerror(errno));
6800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
6810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
683c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	xtables_load_ko(xtables_modprobe_program, true);
6840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	strcpy(rev.name, name);
6860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	rev.revision = revision;
6870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
68877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s);
6890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (max_rev < 0) {
6900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Definitely don't support this? */
6910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (errno == ENOENT || errno == EPROTONOSUPPORT) {
6920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
6930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return 0;
6940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else if (errno == ENOPROTOOPT) {
6950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
6960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Assume only revision 0 support (old kernel) */
6970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return (revision == 0);
6980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else {
6990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr, "getsockopt failed strangely: %s\n",
7000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				strerror(errno));
7010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
7020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
7030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	close(sockfd);
7050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return 1;
7060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_match_revision(const char *name, u_int8_t revision)
7100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
71177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_match);
7120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_target_revision(const char *name, u_int8_t revision)
7150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
71677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_target);
7170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me)
7200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
7210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match **i, *old;
7220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
723c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
724c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: match %s<%u> is missing a version\n",
725c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
726c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
727c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
728dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
729dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
730dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
7315dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
732dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
7330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7360cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
7370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
7385dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
7390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
7430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
7440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: match %s has invalid protocol family\n",
7455dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
7460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested match */
75077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
7510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
7520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7532338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
7540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
75523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision &&
75623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		    old->family == me->family) {
7570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
7580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: match `%s' already registered.\n",
7595dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
7600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
7610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
7620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
7640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_match_revision(old->name, old->revision)
7650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
7660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
7670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
76823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new match can be used. */
7690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_match_revision(me->name, me->revision))
7700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
7710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
77223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
77323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision && me->family == AF_UNSPEC)
77423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt			return;
77523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt
7760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
7770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
7780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
7790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
7820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
7835dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
7845dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
7850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Append to list. */
7890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (i = &xtables_matches; *i; i = &(*i)->next);
7900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = NULL;
7910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	*i = me;
7920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->m = NULL;
7940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->mflags = 0;
7950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7979a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_matches(struct xtables_match *match, unsigned int n)
7989a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
7999a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
8009a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_match(&match[--n]);
8019a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
8029a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
8039a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
8040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me)
8050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
8060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *old;
8070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
808c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
809c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
810c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
811c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
812c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
813dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
814dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
815dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
8165dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
817dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
8180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8210cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
8220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
8235dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
8280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
8290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: target %s has invalid protocol family\n",
8305dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested target */
83577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
8360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
8370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8382338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_target(me->name, XTF_DURING_LOAD);
8390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
8400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_target **i;
8410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
84223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision &&
84323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		    old->family == me->family) {
8440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
8450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: target `%s' already registered.\n",
8465dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
8470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
8480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
8490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
8510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_target_revision(old->name, old->revision)
8520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
8530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
85523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new target can be used. */
8560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_target_revision(me->name, me->revision))
8570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
85923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
86023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision && me->family == AF_UNSPEC)
86123545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt			return;
86223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt
8630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
8640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
8650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
8660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
8690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
8705dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
8715dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
8720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Prepend to list. */
8760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = xtables_targets;
8770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	xtables_targets = me;
8780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->t = NULL;
8790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->tflags = 0;
8800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
881aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
8829a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_targets(struct xtables_target *target, unsigned int n)
8839a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
8849a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
8859a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_target(&target[--n]);
8869a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
8879a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
8889a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
889a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt/**
890a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * xtables_param_act - act on condition
891a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @status:	a constant from enum xtables_exittype
892a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
893a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONLY_ONCE: print error message that option may only be used once.
894a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name (e.g. "mark")
895a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2(...):	option in conflict (e.g. "--mark")
896a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3(...):	condition to match on (see extensions/ for examples)
897a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
898a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_NO_INVERT: option does not support inversion
899a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
900a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option in conflict
901a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		condition to match on
902a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
903a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_BAD_VALUE: bad value for option
904a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
905a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option with which the problem occured (e.g. "--mark")
906a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		string the user passed in (e.g. "99999999999999")
907a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
908a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONE_ACTION: two mutually exclusive actions have been specified
909a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
910a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
911a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * Displays an error message and exits the program.
912a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt */
913a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardtvoid xtables_param_act(unsigned int status, const char *p1, ...)
914aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{
915aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	const char *p2, *p3;
916aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_list args;
917aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	bool b;
918aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
919aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_start(args, p1);
920aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
921aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	switch (status) {
922a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONLY_ONCE:
923aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
924aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
925aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
926aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9278b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
928aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option may only be specified once",
929aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2);
930aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
931a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_NO_INVERT:
932aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
933aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
934aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
935aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9368b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
937aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option cannot be inverted", p1, p2);
938aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
939a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_BAD_VALUE:
940aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
941aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p3 = va_arg(args, const char *);
9428b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
943aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: Bad value for \"%s\" option: \"%s\"",
944aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2, p3);
945aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
946a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONE_ACTION:
947aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b = va_arg(args, unsigned int);
948aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		if (!b)
949aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
9508b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
951aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: At most one action is possible", p1);
952aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
953aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	default:
9548b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(status, p1, args);
955aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
956aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	}
957aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
958aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_end(args);
959aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt}
96008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
961e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp)
96208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
96308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[20];
96408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const unsigned char *bytep = (const void *)&addrp->s_addr;
96508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
96608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
96708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
96808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
96908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
97008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr)
97108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
97208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct hostent *host;
97308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
97408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET);
97508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (host == NULL)
97608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
97708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
97808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return host->h_name;
97908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
98008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
98108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr)
98208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
98308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct netent *net;
98408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
98508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL)
98608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return net->n_name;
98708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
98808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return NULL;
98908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
99008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
991e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr)
99208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
99308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
99408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
99508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ipaddr_to_host(addr)) != NULL ||
99608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	    (name = ipaddr_to_network(addr)) != NULL)
99708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
99808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
999e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ipaddr_to_numeric(addr);
100008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
100108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1002e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipmask_to_numeric(const struct in_addr *mask)
100308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
100408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[20];
100508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t maskaddr, bits;
100608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int i;
100708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
100808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	maskaddr = ntohl(mask->s_addr);
100908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
101008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (maskaddr == 0xFFFFFFFFL)
101108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		/* we don't want to see "/32" */
101208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return "";
101308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
101408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	i = 32;
101508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	bits = 0xFFFFFFFEL;
101608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (--i >= 0 && maskaddr != bits)
101708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		bits <<= 1;
101808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (i >= 0)
101908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		sprintf(buf, "/%d", i);
102008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	else
102108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		/* mask was not a decent combination of 1's and 0's */
1022e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
102308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
102408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
102508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
102608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1027bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask)
1028bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1029bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1030bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned char *addrp;
1031bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int onebyte;
1032bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[20], *p, *q;
1033bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int i;
1034bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1035bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* copy dotted string, because we need to modify it */
1036bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, dotted, sizeof(buf) - 1);
1037bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1038bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = (void *)&addr.s_addr;
1039bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1040bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	p = buf;
1041bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0; i < 3; ++i) {
1042bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if ((q = strchr(p, '.')) == NULL) {
1043bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (is_mask)
1044bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1045bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1046bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			/* autocomplete, this is a network address */
10475f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt			if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1048bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1049bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1050bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			addrp[i] = onebyte;
1051bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			while (i < 3)
1052bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				addrp[++i] = 0;
1053bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1054bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return &addr;
1055bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		}
1056bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1057bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*q = '\0';
10585f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt		if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1059bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1060bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1061bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[i] = onebyte;
1062bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p = q + 1;
1063bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1064bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1065bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* we have checked 3 bytes, now we check the last one */
10665f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1067bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1068bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1069bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp[3] = onebyte;
1070bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &addr;
1071bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1072bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
10731e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted)
1074bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1075bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, false);
1076bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1077bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
10781e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipmask(const char *dotted)
1079bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1080bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, true);
1081bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1082bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1083bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name)
1084bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1085bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1086bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct netent *net;
1087bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1088bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((net = getnetbyname(name)) != NULL) {
1089bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (net->n_addrtype != AF_INET)
1090bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1091bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addr.s_addr = htonl(net->n_net);
1092bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &addr;
1093bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1094bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1095bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1096bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1097bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1098bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
1099bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1100bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct hostent *host;
1101bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addr;
1102bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i;
1103bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1104bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1105bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((host = gethostbyname(name)) != NULL) {
1106bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (host->h_addrtype != AF_INET ||
1107bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		    host->h_length != sizeof(struct in_addr))
1108bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1109bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1110bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		while (host->h_addr_list[*naddr] != NULL)
1111bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			++*naddr;
1112630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addr = xtables_calloc(*naddr, sizeof(struct in_addr) * *naddr);
1113bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (i = 0; i < *naddr; i++)
1114bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			memcpy(&addr[i], host->h_addr_list[i],
1115bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			       sizeof(struct in_addr));
1116bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1117bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1118bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1119bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1120bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1121bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1122bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *
1123bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs)
1124bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1125bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrptmp, *addrp;
1126bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11271e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL ||
1128bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ipaddr(name)) != NULL) {
1129630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in_addr));
1130bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1131bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1132bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1133bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1134bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL)
1135bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrptmp;
1136bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
11378b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1138bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1139bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1140bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask)
1141bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1142bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr maskaddr;
1143bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1144bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1145bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1146bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1147bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 32 bits */
1148bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = 0xFFFFFFFF;
1149bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1150bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
11511e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL)
1152bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* dotted_to_addr already returns a network byte order addr */
1153bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
11545f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 32))
11558b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1156bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1157bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1158bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
1159bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1160bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1161bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1162bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	maskaddr.s_addr = 0U;
1163bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1164bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1165bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1166332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
1167332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow                              struct in_addr **maskpp, unsigned int *naddrs)
1168332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
1169332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in_addr *addrp;
1170332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	char buf[256], *p;
1171332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1172332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1173332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1174332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1175332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1176332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1177332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1178332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1179332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
1180332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
1181332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1182332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1183332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1184332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count; ++i) {
1185332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (loop == NULL)
1186332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1187332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == ',')
1188332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			++loop;
1189332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == '\0')
1190332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1191332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		p = strchr(loop, ',');
1192332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (p != NULL)
1193332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = p - loop;
1194332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1195332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1196332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (len == 0 || sizeof(buf) - 1 < len)
1197332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1198332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1199332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1200332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1201332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		loop += len;
1202332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1203332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1204332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(p + 1);
1205332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1206332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(NULL);
1207332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1208332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1209332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1210332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
1211332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((*maskpp + i)->s_addr == 0)
1212332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			/*
1213332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * A bit pointless to process multiple addresses
1214332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * in this case...
1215332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 */
1216332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "0.0.0.0");
1217332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1218332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ipparse_hostnetwork(buf, &n);
1219332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1220332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1221332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1222332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1223332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1224332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1225332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1226332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1227332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1228332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1229332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1230332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1231332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1232332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1233332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1234332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1235332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1236332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1237332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ipparse_hostnetwork had allocated: */
1238332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1239332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1240332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
1241332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < n; ++i)
1242332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
1243332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1244332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1245332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1246a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt/**
1247a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * xtables_ipparse_any - transform arbitrary name to in_addr
1248a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt *
1249a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * Possible inputs (pseudo regex):
1250a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * 	m{^($hostname|$networkname|$ipaddr)(/$mask)?}
1251a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname"
1252a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt */
1253a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp,
1254a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                         struct in_addr *maskp, unsigned int *naddrs)
1255bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1256bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1257bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1258bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1259bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1260bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1261bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1262bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1263bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1264bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(p + 1);
1265bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1266bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(NULL);
1267bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1268bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1269bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1270bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
1271bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (maskp->s_addr == 0U)
1272bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "0.0.0.0");
1273bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1274bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ipparse_hostnetwork(buf, naddrs);
1275bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1276bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1277bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[j++].s_addr &= maskp->s_addr;
1278bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1279bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (addrp[k].s_addr == addrp[j-1].s_addr) {
1280bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				--*naddrs;
1281bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				--j;
1282bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1283bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1284bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1285bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1286bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1287e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp)
128808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
128908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	/* 0000:0000:0000:0000:0000:000.000.000.000
129008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	 * 0000:0000:0000:0000:0000:0000:0000:0000 */
129108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+1];
129208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
129308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
129408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
129508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr)
129608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
129708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char hostname[NI_MAXHOST];
129808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct sockaddr_in6 saddr;
129908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int err;
130008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
130108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memset(&saddr, 0, sizeof(struct sockaddr_in6));
130208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memcpy(&saddr.sin6_addr, addr, sizeof(*addr));
130308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	saddr.sin6_family = AF_INET6;
130408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
130508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6),
130608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	      hostname, sizeof(hostname) - 1, NULL, 0, 0);
130708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (err != 0) {
130808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
130908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		fprintf(stderr,"IP2Name: %s\n",gai_strerror(err));
131008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
131108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
131208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
131308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
131408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
131508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	fprintf (stderr, "\naddr2host: %s\n", hostname);
131608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
131708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return hostname;
131808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
131908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1320e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr)
132108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
132208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
132308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
132408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ip6addr_to_host(addr)) != NULL)
132508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
132608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1327e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ip6addr_to_numeric(addr);
132808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
132908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
133008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic int ip6addr_prefix_length(const struct in6_addr *k)
133108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
133208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	unsigned int bits = 0;
133308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t a, b, c, d;
133408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
133548607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	a = ntohl(k->s6_addr32[0]);
133648607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	b = ntohl(k->s6_addr32[1]);
133748607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	c = ntohl(k->s6_addr32[2]);
133848607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	d = ntohl(k->s6_addr32[3]);
133908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (a & 0x80000000U) {
134008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		++bits;
134108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a <<= 1;
134208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a  |= (b >> 31) & 1;
134308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b <<= 1;
134408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b  |= (c >> 31) & 1;
134508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c <<= 1;
134608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c  |= (d >> 31) & 1;
134708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		d <<= 1;
134808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
134908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (a != 0 || b != 0 || c != 0 || d != 0)
135008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return -1;
135108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return bits;
135208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
135308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1354e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
135508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
135608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+2];
135708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int l = ip6addr_prefix_length(addrp);
135808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
135908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (l == -1) {
136008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		strcpy(buf, "/");
1361e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		strcat(buf, xtables_ip6addr_to_numeric(addrp));
136208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return buf;
136308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
136408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "/%d", l);
136508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
136608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
1367bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
13681e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in6_addr *xtables_numeric_to_ip6addr(const char *num)
1369bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1370bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr ap;
1371bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
1372bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1373bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
1374bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &ap;
1375bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1376bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	fprintf(stderr, "\nnumeric2addr: %d\n", err);
1377bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1378bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1379bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1380bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1381bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1382bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr)
1383bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1384bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr *addr;
1385bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct addrinfo hints;
1386bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct addrinfo *res;
1387bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
1388bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1389bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&hints, 0, sizeof(hints));
1390bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_flags    = AI_CANONNAME;
1391bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_family   = AF_INET6;
1392bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_socktype = SOCK_RAW;
1393bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_protocol = IPPROTO_IPV6;
1394bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_next     = NULL;
1395bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1396bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1397bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
1398bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1399bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr,"Name2IP: %s\n",gai_strerror(err));
1400bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1401bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1402bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1403bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (res->ai_family != AF_INET6 ||
1404bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		    res->ai_addrlen != sizeof(struct sockaddr_in6))
1405bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1406bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1407bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1408bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr, "resolved: len=%d  %s ", res->ai_addrlen,
140930290aea009cf3fd76f27336fb4370be3467c4daPatrick McHardy		        xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr));
1410bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1411bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* Get the first element of the address-chain */
1412630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addr = xtables_malloc(sizeof(struct in6_addr));
1413bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addr, &((const struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
1414bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		       sizeof(struct in6_addr));
1415bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		freeaddrinfo(res);
1416bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddr = 1;
1417bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1418bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1419bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1420bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1421bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1422bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1423bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name)
1424bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1425bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/*	abort();*/
1426bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* TODO: not implemented yet, but the exception breaks the
1427bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	 *       name resolvation */
1428bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1429bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1430bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1431bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1432bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs)
1433bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1434bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp, *addrptmp;
1435bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
14361e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL ||
1437bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ip6addr(name)) != NULL) {
1438630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in6_addr));
1439bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1440bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1441bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1442bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1443bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrp = host_to_ip6addr(name, naddrs)) != NULL)
1444bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1445bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
14468b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1447bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1448bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1449bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask)
1450bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1451bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr maskaddr;
1452bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1453bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1454bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1455bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1456bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 128 bits */
1457bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(&maskaddr, 0xff, sizeof maskaddr);
1458bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1459bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
14601e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL)
1461bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
14625f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
14638b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1464bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1465bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1466bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		char *p = (void *)&maskaddr;
1467bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p, 0xff, bits / 8);
1468bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
1469bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p[bits/8] = 0xff << (8 - (bits & 7));
1470bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1471bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1472bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1473bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&maskaddr, 0, sizeof(maskaddr));
1474bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1475bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1476bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1477332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid
1478332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowxtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
1479332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		      struct in6_addr **maskpp, unsigned int *naddrs)
1480332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
148158df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel	static const struct in6_addr zero_addr;
1482332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in6_addr *addrp;
1483332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	char buf[256], *p;
1484332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1485332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1486332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1487332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1488332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1489332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1490332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1491332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1492332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
1493332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
1494332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1495332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1496332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1497332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count /*NB: count can grow*/; ++i) {
1498332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (loop == NULL)
1499332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1500332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == ',')
1501332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			++loop;
1502332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (*loop == '\0')
1503332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1504332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		p = strchr(loop, ',');
1505332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (p != NULL)
1506332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = p - loop;
1507332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1508332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1509332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (len == 0 || sizeof(buf) - 1 < len)
1510332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			break;
1511332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1512332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1513332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1514332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		loop += len;
1515332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1516332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1517332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(p + 1);
1518332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1519332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(NULL);
1520332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1521332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1522332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1523332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
152458df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel		if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0)
1525332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "::");
1526332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1527332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ip6parse_hostnetwork(buf, &n);
1528332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* ip6parse_hostnetwork only ever returns one IP
1529332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		address (it exits if the resolution fails).
1530332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		Therefore, n will always be 1 here.  Leaving the
1531332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		code below in anyway in case ip6parse_hostnetwork
1532332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		is improved some day to behave like
1533332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		ipparse_hostnetwork: */
1534332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1535332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1536332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1537332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1538332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1539332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1540332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1541332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1542332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1543332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1544332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1545332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1546332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1547332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1548332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1549332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1550332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1551332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1552332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ip6parse_hostnetwork had allocated: */
1553332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1554332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1555332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
1556332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < n; ++i)
1557332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		for (j = 0; j < 4; ++j)
1558332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
1559332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1560332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1561a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
1562a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                          struct in6_addr *maskp, unsigned int *naddrs)
1563bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
15649c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	static const struct in6_addr zero_addr;
1565bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1566bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1567bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1568bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1569bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1570bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf)-1] = '\0';
1571bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1572bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1573bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(p + 1);
1574bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1575bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(NULL);
1576bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1577bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1578bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1579bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
15809c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0)
1581bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "::");
1582bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1583bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs);
1584bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1585bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1586bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < 4; ++k)
15875a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai			addrp[j].s6_addr32[k] &= maskp->s6_addr32[k];
1588bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		++j;
1589bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1590bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
1591bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				--*naddrs;
1592bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				--j;
1593bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1594bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1595bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1596bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1597a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1598a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_save_string(const char *value)
1599a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{
1600a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char no_quote_chars[] = "_-0123456789"
1601a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"abcdefghijklmnopqrstuvwxyz"
1602a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1603a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char escape_chars[] = "\"\\'";
1604a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	size_t length;
1605a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	const char *p;
1606a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1607a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	length = strcspn(value, no_quote_chars);
1608a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	if (length > 0 && value[length] == 0) {
1609a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* no quoting required */
1610a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		fputs(value, stdout);
1611a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		putchar(' ');
1612a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	} else {
1613a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* there is at least one dangerous character in the
1614a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   value, which we have to quote.  Write double quotes
1615a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   around the value and escape special characters with
1616a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   a backslash */
1617a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		putchar('"');
1618a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1619a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		for (p = strpbrk(value, escape_chars); p != NULL;
1620a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		     p = strpbrk(value, escape_chars)) {
1621a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			if (p > value)
1622a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann				fwrite(value, 1, p - value, stdout);
1623a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar('\\');
1624a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar(*p);
1625a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			value = p + 1;
1626a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		}
1627a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1628a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* print the rest and finish the double quoted
1629a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   string */
1630a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		fputs(value, stdout);
1631a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		printf("\" ");
1632a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	}
1633a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann}
16340f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16350f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt/**
16360f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Check for option-intrapositional negation.
16370f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Do not use in new code.
16380f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt */
16390f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardtint xtables_check_inverse(const char option[], int *invert,
1640bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt			  int *my_optind, int argc, char **argv)
16410f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt{
16422be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (option == NULL || strcmp(option, "!") != 0)
16432be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		return false;
16440f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16452be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	fprintf(stderr, "Using intrapositioned negation "
16462be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	        "(`--option ! this`) is deprecated in favor of "
16472be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	        "extrapositioned (`! --option this`).\n");
16480f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
16492be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (*invert)
16502be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
16512be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt			   "Multiple `!' flags not allowed");
16522be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	*invert = true;
16532be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	if (my_optind != NULL) {
1654bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt		optarg = argv[*my_optind];
16552be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		++*my_optind;
16562be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt		if (argc && *my_optind > argc)
16572be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
16582be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt				   "no argument following `!'");
16590f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt	}
16602be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt
16612be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt	return true;
16620f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt}
16631de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
16641de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtconst struct xtables_pprot xtables_chain_protos[] = {
16651de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"tcp",       IPPROTO_TCP},
16661de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"sctp",      IPPROTO_SCTP},
16671de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udp",       IPPROTO_UDP},
16681de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udplite",   IPPROTO_UDPLITE},
16691de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmp",      IPPROTO_ICMP},
16701de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmpv6",    IPPROTO_ICMPV6},
16711de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-icmp", IPPROTO_ICMPV6},
16721de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"esp",       IPPROTO_ESP},
16731de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ah",        IPPROTO_AH},
16741de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-mh",   IPPROTO_MH},
16751de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"mh",        IPPROTO_MH},
16761de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"all",       0},
16771de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{NULL},
16781de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt};
16791de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
16801de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtu_int16_t
16811de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtxtables_parse_protocol(const char *s)
16821de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt{
16831de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	unsigned int proto;
16841de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
16851de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) {
16861de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		struct protoent *pent;
16871de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
16881de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		/* first deal with the special case of 'all' to prevent
16891de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * people from being able to redefine 'all' in nsswitch
16901de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * and/or provoke expensive [not working] ldap/nis/...
16911de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		 * lookups */
16921de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		if (!strcmp(s, "all"))
16931de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			return 0;
16941de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
16951de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		if ((pent = getprotobyname(s)))
16961de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			proto = pent->p_proto;
16971de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		else {
16981de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			unsigned int i;
16991de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
1700e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso				if (xtables_chain_protos[i].name == NULL)
1701e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso					continue;
1702e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso
17031de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt				if (strcmp(s, xtables_chain_protos[i].name) == 0) {
17041de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					proto = xtables_chain_protos[i].num;
17051de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					break;
17061de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt				}
17071de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			}
17081de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt			if (i == ARRAY_SIZE(xtables_chain_protos))
17098b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim				xt_params->exit_err(PARAMETER_PROBLEM,
17101de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					   "unknown protocol `%s' specified",
17111de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt					   s);
17121de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt		}
17131de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	}
17141de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
17151de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	return proto;
17161de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt}
1717