xtables.c revision cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adf
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 */
183c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#include "config.h"
19d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt#include <ctype.h>
203dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <errno.h>
210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <fcntl.h>
220b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt#include <inttypes.h>
2304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI#include <netdb.h>
24aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt#include <stdarg.h>
25cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt#include <stdbool.h>
263dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdio.h>
273dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdlib.h>
280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <string.h>
290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <unistd.h>
300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#include <sys/socket.h>
310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/stat.h>
32b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski#include <sys/statfs.h>
330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/types.h>
34f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt#include <sys/utsname.h>
350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/wait.h>
3608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#include <arpa/inet.h>
373c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#if defined(HAVE_LINUX_MAGIC_H)
383c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#	include <linux/magic.h> /* for PROC_SUPER_MAGIC */
393c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#elif defined(HAVE_LINUX_PROC_FS_H)
403c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#	include <linux/proc_fs.h>	/* Linux 2.4 */
4141a9b481693b4c43c16d0588cc558dd455168af0Jan Engelhardt#else
4241a9b481693b4c43c16d0588cc558dd455168af0Jan Engelhardt#	define PROC_SUPER_MAGIC	0x9fa0
433c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#endif
443dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
455208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI#include <xtables.h>
464e41854423b529d3107c23b85434d50a75d08057Jan Engelhardt#include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */
4777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt#include <linux/netfilter_ipv4/ip_tables.h>
4877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt#include <linux/netfilter_ipv6/ip6_tables.h>
49ef18e8147903885708d1c264904129af4fb636d6Jan Engelhardt#include <libiptc/libxtc.h>
503dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
515a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#ifndef NO_SHARED_LIBS
525a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#include <dlfcn.h>
535a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#endif
54c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */
55c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IPT_SO_GET_REVISION_MATCH	(IPT_BASE_CTL + 2)
56c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IPT_SO_GET_REVISION_TARGET	(IPT_BASE_CTL + 3)
57c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#endif
58c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */
59c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IP6T_SO_GET_REVISION_MATCH	68
60c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IP6T_SO_GET_REVISION_TARGET	69
61c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#endif
6270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim#include <getopt.h>
63aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "iptables/internal.h"
641e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt#include "xshared.h"
655a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger
660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#define NPROTO	255
670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
680b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#ifndef PROC_SYS_MODPROBE
690b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
700b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#endif
710b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
7237911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski/* we need this for ip6?tables-restore.  ip6?tables-restore.c sets line to the
7337911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski * current line of the input file, in order  to give a more precise error
7437911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski * message.  ip6?tables itself doesn't need this, so it is initialized to the
7537911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski * magic number of -1 */
7637911de507d0597980ad218a044a482501a21b01Maciej Zenczykowskiint line = -1;
7737911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski
788b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
798b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim
8040a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salimstruct xtables_globals *xt_params = NULL;
8140a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim
828b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...)
8340a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim{
8440a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	va_list args;
8540a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim
8640a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	va_start(args, msg);
8740a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version);
8840a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	vfprintf(stderr, msg, args);
8940a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	va_end(args);
9040a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	fprintf(stderr, "\n");
9140a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	exit(status);
9240a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim}
9340a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim
94600f38db82548a683775fd89b6e136673e924097Jan Engelhardtvoid xtables_free_opts(int unused)
9584c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim{
96df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt	if (xt_params->opts != xt_params->orig_opts) {
9759e8114c6792242e80785f4461d5e663fb9a3d64Jan Engelhardt		free(xt_params->opts);
98df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt		xt_params->opts = NULL;
99df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt	}
10084c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim}
10184c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim
102600f38db82548a683775fd89b6e136673e924097Jan Engelhardtstruct option *xtables_merge_options(struct option *orig_opts,
103600f38db82548a683775fd89b6e136673e924097Jan Engelhardt				     struct option *oldopts,
10470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim				     const struct option *newopts,
10570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim				     unsigned int *option_offset)
10670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim{
107600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	unsigned int num_oold = 0, num_old = 0, num_new = 0, i;
108600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	struct option *merge, *mp;
10970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
11070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	if (newopts == NULL)
11170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim		return oldopts;
11270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
113600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ;
114600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	if (oldopts != NULL)
115600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		for (num_old = 0; oldopts[num_old].name; num_old++) ;
11670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	for (num_new = 0; newopts[num_new].name; num_new++) ;
11770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
1181dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	/*
1191dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 * Since @oldopts also has @orig_opts already (and does so at the
1201dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 * start), skip these entries.
1211dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 */
1221dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	oldopts += num_oold;
1231dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	num_old -= num_oold;
1241dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt
125600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1));
126600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	if (merge == NULL)
127600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		return NULL;
128600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
129600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Let the base options -[ADI...] have precedence over everything */
130600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(merge, orig_opts, sizeof(*mp) * num_oold);
131600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	mp = merge + num_oold;
132600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
133600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Second, the new options */
1341e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt	xt_params->option_offset += XT_OPTION_OFFSET_SCALE;
13570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	*option_offset = xt_params->option_offset;
136600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(mp, newopts, sizeof(*mp) * num_new);
13770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
138600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	for (i = 0; i < num_new; ++i, ++mp)
139600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		mp->val += *option_offset;
140600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
141600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Third, the old options */
142600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(mp, oldopts, sizeof(*mp) * num_old);
143600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	mp += num_old;
144600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	xtables_free_opts(0);
14570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
146600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Clear trailing entry */
147600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memset(mp, 0, sizeof(*mp));
14870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	return merge;
14970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim}
15070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
15177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv4 = {
15277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.kmod          = "ip_tables",
153b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	.proc_exists   = "/proc/net/ip_tables_names",
15477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.libprefix     = "libipt_",
15577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.family	       = NFPROTO_IPV4,
15677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.ipproto       = IPPROTO_IP,
15777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_match  = IPT_SO_GET_REVISION_MATCH,
15877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_target = IPT_SO_GET_REVISION_TARGET,
15977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
16077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
16177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv6 = {
16277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.kmod          = "ip6_tables",
163b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	.proc_exists   = "/proc/net/ip6_tables_names",
16477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.libprefix     = "libip6t_",
16577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.family        = NFPROTO_IPV6,
16677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.ipproto       = IPPROTO_IPV6,
16777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_match  = IP6T_SO_GET_REVISION_MATCH,
16877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_target = IP6T_SO_GET_REVISION_TARGET,
16977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
17077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
171aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtconst struct xtables_afinfo *afinfo;
17277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
17339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt/* Search path for Xtables .so files */
17439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtstatic const char *xtables_libdir;
1750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1760b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */
177c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtconst char *xtables_modprobe_program;
1780b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1792c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski/* Keep track of matches/targets pending full registration: linked lists. */
1802c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistruct xtables_match *xtables_pending_matches;
1812c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistruct xtables_target *xtables_pending_targets;
1822c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
1832c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski/* Keep track of fully registered external matches/targets: linked lists. */
1840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches;
1850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets;
1860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1872c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski/* Fully register a match/target which was previously partially registered. */
1882c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_match(struct xtables_match *me);
1892c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_target(struct xtables_target *me);
1902c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
19139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtvoid xtables_init(void)
19239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt{
19339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = getenv("XTABLES_LIBDIR");
19439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	if (xtables_libdir != NULL)
19539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		return;
19639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = getenv("IPTABLES_LIB_DIR");
19739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	if (xtables_libdir != NULL) {
19839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, "
19939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		        "use XTABLES_LIBDIR.\n");
20039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		return;
20139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	}
202ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	/*
203ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * Well yes, IP6TABLES_LIB_DIR is of lower priority over
204ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok
205ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * for these env vars are deprecated anyhow, and in light of the
206ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * (shared) libxt_*.so files, makes less sense to have
207ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR.
208ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 */
209ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	xtables_libdir = getenv("IP6TABLES_LIB_DIR");
210ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	if (xtables_libdir != NULL) {
211ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, "
212ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		        "use XTABLES_LIBDIR.\n");
213ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		return;
214ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	}
21539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = XTABLES_LIBDIR;
21639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt}
21739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt
21877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtvoid xtables_set_nfproto(uint8_t nfproto)
21977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt{
22077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	switch (nfproto) {
22177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	case NFPROTO_IPV4:
22277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		afinfo = &afinfo_ipv4;
22377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		break;
22477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	case NFPROTO_IPV6:
22577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		afinfo = &afinfo_ipv6;
22677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		break;
22777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	default:
22877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n",
22977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		        __func__);
23077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	}
23177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}
23277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
233630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt/**
2347e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * xtables_set_params - set the global parameters used by xtables
2357e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp:	input xtables_globals structure
2367e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim *
2377e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * The app is expected to pass a valid xtables_globals data-filled
2387e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * with proper values
2397e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp cannot be NULL
2407e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim *
2417e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * Returns -1 on failure to set and 0 on success
2427e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim */
2437e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_set_params(struct xtables_globals *xtp)
2447e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{
2457e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	if (!xtp) {
2467e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		fprintf(stderr, "%s: Illegal global params\n",__func__);
2477e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		return -1;
2487e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	}
2497e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2507e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xt_params = xtp;
2517e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2527e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	if (!xt_params->exit_err)
2537e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		xt_params->exit_err = basic_exit_err;
2547e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2557e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	return 0;
2567e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim}
2577e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2587e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto)
2597e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{
2607e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xtables_init();
2617e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xtables_set_nfproto(nfproto);
2627e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	return xtables_set_params(xtp);
2637e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim}
2647e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2657e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim/**
266630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt * xtables_*alloc - wrappers that exit on failure
267630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt */
268630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_calloc(size_t count, size_t size)
2693dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
2703dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
2713dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2723dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = calloc(count, size)) == NULL) {
2733dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: calloc failed");
2743dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
2753dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
2763dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2773dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
2783dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
2793dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
280630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_malloc(size_t size)
2813dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
2823dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
2833dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2843dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = malloc(size)) == NULL) {
2853dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: malloc failed");
2863dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
2873dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
2883dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2893dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
2903dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
2910b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
292332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid *xtables_realloc(void *ptr, size_t size)
293332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
294332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	void *p;
295332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
296332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	if ((p = realloc(ptr, size)) == NULL) {
297332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		perror("ip[6]tables: realloc failed");
298332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		exit(1);
299332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
300332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
301332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	return p;
302332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
303332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
3040b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void)
3050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
3060b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int procfile;
3070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *ret;
3080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ	1024
3100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
3110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (procfile < 0)
3120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return NULL;
313a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) {
314a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		fprintf(stderr, "Could not set close on exec: %s\n",
315a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski			strerror(errno));
316a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		exit(1);
317a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	}
3180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
319371cea299f0b2eb100b9fc9fb99089640d2d606fJan Engelhardt	ret = malloc(PROCFILE_BUFSIZ);
3200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (ret) {
3210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		memset(ret, 0, PROCFILE_BUFSIZ);
3220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
3230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case -1: goto fail;
3240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
3250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
3260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (ret[strlen(ret)-1]=='\n')
3270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			ret[strlen(ret)-1]=0;
3280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		close(procfile);
3290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return ret;
3300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail:
3320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(ret);
3330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	close(procfile);
3340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return NULL;
3350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
337c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_insmod(const char *modname, const char *modprobe, bool quiet)
3380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
3390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *buf = NULL;
3400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *argv[4];
3410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int status;
3420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	/* If they don't explicitly set it, read out of kernel */
3440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (!modprobe) {
3450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		buf = get_modprobe();
3460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (!buf)
3470b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			return -1;
3480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		modprobe = buf;
3490b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
351c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	/*
352c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * Need to flush the buffer, or the child may output it again
353c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * when switching the program thru execv.
354c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 */
355c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	fflush(stdout);
356c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt
35794aa2ea67d7b8a669e8541f094661a1dc89722a3Jan Engelhardt	switch (vfork()) {
3580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case 0:
3590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[0] = (char *)modprobe;
3600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[1] = (char *)modname;
3610b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (quiet) {
3620b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = "-q";
3630b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3640b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		} else {
3650b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = NULL;
3660b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3670b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
3680b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		execv(argv[0], argv);
3690b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3700b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		/* not usually reached */
3710b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		exit(1);
3720b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case -1:
373f53710b16c2bae1843c3f5fee390f496dfa82526Jiri Popelka		free(buf);
3740b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return -1;
3750b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3760b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	default: /* parent */
3770b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		wait(&status);
3780b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3790b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3800b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(buf);
3810b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
3820b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return 0;
3830b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return -1;
3840b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3850b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
386b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski/* return true if a given file exists within procfs */
387b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowskistatic bool proc_file_exists(const char *filename)
388b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski{
389b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	struct stat s;
390b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	struct statfs f;
391b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski
392b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (lstat(filename, &s))
393b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return false;
394b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (!S_ISREG(s.st_mode))
395b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return false;
396b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (statfs(filename, &f))
397b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return false;
398b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (f.f_type != PROC_SUPER_MAGIC)
399b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return false;
400b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	return true;
401b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski}
402b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski
403c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_load_ko(const char *modprobe, bool quiet)
4040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
405c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	static bool loaded = false;
406b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	int ret;
4070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
408b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (loaded)
409b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return 0;
410b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski
411b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (proc_file_exists(afinfo->proc_exists)) {
412b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		loaded = true;
413b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return 0;
414b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	};
415b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski
416b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	ret = xtables_insmod(afinfo->kmod, modprobe, quiet);
417b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (ret == 0)
418b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		loaded = true;
4190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ret;
4210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
4220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4235f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt/**
4245f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * xtables_strtou{i,l} - string to number conversion
4255f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @s:	input string
4265f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @end:	like strtoul's "end" pointer
4275f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @value:	pointer for result
4285f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @min:	minimum accepted value
4295f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @max:	maximum accepted value
4305f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt *
4315f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * If @end is NULL, we assume the caller wants a "strict strtoul", and hence
4325f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * "15a" is rejected.
4335f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * In either case, the value obtained is compared for min-max compliance.
4345f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Base is always 0, i.e. autodetect depending on @s.
435cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *
4365f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Returns true/false whether number was accepted. On failure, *value has
4375f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * undefined contents.
438cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */
4390b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardtbool xtables_strtoul(const char *s, char **end, uintmax_t *value,
4400b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt                     uintmax_t min, uintmax_t max)
441cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
4420b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt	uintmax_t v;
443d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt	const char *p;
444cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	char *my_end;
445cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
446cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	errno = 0;
447d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt	/* Since strtoul allows leading minus, we have to check for ourself. */
448d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt	for (p = s; isspace(*p); ++p)
449d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt		;
450d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt	if (*p == '-')
451d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt		return false;
4520b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt	v = strtoumax(s, &my_end, 0);
453cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (my_end == s)
454cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return false;
455cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (end != NULL)
456cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*end = my_end;
457cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
458cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (errno != ERANGE && min <= v && (max == 0 || v <= max)) {
459cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (value != NULL)
460cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			*value = v;
461cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (end == NULL)
462cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			return *my_end == '\0';
463cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return true;
464cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	}
465cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
466cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return false;
467cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
468cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4695f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoui(const char *s, char **end, unsigned int *value,
4705f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt                     unsigned int min, unsigned int max)
471cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
4720b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt	uintmax_t v;
473cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	bool ret;
474cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4755f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	ret = xtables_strtoul(s, end, &v, min, max);
476cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (value != NULL)
477cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*value = v;
478cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return ret;
479cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
480cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
481aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtint xtables_service_to_port(const char *name, const char *proto)
48204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
48304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	struct servent *service;
48404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
48504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((service = getservbyname(name, proto)) != NULL)
48604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		return ntohs((unsigned short) service->s_port);
48704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
48804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return -1;
48904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
49004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4917ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t xtables_parse_port(const char *port, const char *proto)
49204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
4937a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt	unsigned int portnum;
49404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4955f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) ||
496aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt	    (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1)
497213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt		return portnum;
49804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4998b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM,
50004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		   "invalid port/service `%s' specified", port);
50104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
50204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
503aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtvoid xtables_parse_interface(const char *arg, char *vianame,
504aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt			     unsigned char *mask)
50504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
506fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	unsigned int vialen = strlen(arg);
50704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned int i;
50804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
50904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(mask, 0, IFNAMSIZ);
51004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(vianame, 0, IFNAMSIZ);
51104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
51204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if (vialen + 1 > IFNAMSIZ)
5138b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
51404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   "interface name `%s' must be shorter than IFNAMSIZ"
51504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   " (%i)", arg, IFNAMSIZ-1);
51604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
51704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	strcpy(vianame, arg);
518fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	if (vialen == 0)
5192ca6273c73b42e8c74afd5f8b1fe10c5c93ce363Richard Weinberger		return;
52004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	else if (vianame[vialen - 1] == '+') {
52104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen - 1);
52204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Don't remove `+' here! -HW */
52304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	} else {
52404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Include nul-terminator in match */
52504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen + 1);
52604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		for (i = 0; vianame[i]; i++) {
527fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			if (vianame[i] == '/' ||
528fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			    vianame[i] == ' ') {
529aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann				fprintf(stderr,
530aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					"Warning: weird character in interface"
531fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt					" `%s' ('/' and ' ' are not allowed by the kernel).\n",
532aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					vianame);
53304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI				break;
53404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			}
53504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		}
53604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	}
53704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
53804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
539cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS
540927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardtstatic void *load_extension(const char *search_path, const char *af_prefix,
54121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt    const char *name, bool is_target)
54221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{
543927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt	const char *all_prefixes[] = {"libxt_", af_prefix, NULL};
544927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt	const char **prefix;
54521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	const char *dir = search_path, *next;
54621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	void *ptr = NULL;
54721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	struct stat sb;
54821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	char path[256];
54921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
55021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	do {
55121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		next = strchr(dir, ':');
55221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (next == NULL)
55321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			next = dir + strlen(dir);
55421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
555927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt		for (prefix = all_prefixes; *prefix != NULL; ++prefix) {
556927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			snprintf(path, sizeof(path), "%.*s/%s%s.so",
557927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			         (unsigned int)(next - dir), dir,
558927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			         *prefix, name);
559927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt
560927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (stat(path, &sb) != 0) {
561927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				if (errno == ENOENT)
562927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt					continue;
563927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				fprintf(stderr, "%s: %s\n", path,
564927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt					strerror(errno));
565927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				return NULL;
566927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			}
567927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (dlopen(path, RTLD_NOW) == NULL) {
568927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				fprintf(stderr, "%s: %s\n", path, dlerror());
569927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				break;
570927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			}
57121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
57221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			if (is_target)
5732338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_target(name, XTF_DONT_LOAD);
57421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			else
5752338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_match(name,
5762338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				      XTF_DONT_LOAD, NULL);
57721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
578927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (ptr != NULL)
579927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				return ptr;
58021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
581927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			fprintf(stderr, "%s: no \"%s\" extension found for "
582927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				"this protocol\n", path, name);
583927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			errno = ENOENT;
584927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			return NULL;
585927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt		}
58621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		dir = next + 1;
58721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	} while (*next != '\0');
58821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
58921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	return NULL;
59021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt}
591cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif
59221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
5932338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_match *
5942338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_match(const char *name, enum xtables_tryload tryload,
5952338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		   struct xtables_rule_match **matches)
5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
5972c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	struct xtables_match **dptr;
5980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match *ptr;
5990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	const char *icmp6 = "icmp6";
6000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6010cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(name) >= XT_EXTENSION_MAXNAMELEN)
60221d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt		xtables_error(PARAMETER_PROBLEM,
60321d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt			   "Invalid match name \"%s\" (%u chars max)",
6040cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt			   name, XT_EXTENSION_MAXNAMELEN - 1);
60521d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt
6060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* This is ugly as hell. Nonetheless, there is no way of changing
6070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	 * this without hurting backwards compatibility */
6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if ( (strcmp(name,"icmpv6") == 0) ||
6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"ipv6-icmp") == 0) ||
6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"icmp6") == 0) )
6110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = icmp6;
6120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6132c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	/* Trigger delayed initialization */
6142c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	for (dptr = &xtables_pending_matches; *dptr; ) {
6152c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		if (strcmp(name, (*dptr)->name) == 0) {
6162c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			ptr = *dptr;
6172c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			*dptr = (*dptr)->next;
6182c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			ptr->next = NULL;
6192c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			xtables_fully_register_pending_match(ptr);
6202c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		} else {
6212c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			dptr = &((*dptr)->next);
6222c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		}
6232c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	}
6242c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
6250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_matches; ptr; ptr = ptr->next) {
6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0) {
6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			struct xtables_match *clone;
6280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* First match of this type: */
6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (ptr->m == NULL)
6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				break;
6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Second and subsequent clones */
634630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt			clone = xtables_malloc(sizeof(struct xtables_match));
6350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			memcpy(clone, ptr, sizeof(struct xtables_match));
6363eab786d6a687187556c92b3dc0f0664d8352471Jan Engelhardt			clone->udata = NULL;
6370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->mflags = 0;
6380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* This is a clone: */
6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->next = clone;
6400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = clone;
6420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
6430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
6440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
6472338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
64877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
64939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, false);
650170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
6512338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
6528b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
6530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load match `%s':%s\n",
654927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				   name, strerror(errno));
6550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
6570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
6582338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
6590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
6600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
6610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
6620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6632338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) {
6648b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
6650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find match `%s'\n", name);
6660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
6680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && matches) {
6700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match **i;
6710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match *newentry;
6720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
673630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		newentry = xtables_malloc(sizeof(struct xtables_rule_match));
6740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = matches; *i; i = &(*i)->next) {
6760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (strcmp(name, (*i)->match->name) == 0)
6772338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				(*i)->completed = true;
6780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
6790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->match = ptr;
6802338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		newentry->completed = false;
6810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->next = NULL;
6820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = newentry;
6830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
6860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
6870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6882338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_target *
6892338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_target(const char *name, enum xtables_tryload tryload)
6900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
6912c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	struct xtables_target **dptr;
6920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *ptr;
6930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Standard target? */
6950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(name, "") == 0
6960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_ACCEPT) == 0
6970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_DROP) == 0
6980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_QUEUE) == 0
6990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_RETURN) == 0)
7000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = "standard";
7010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7022c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	/* Trigger delayed initialization */
7032c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	for (dptr = &xtables_pending_targets; *dptr; ) {
7042c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		if (strcmp(name, (*dptr)->name) == 0) {
7052c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			ptr = *dptr;
7062c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			*dptr = (*dptr)->next;
7072c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			ptr->next = NULL;
7082c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			xtables_fully_register_pending_target(ptr);
7092c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		} else {
7102c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			dptr = &((*dptr)->next);
7112c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		}
7122c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	}
7132c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
7140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_targets; ptr; ptr = ptr->next) {
7150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0)
7160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
7170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
7202338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
72177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
72239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, true);
723170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
7242338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
7258b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
7260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load target `%s':%s\n",
727927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				   name, strerror(errno));
7280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
7300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
7312338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
7320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
7330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
7340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
7350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
736854d2d9bd7556cfd8a676b0bc18dc059a9a2dd25Peter Volkov	if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) {
7378b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
7380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find target `%s'\n", name);
7390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
7410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr)
7430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		ptr->used = 1;
7440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
7460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7487ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_revision(const char *name, uint8_t revision, int opt)
7490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
7500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xt_get_revision rev;
7510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	socklen_t s = sizeof(rev);
7520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	int max_rev, sockfd;
7530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
75477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);
7550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (sockfd < 0) {
756df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		if (errno == EPERM) {
757df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			/* revision 0 is always supported. */
758df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			if (revision != 0)
759e1639b0bc28420ca01d733749c8db16d5a3fbd0cJan Engelhardt				fprintf(stderr, "%s: Could not determine whether "
760df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"revision %u is supported, "
761df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"assuming it is.\n",
762e1639b0bc28420ca01d733749c8db16d5a3fbd0cJan Engelhardt					name, revision);
763df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			return 1;
764df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		}
7650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "Could not open socket to kernel: %s\n",
7660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			strerror(errno));
7670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
770a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) {
771a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		fprintf(stderr, "Could not set close on exec: %s\n",
772a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski			strerror(errno));
773a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		exit(1);
774a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	}
775a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski
776c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	xtables_load_ko(xtables_modprobe_program, true);
7770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	strcpy(rev.name, name);
7790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	rev.revision = revision;
7800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
78177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s);
7820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (max_rev < 0) {
7830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Definitely don't support this? */
7840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (errno == ENOENT || errno == EPROTONOSUPPORT) {
7850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
7860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return 0;
7870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else if (errno == ENOPROTOOPT) {
7880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
7890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Assume only revision 0 support (old kernel) */
7900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return (revision == 0);
7910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else {
7920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr, "getsockopt failed strangely: %s\n",
7930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				strerror(errno));
7940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
7950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
7960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	close(sockfd);
7980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return 1;
7990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
8000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8027ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_match_revision(const char *name, uint8_t revision)
8030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
80477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_match);
8050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
8060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8077ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_target_revision(const char *name, uint8_t revision)
8080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
80977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_target);
8100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
8110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
812dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardtstatic void xtables_check_options(const char *name, const struct option *opt)
813dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt{
814dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	for (; opt->name != NULL; ++opt)
815dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) {
816dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			fprintf(stderr, "%s: Extension %s uses invalid "
817dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			        "option value %d\n",xt_params->program_name,
818dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			        name, opt->val);
819dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			exit(1);
820dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		}
821dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt}
822dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
8230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me)
8240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
825c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
826c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: match %s<%u> is missing a version\n",
827c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
828c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
829c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
830dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
831dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
832dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
8335dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
834dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
8350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8380cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
839281439ba6b96b729ef1400a49ec53eda298bb9f8Li Yewang		fprintf(stderr, "%s: match `%s' has invalid name\n",
8405dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
8450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
8460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: match %s has invalid protocol family\n",
8475dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
851aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (me->x6_options != NULL)
852aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_option_metavalidate(me->name, me->x6_options);
853dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	if (me->extra_opts != NULL)
854dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		xtables_check_options(me->name, me->extra_opts);
855dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
8560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested match */
85777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
8580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
8590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8602c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	/* place on linked list of matches pending full registration */
8612c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	me->next = xtables_pending_matches;
8622c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	xtables_pending_matches = me;
8632c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski}
8642c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
865954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt/**
866954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * Compare two actions for their preference
867954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * @a:	one action
868954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * @b: 	another
869954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt *
870954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * Like strcmp, returns a negative number if @a is less preferred than @b,
871954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * positive number if @a is more preferred than @b, or zero if equally
872954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * preferred.
873954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt */
874954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardtstatic int
875cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardtxtables_mt_prefer(bool a_alias, unsigned int a_rev, unsigned int a_fam,
876cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		  bool b_alias, unsigned int b_rev, unsigned int b_fam)
877954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt{
878cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	/*
879cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 * Alias ranks higher than no alias.
880cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 * (We want the new action to be used whenever possible.)
881cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 */
882cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	if (!a_alias && b_alias)
883cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		return -1;
884cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	if (a_alias && !b_alias)
885cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		return 1;
886cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt
887954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	/* Higher revision ranks higher. */
888954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	if (a_rev < b_rev)
889954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		return -1;
890954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	if (a_rev > b_rev)
891954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		return 1;
892954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt
893954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	/* NFPROTO_<specific> ranks higher than NFPROTO_UNSPEC. */
894954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	if (a_fam == NFPROTO_UNSPEC && b_fam != NFPROTO_UNSPEC)
895954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		return -1;
896954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	if (a_fam != NFPROTO_UNSPEC && b_fam == NFPROTO_UNSPEC)
897954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		return 1;
898954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt
899954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	/* Must be the same thing. */
900954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	return 0;
901954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt}
902954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt
903954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardtstatic int xtables_match_prefer(const struct xtables_match *a,
904954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt				const struct xtables_match *b)
905954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt{
906cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	return xtables_mt_prefer(false, a->revision, a->family,
907cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt				 false, b->revision, b->family);
908954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt}
909954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt
910954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardtstatic int xtables_target_prefer(const struct xtables_target *a,
911954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt				 const struct xtables_target *b)
912954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt{
913cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	/*
914cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 * Note that if x->real_name==NULL, it will be set to x->name in
915cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 * xtables_register_*; the direct pointer comparison here is therefore
916cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 * legitimate to detect an alias.
917cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 */
918cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	return xtables_mt_prefer(a->name != a->real_name,
919cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt				 a->revision, a->family,
920cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt				 b->name != b->real_name,
921954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt				 b->revision, b->family);
922954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt}
923954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt
9242c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_match(struct xtables_match *me)
9252c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski{
9262c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	struct xtables_match **i, *old;
927954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	int compare;
9282c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
9292338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
9300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
931954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		compare = xtables_match_prefer(old, me);
932954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		if (compare == 0) {
9330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
9340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: match `%s' already registered.\n",
9355dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
9360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
9370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
9380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
940954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		if (compare > 0 &&
941954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		    compatible_match_revision(old->name, old->revision))
9420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
9430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
94423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new match can be used. */
9450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_match_revision(me->name, me->revision))
9460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
9470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
9490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
9500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
9510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
9540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
9555dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
9565dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
9570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Append to list. */
9610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (i = &xtables_matches; *i; i = &(*i)->next);
9620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = NULL;
9630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	*i = me;
9640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->m = NULL;
9660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->mflags = 0;
9670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
9680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9699a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_matches(struct xtables_match *match, unsigned int n)
9709a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
9719a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
9729a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_match(&match[--n]);
9739a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
9749a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
9759a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
9760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me)
9770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
978c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
979c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
980c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
981c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
982c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
983dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
984dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
985dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
9865dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
987dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
9880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9910cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
9920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
9935dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
9940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
9980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
9990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: target %s has invalid protocol family\n",
10005dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
10010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
10020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
10030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1004cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	if (me->real_name == NULL)
1005cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		me->real_name = me->name;
1006aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (me->x6_options != NULL)
1007aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_option_metavalidate(me->name, me->x6_options);
1008dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	if (me->extra_opts != NULL)
1009dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		xtables_check_options(me->name, me->extra_opts);
1010dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
10110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested target */
101277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
10130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
10140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10152c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	/* place on linked list of targets pending full registration */
10162c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	me->next = xtables_pending_targets;
10172c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	xtables_pending_targets = me;
10182c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski}
10192c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
10202c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_target(struct xtables_target *me)
10212c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski{
10222c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	struct xtables_target *old;
1023954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	int compare;
10242c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
10252338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_target(me->name, XTF_DURING_LOAD);
10260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
10270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_target **i;
10280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1029954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		compare = xtables_target_prefer(old, me);
1030954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		if (compare == 0) {
10310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
10320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: target `%s' already registered.\n",
10335dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
10340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
10350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
10360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
1038954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		if (compare > 0 &&
1039cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		    compatible_target_revision(old->real_name, old->revision))
10400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
10410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
104223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new target can be used. */
1043cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		if (!compatible_target_revision(me->real_name, me->revision))
10440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
10450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
10470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
10480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
10490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
10500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
10520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
10535dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
10545dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
10550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
10560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
10570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Prepend to list. */
10590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = xtables_targets;
10600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	xtables_targets = me;
10610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->t = NULL;
10620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->tflags = 0;
10630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
1064aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
10659a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_targets(struct xtables_target *target, unsigned int n)
10669a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
10679a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
10689a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_target(&target[--n]);
10699a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
10709a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
10719a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
1072a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt/**
1073a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * xtables_param_act - act on condition
1074a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @status:	a constant from enum xtables_exittype
1075a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1076a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONLY_ONCE: print error message that option may only be used once.
1077a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name (e.g. "mark")
1078a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2(...):	option in conflict (e.g. "--mark")
1079a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3(...):	condition to match on (see extensions/ for examples)
1080a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1081a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_NO_INVERT: option does not support inversion
1082a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
1083a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option in conflict
1084a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		condition to match on
1085a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1086a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_BAD_VALUE: bad value for option
1087a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
1088a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option with which the problem occured (e.g. "--mark")
1089a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		string the user passed in (e.g. "99999999999999")
1090a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1091a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONE_ACTION: two mutually exclusive actions have been specified
1092a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
1093a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1094a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * Displays an error message and exits the program.
1095a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt */
1096a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardtvoid xtables_param_act(unsigned int status, const char *p1, ...)
1097aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{
1098aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	const char *p2, *p3;
1099aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_list args;
1100aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	bool b;
1101aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
1102aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_start(args, p1);
1103aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
1104aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	switch (status) {
1105a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONLY_ONCE:
1106aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
1107aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
1108d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		if (!b) {
1109d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka			va_end(args);
1110aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
1111d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		}
11128b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1113aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option may only be specified once",
1114aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2);
1115aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1116a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_NO_INVERT:
1117aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
1118aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
1119d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		if (!b) {
1120d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka			va_end(args);
1121aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
1122d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		}
11238b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1124aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option cannot be inverted", p1, p2);
1125aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1126a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_BAD_VALUE:
1127aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
1128aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p3 = va_arg(args, const char *);
11298b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1130aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: Bad value for \"%s\" option: \"%s\"",
1131aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2, p3);
1132aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1133a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONE_ACTION:
1134aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b = va_arg(args, unsigned int);
1135d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		if (!b) {
1136d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka			va_end(args);
1137aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
1138d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		}
11398b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1140aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: At most one action is possible", p1);
1141aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1142aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	default:
11438b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(status, p1, args);
1144aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1145aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	}
1146aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
1147aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_end(args);
1148aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt}
114908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1150e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp)
115108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
115208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[20];
115308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const unsigned char *bytep = (const void *)&addrp->s_addr;
115408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
115508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
115608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
115708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
115808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
115908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr)
116008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
116108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct hostent *host;
116208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
116308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET);
116408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (host == NULL)
116508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
116608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
116708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return host->h_name;
116808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
116908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
117008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr)
117108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
117208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct netent *net;
117308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
117408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL)
117508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return net->n_name;
117608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
117708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return NULL;
117808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
117908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1180e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr)
118108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
118208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
118308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
118408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ipaddr_to_host(addr)) != NULL ||
118508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	    (name = ipaddr_to_network(addr)) != NULL)
118608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
118708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1188e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ipaddr_to_numeric(addr);
118908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
119008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1191a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayusoint xtables_ipmask_to_cidr(const struct in_addr *mask)
119208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
119308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t maskaddr, bits;
119408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int i;
119508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
119608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	maskaddr = ntohl(mask->s_addr);
1197a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	/* shortcut for /32 networks */
119808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (maskaddr == 0xFFFFFFFFL)
1199a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return 32;
120008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
120108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	i = 32;
120208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	bits = 0xFFFFFFFEL;
120308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (--i >= 0 && maskaddr != bits)
120408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		bits <<= 1;
120508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (i >= 0)
1206a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return i;
1207a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso
1208a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	/* this mask cannot be converted to CIDR notation */
1209a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	return -1;
1210a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso}
1211a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso
1212a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayusoconst char *xtables_ipmask_to_numeric(const struct in_addr *mask)
1213a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso{
1214a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	static char buf[20];
1215a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	uint32_t cidr;
1216a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso
1217a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	cidr = xtables_ipmask_to_cidr(mask);
1218a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	if (cidr < 0) {
121908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		/* mask was not a decent combination of 1's and 0's */
1220e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
1221a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return buf;
1222a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	} else if (cidr == 32) {
1223a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		/* we don't want to see "/32" */
1224a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return "";
1225a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	}
122608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1227a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	sprintf(buf, "/%d", cidr);
122808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
122908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
123008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1231bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask)
1232bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1233bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1234bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned char *addrp;
1235bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int onebyte;
1236bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[20], *p, *q;
1237bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int i;
1238bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1239bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* copy dotted string, because we need to modify it */
1240bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, dotted, sizeof(buf) - 1);
1241bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1242bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = (void *)&addr.s_addr;
1243bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1244bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	p = buf;
1245bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0; i < 3; ++i) {
1246bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if ((q = strchr(p, '.')) == NULL) {
1247bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (is_mask)
1248bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1249bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1250bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			/* autocomplete, this is a network address */
12515f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt			if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1252bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1253bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1254bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			addrp[i] = onebyte;
1255bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			while (i < 3)
1256bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				addrp[++i] = 0;
1257bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1258bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return &addr;
1259bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		}
1260bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1261bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*q = '\0';
12625f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt		if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1263bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1264bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1265bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[i] = onebyte;
1266bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p = q + 1;
1267bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1268bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1269bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* we have checked 3 bytes, now we check the last one */
12705f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1271bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1272bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1273bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp[3] = onebyte;
1274bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &addr;
1275bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1276bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
12771e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted)
1278bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1279bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, false);
1280bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1281bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
12821e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipmask(const char *dotted)
1283bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1284bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, true);
1285bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1286bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1287bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name)
1288bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1289bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1290bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct netent *net;
1291bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1292bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((net = getnetbyname(name)) != NULL) {
1293bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (net->n_addrtype != AF_INET)
1294bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1295bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addr.s_addr = htonl(net->n_net);
1296bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &addr;
1297bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1298bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1299bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1300bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1301bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1302bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
1303bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1304bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct hostent *host;
1305bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addr;
1306bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i;
1307bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1308bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1309bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((host = gethostbyname(name)) != NULL) {
1310bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (host->h_addrtype != AF_INET ||
1311bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		    host->h_length != sizeof(struct in_addr))
1312bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1313bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1314bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		while (host->h_addr_list[*naddr] != NULL)
1315bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			++*naddr;
131611e250ba02349cb1e34058673db3d0b54eb56c44Wes Campaigne		addr = xtables_calloc(*naddr, sizeof(struct in_addr));
1317bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (i = 0; i < *naddr; i++)
1318bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			memcpy(&addr[i], host->h_addr_list[i],
1319bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			       sizeof(struct in_addr));
1320bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1321bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1322bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1323bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1324bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1325bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1326bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *
1327bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs)
1328bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1329bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrptmp, *addrp;
1330bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
13311e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL ||
1332bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ipaddr(name)) != NULL) {
1333630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in_addr));
1334bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1335bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1336bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1337bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1338bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL)
1339bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrptmp;
1340bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
13418b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1342bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1343bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1344bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask)
1345bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1346bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr maskaddr;
1347bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1348bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1349bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1350bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1351bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 32 bits */
1352bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = 0xFFFFFFFF;
1353bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1354bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
13551e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL)
1356bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* dotted_to_addr already returns a network byte order addr */
1357bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
13585f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 32))
13598b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1360bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1361bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1362bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
1363bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1364bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1365bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1366bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	maskaddr.s_addr = 0U;
1367bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1368bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1369bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1370332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
1371332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow                              struct in_addr **maskpp, unsigned int *naddrs)
1372332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
1373332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in_addr *addrp;
1374c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt	char buf[256], *p, *next;
1375332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1376332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1377332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1378332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1379332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1380332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1381332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1382332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1383332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
1384332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
1385332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1386332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1387332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1388332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count; ++i) {
13890c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt		while (isspace(*loop))
13900c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt			++loop;
1391c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		next = strchr(loop, ',');
1392c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next != NULL)
1393c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			len = next - loop;
1394332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1395332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1396c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (len > sizeof(buf) - 1)
1397c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
1398c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt				"Hostname too long");
1399332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1400332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1401332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1402332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1403332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1404332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(p + 1);
1405332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1406332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(NULL);
1407332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1408332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1409332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1410332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
1411332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((*maskpp + i)->s_addr == 0)
1412332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			/*
1413332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * A bit pointless to process multiple addresses
1414332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * in this case...
1415332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 */
1416332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "0.0.0.0");
1417332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1418332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ipparse_hostnetwork(buf, &n);
1419332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1420332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1421332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1422332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1423332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1424332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1425332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1426332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1427332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1428332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1429332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1430332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1431332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1432332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1433332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1434332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1435332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1436332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1437332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ipparse_hostnetwork had allocated: */
1438332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1439c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next == NULL)
1440c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			break;
1441c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		loop = next + 1;
1442332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1443332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
14444b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt	for (i = 0; i < count; ++i)
1445332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
1446332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1447332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1448332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1449a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt/**
1450a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * xtables_ipparse_any - transform arbitrary name to in_addr
1451a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt *
1452a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * Possible inputs (pseudo regex):
1453a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * 	m{^($hostname|$networkname|$ipaddr)(/$mask)?}
1454a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname"
1455a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt */
1456a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp,
1457a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                         struct in_addr *maskp, unsigned int *naddrs)
1458bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1459bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1460bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1461bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1462bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1463bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1464bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1465bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1466bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1467bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(p + 1);
1468bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1469bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(NULL);
1470bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1471bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1472bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1473bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
1474bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (maskp->s_addr == 0U)
1475bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "0.0.0.0");
1476bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1477bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ipparse_hostnetwork(buf, naddrs);
1478bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1479bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1480bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[j++].s_addr &= maskp->s_addr;
1481bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1482bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (addrp[k].s_addr == addrp[j-1].s_addr) {
1483adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				/*
1484adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * Nuke the dup by copying an address from the
1485adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * tail here, and check the current position
1486adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * again (--j).
1487adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 */
1488adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				memcpy(&addrp[--j], &addrp[--*naddrs],
1489adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				       sizeof(struct in_addr));
1490bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1491bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1492bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1493bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1494bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1495e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp)
149608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
1497cf3e52d00b7d3fedf98ef7710c337c441270d936Maciej Zenczykowski	/* 0000:0000:0000:0000:0000:0000:000.000.000.000
149808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	 * 0000:0000:0000:0000:0000:0000:0000:0000 */
149908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+1];
150008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
150108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
150208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
150308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr)
150408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
150508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char hostname[NI_MAXHOST];
150608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct sockaddr_in6 saddr;
150708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int err;
150808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
150908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memset(&saddr, 0, sizeof(struct sockaddr_in6));
151008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memcpy(&saddr.sin6_addr, addr, sizeof(*addr));
151108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	saddr.sin6_family = AF_INET6;
151208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
151308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6),
151408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	      hostname, sizeof(hostname) - 1, NULL, 0, 0);
151508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (err != 0) {
151608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
151708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		fprintf(stderr,"IP2Name: %s\n",gai_strerror(err));
151808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
151908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
152008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
152108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
152208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
152308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	fprintf (stderr, "\naddr2host: %s\n", hostname);
152408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
152508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return hostname;
152608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
152708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1528e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr)
152908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
153008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
153108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
153208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ip6addr_to_host(addr)) != NULL)
153308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
153408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1535e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ip6addr_to_numeric(addr);
153608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
153708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1538a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayusoint xtables_ip6mask_to_cidr(const struct in6_addr *k)
153908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
154008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	unsigned int bits = 0;
154108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t a, b, c, d;
154208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
154348607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	a = ntohl(k->s6_addr32[0]);
154448607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	b = ntohl(k->s6_addr32[1]);
154548607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	c = ntohl(k->s6_addr32[2]);
154648607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	d = ntohl(k->s6_addr32[3]);
154708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (a & 0x80000000U) {
154808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		++bits;
154908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a <<= 1;
155008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a  |= (b >> 31) & 1;
155108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b <<= 1;
155208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b  |= (c >> 31) & 1;
155308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c <<= 1;
155408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c  |= (d >> 31) & 1;
155508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		d <<= 1;
155608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
155708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (a != 0 || b != 0 || c != 0 || d != 0)
155808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return -1;
155908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return bits;
156008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
156108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1562e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
156308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
156408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+2];
1565a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	int l = xtables_ip6mask_to_cidr(addrp);
156608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
156708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (l == -1) {
156808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		strcpy(buf, "/");
1569e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		strcat(buf, xtables_ip6addr_to_numeric(addrp));
157008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return buf;
157108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
157208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "/%d", l);
157308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
157408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
1575bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
15761e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in6_addr *xtables_numeric_to_ip6addr(const char *num)
1577bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1578bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr ap;
1579bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
1580bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1581bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
1582bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &ap;
1583bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1584bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	fprintf(stderr, "\nnumeric2addr: %d\n", err);
1585bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1586bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1587bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1588bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1589bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1590bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr)
1591bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
15922ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	struct in6_addr *addr;
1593bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct addrinfo hints;
15942ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	struct addrinfo *res, *p;
1595bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
15962ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	unsigned int i;
1597bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1598bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&hints, 0, sizeof(hints));
1599bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_flags    = AI_CANONNAME;
1600bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_family   = AF_INET6;
1601bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_socktype = SOCK_RAW;
1602bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1603bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1604bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
1605bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1606bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr,"Name2IP: %s\n",gai_strerror(err));
1607bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1608bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1609bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
16102ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		/* Find length of address chain */
16112ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		for (p = res; p != NULL; p = p->ai_next)
16122ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			++*naddr;
1613bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1614bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr, "resolved: len=%d  %s ", res->ai_addrlen,
161530290aea009cf3fd76f27336fb4370be3467c4daPatrick McHardy		        xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr));
1616bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
16172ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		/* Copy each element of the address chain */
16182ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		addr = xtables_calloc(*naddr, sizeof(struct in6_addr));
16192ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		for (i = 0, p = res; p != NULL; p = p->ai_next)
16202ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			memcpy(&addr[i++],
16212ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			       &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr,
16222ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			       sizeof(struct in6_addr));
1623bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		freeaddrinfo(res);
1624bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1625bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1626bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1627bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1628bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1629bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1630bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name)
1631bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1632bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/*	abort();*/
1633bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* TODO: not implemented yet, but the exception breaks the
1634bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	 *       name resolvation */
1635bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1636bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1637bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1638bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1639bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs)
1640bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1641bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp, *addrptmp;
1642bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
16431e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL ||
1644bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ip6addr(name)) != NULL) {
1645630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in6_addr));
1646bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1647bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1648bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1649bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1650bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrp = host_to_ip6addr(name, naddrs)) != NULL)
1651bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1652bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
16538b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1654bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1655bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1656bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask)
1657bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1658bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr maskaddr;
1659bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1660bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1661bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1662bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1663bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 128 bits */
1664bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(&maskaddr, 0xff, sizeof maskaddr);
1665bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1666bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
16671e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL)
1668bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
16695f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
16708b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1671bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1672bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1673bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		char *p = (void *)&maskaddr;
1674bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p, 0xff, bits / 8);
1675bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
1676bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p[bits/8] = 0xff << (8 - (bits & 7));
1677bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1678bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1679bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1680bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&maskaddr, 0, sizeof(maskaddr));
1681bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1682bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1683bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1684332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid
1685332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowxtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
1686332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		      struct in6_addr **maskpp, unsigned int *naddrs)
1687332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
168858df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel	static const struct in6_addr zero_addr;
1689332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in6_addr *addrp;
1690c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt	char buf[256], *p, *next;
1691332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1692332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1693332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1694332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1695332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1696332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1697332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1698332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1699332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
1700332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
1701332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1702332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1703332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1704332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count /*NB: count can grow*/; ++i) {
17050c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt		while (isspace(*loop))
17060c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt			++loop;
1707c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		next = strchr(loop, ',');
1708c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next != NULL)
1709c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			len = next - loop;
1710332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1711332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1712c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (len > sizeof(buf) - 1)
1713c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
1714c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt				"Hostname too long");
1715332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1716332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1717332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1718332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1719332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1720332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(p + 1);
1721332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1722332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(NULL);
1723332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1724332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1725332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1726332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
172758df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel		if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0)
1728332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "::");
1729332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1730332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ip6parse_hostnetwork(buf, &n);
1731332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1732332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1733332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1734332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1735332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1736332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1737332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1738332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1739332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1740332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1741332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1742332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1743332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1744332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1745332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1746332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1747332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1748332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1749332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ip6parse_hostnetwork had allocated: */
1750332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1751c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next == NULL)
1752c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			break;
1753c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		loop = next + 1;
1754332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1755332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
17564b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt	for (i = 0; i < count; ++i)
1757332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		for (j = 0; j < 4; ++j)
1758332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
1759332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1760332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1761a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
1762a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                          struct in6_addr *maskp, unsigned int *naddrs)
1763bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
17649c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	static const struct in6_addr zero_addr;
1765bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1766bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1767bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1768bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1769bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1770bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf)-1] = '\0';
1771bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1772bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1773bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(p + 1);
1774bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1775bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(NULL);
1776bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1777bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1778bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1779bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
17809c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0)
1781bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "::");
1782bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1783bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs);
1784bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1785bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1786bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < 4; ++k)
17875a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai			addrp[j].s6_addr32[k] &= maskp->s6_addr32[k];
1788bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		++j;
1789bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1790bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
1791adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				/*
1792adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * Nuke the dup by copying an address from the
1793adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * tail here, and check the current position
1794adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * again (--j).
1795adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 */
1796adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				memcpy(&addrp[--j], &addrp[--*naddrs],
1797adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				       sizeof(struct in_addr));
1798bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1799bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1800bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1801bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1802a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1803a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_save_string(const char *value)
1804a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{
1805a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char no_quote_chars[] = "_-0123456789"
1806a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"abcdefghijklmnopqrstuvwxyz"
1807a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1808a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char escape_chars[] = "\"\\'";
1809a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	size_t length;
1810a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	const char *p;
1811a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
181287dc7c4c842deb1e2e3d38089ffcad9f238d98deMax Kellerman	length = strspn(value, no_quote_chars);
1813a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	if (length > 0 && value[length] == 0) {
1814a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* no quoting required */
1815a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		putchar(' ');
181673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		fputs(value, stdout);
1817a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	} else {
1818a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* there is at least one dangerous character in the
1819a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   value, which we have to quote.  Write double quotes
1820a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   around the value and escape special characters with
1821a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   a backslash */
182273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" \"");
1823a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1824a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		for (p = strpbrk(value, escape_chars); p != NULL;
1825a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		     p = strpbrk(value, escape_chars)) {
1826a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			if (p > value)
1827a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann				fwrite(value, 1, p - value, stdout);
1828a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar('\\');
1829a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar(*p);
1830a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			value = p + 1;
1831a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		}
1832a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1833a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* print the rest and finish the double quoted
1834a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   string */
1835a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		fputs(value, stdout);
183673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		putchar('\"');
1837a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	}
1838a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann}
18390f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
18401de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtconst struct xtables_pprot xtables_chain_protos[] = {
18411de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"tcp",       IPPROTO_TCP},
18421de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"sctp",      IPPROTO_SCTP},
18431de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udp",       IPPROTO_UDP},
18441de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udplite",   IPPROTO_UDPLITE},
18451de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmp",      IPPROTO_ICMP},
18461de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmpv6",    IPPROTO_ICMPV6},
18471de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-icmp", IPPROTO_ICMPV6},
18481de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"esp",       IPPROTO_ESP},
18491de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ah",        IPPROTO_AH},
18501de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-mh",   IPPROTO_MH},
18511de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"mh",        IPPROTO_MH},
18521de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"all",       0},
18531de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{NULL},
18541de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt};
18551de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
18567ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t
18571de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtxtables_parse_protocol(const char *s)
18581de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt{
185985f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	const struct protoent *pent;
186085f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	unsigned int proto, i;
18611de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
186285f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	if (xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX))
186385f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		return proto;
18641de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
186585f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	/* first deal with the special case of 'all' to prevent
186685f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	 * people from being able to redefine 'all' in nsswitch
186785f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	 * and/or provoke expensive [not working] ldap/nis/...
186885f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	 * lookups */
186985f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	if (strcmp(s, "all") == 0)
187085f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		return 0;
18711de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
187285f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	pent = getprotobyname(s);
187385f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	if (pent != NULL)
187485f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		return pent->p_proto;
1875e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso
187685f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
187785f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		if (xtables_chain_protos[i].name == NULL)
187885f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt			continue;
187985f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		if (strcmp(s, xtables_chain_protos[i].name) == 0)
188085f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt			return xtables_chain_protos[i].num;
18811de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	}
188285f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	xt_params->exit_err(PARAMETER_PROBLEM,
188385f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		"unknown protocol \"%s\" specified", s);
188485f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	return -1;
18851de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt}
1886f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1887f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardtint kernel_version;
1888f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1889f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardtvoid get_kernel_version(void)
1890f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt{
1891f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	static struct utsname uts;
1892f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	int x = 0, y = 0, z = 0;
1893f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1894f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	if (uname(&uts) == -1) {
1895f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt		fprintf(stderr, "Unable to retrieve kernel version.\n");
1896f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt		xtables_free_opts(1);
1897f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt		exit(1);
1898f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	}
1899f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1900f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
1901f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	kernel_version = LINUX_VERSION(x, y, z);
1902f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt}
1903