xtables.c revision c436dad7cfdd80ca4a05ceed556c39babc266f55
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
851c436dad7cfdd80ca4a05ceed556c39babc266f55Jan Engelhardt	if (me->real_name == NULL)
852c436dad7cfdd80ca4a05ceed556c39babc266f55Jan Engelhardt		me->real_name = me->name;
853aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (me->x6_options != NULL)
854aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_option_metavalidate(me->name, me->x6_options);
855dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	if (me->extra_opts != NULL)
856dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		xtables_check_options(me->name, me->extra_opts);
857dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
8580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested match */
85977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
8600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
8610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8622c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	/* place on linked list of matches pending full registration */
8632c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	me->next = xtables_pending_matches;
8642c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	xtables_pending_matches = me;
8652c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski}
8662c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
867954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt/**
868954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * Compare two actions for their preference
869954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * @a:	one action
870954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * @b: 	another
871954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt *
872954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * Like strcmp, returns a negative number if @a is less preferred than @b,
873954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * positive number if @a is more preferred than @b, or zero if equally
874954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt * preferred.
875954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt */
876954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardtstatic int
877cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardtxtables_mt_prefer(bool a_alias, unsigned int a_rev, unsigned int a_fam,
878cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		  bool b_alias, unsigned int b_rev, unsigned int b_fam)
879954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt{
880cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	/*
881cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 * Alias ranks higher than no alias.
882cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 * (We want the new action to be used whenever possible.)
883cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 */
884cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	if (!a_alias && b_alias)
885cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		return -1;
886cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	if (a_alias && !b_alias)
887cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		return 1;
888cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt
889954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	/* Higher revision ranks higher. */
890954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	if (a_rev < b_rev)
891954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		return -1;
892954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	if (a_rev > b_rev)
893954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		return 1;
894954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt
895954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	/* NFPROTO_<specific> ranks higher than NFPROTO_UNSPEC. */
896954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	if (a_fam == NFPROTO_UNSPEC && b_fam != NFPROTO_UNSPEC)
897954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		return -1;
898954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	if (a_fam != NFPROTO_UNSPEC && b_fam == NFPROTO_UNSPEC)
899954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		return 1;
900954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt
901954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	/* Must be the same thing. */
902954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	return 0;
903954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt}
904954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt
905954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardtstatic int xtables_match_prefer(const struct xtables_match *a,
906954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt				const struct xtables_match *b)
907954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt{
908c436dad7cfdd80ca4a05ceed556c39babc266f55Jan Engelhardt	return xtables_mt_prefer(a->name != a->real_name,
909c436dad7cfdd80ca4a05ceed556c39babc266f55Jan Engelhardt				 a->revision, a->family,
910c436dad7cfdd80ca4a05ceed556c39babc266f55Jan Engelhardt				 b->name != b->real_name,
911c436dad7cfdd80ca4a05ceed556c39babc266f55Jan Engelhardt				 b->revision, b->family);
912954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt}
913954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt
914954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardtstatic int xtables_target_prefer(const struct xtables_target *a,
915954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt				 const struct xtables_target *b)
916954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt{
917cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	/*
918cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 * Note that if x->real_name==NULL, it will be set to x->name in
919cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 * xtables_register_*; the direct pointer comparison here is therefore
920cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 * legitimate to detect an alias.
921cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	 */
922cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	return xtables_mt_prefer(a->name != a->real_name,
923cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt				 a->revision, a->family,
924cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt				 b->name != b->real_name,
925954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt				 b->revision, b->family);
926954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt}
927954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt
9282c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_match(struct xtables_match *me)
9292c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski{
9302c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	struct xtables_match **i, *old;
931954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	int compare;
9322c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
9332338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
9340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
935954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		compare = xtables_match_prefer(old, me);
936954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		if (compare == 0) {
9370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
9380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: match `%s' already registered.\n",
9395dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
9400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
9410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
9420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
944954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		if (compare > 0 &&
945c436dad7cfdd80ca4a05ceed556c39babc266f55Jan Engelhardt		    compatible_match_revision(old->real_name, old->revision))
9460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
9470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
94823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new match can be used. */
949c436dad7cfdd80ca4a05ceed556c39babc266f55Jan Engelhardt		if (!compatible_match_revision(me->real_name, me->revision))
9500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
9510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
9530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
9540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
9550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
9580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
9595dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
9605dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
9610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Append to list. */
9650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (i = &xtables_matches; *i; i = &(*i)->next);
9660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = NULL;
9670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	*i = me;
9680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->m = NULL;
9700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->mflags = 0;
9710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
9720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9739a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_matches(struct xtables_match *match, unsigned int n)
9749a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
9759a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
9769a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_match(&match[--n]);
9779a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
9789a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
9799a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
9800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me)
9810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
982c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
983c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
984c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
985c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
986c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
987dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
988dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
989dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
9905dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
991dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
9920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9950cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
9960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
9975dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
9980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
10000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
10020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
10030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: target %s has invalid protocol family\n",
10045dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
10050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
10060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
10070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1008cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt	if (me->real_name == NULL)
1009cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		me->real_name = me->name;
1010aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (me->x6_options != NULL)
1011aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_option_metavalidate(me->name, me->x6_options);
1012dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	if (me->extra_opts != NULL)
1013dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		xtables_check_options(me->name, me->extra_opts);
1014dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
10150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested target */
101677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
10170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
10180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10192c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	/* place on linked list of targets pending full registration */
10202c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	me->next = xtables_pending_targets;
10212c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	xtables_pending_targets = me;
10222c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski}
10232c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
10242c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_target(struct xtables_target *me)
10252c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski{
10262c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	struct xtables_target *old;
1027954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt	int compare;
10282c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
10292338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_target(me->name, XTF_DURING_LOAD);
10300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
10310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_target **i;
10320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1033954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		compare = xtables_target_prefer(old, me);
1034954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		if (compare == 0) {
10350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
10360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: target `%s' already registered.\n",
10375dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
10380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
10390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
10400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
1042954b76c317f641b7faf33cc26931d45585cc0deaJan Engelhardt		if (compare > 0 &&
1043cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		    compatible_target_revision(old->real_name, old->revision))
10440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
10450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
104623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new target can be used. */
1047cd2f9bdbb7f9b737e5d640aafeb78bcd8e3a7adfJan Engelhardt		if (!compatible_target_revision(me->real_name, me->revision))
10480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
10490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
10510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
10520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
10530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
10540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
10560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
10575dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
10585dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
10590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
10600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
10610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Prepend to list. */
10630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = xtables_targets;
10640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	xtables_targets = me;
10650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->t = NULL;
10660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->tflags = 0;
10670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
1068aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
10699a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_targets(struct xtables_target *target, unsigned int n)
10709a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
10719a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
10729a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_target(&target[--n]);
10739a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
10749a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
10759a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
1076a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt/**
1077a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * xtables_param_act - act on condition
1078a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @status:	a constant from enum xtables_exittype
1079a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1080a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONLY_ONCE: print error message that option may only be used once.
1081a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name (e.g. "mark")
1082a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2(...):	option in conflict (e.g. "--mark")
1083a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3(...):	condition to match on (see extensions/ for examples)
1084a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1085a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_NO_INVERT: option does not support inversion
1086a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
1087a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option in conflict
1088a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		condition to match on
1089a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1090a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_BAD_VALUE: bad value for option
1091a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
1092a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option with which the problem occured (e.g. "--mark")
1093a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		string the user passed in (e.g. "99999999999999")
1094a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1095a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONE_ACTION: two mutually exclusive actions have been specified
1096a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
1097a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1098a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * Displays an error message and exits the program.
1099a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt */
1100a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardtvoid xtables_param_act(unsigned int status, const char *p1, ...)
1101aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{
1102aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	const char *p2, *p3;
1103aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_list args;
1104aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	bool b;
1105aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
1106aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_start(args, p1);
1107aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
1108aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	switch (status) {
1109a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONLY_ONCE:
1110aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
1111aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
1112d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		if (!b) {
1113d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka			va_end(args);
1114aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
1115d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		}
11168b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1117aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option may only be specified once",
1118aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2);
1119aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1120a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_NO_INVERT:
1121aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
1122aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
1123d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		if (!b) {
1124d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka			va_end(args);
1125aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
1126d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		}
11278b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1128aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option cannot be inverted", p1, p2);
1129aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1130a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_BAD_VALUE:
1131aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
1132aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p3 = va_arg(args, const char *);
11338b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1134aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: Bad value for \"%s\" option: \"%s\"",
1135aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2, p3);
1136aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1137a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONE_ACTION:
1138aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b = va_arg(args, unsigned int);
1139d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		if (!b) {
1140d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka			va_end(args);
1141aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
1142d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		}
11438b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1144aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: At most one action is possible", p1);
1145aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1146aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	default:
11478b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(status, p1, args);
1148aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1149aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	}
1150aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
1151aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_end(args);
1152aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt}
115308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1154e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp)
115508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
115608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[20];
115708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const unsigned char *bytep = (const void *)&addrp->s_addr;
115808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
115908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
116008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
116108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
116208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
116308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr)
116408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
116508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct hostent *host;
116608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
116708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET);
116808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (host == NULL)
116908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
117008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
117108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return host->h_name;
117208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
117308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
117408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr)
117508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
117608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct netent *net;
117708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
117808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL)
117908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return net->n_name;
118008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
118108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return NULL;
118208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
118308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1184e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr)
118508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
118608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
118708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
118808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ipaddr_to_host(addr)) != NULL ||
118908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	    (name = ipaddr_to_network(addr)) != NULL)
119008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
119108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1192e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ipaddr_to_numeric(addr);
119308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
119408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1195a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayusoint xtables_ipmask_to_cidr(const struct in_addr *mask)
119608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
119708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t maskaddr, bits;
119808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int i;
119908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
120008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	maskaddr = ntohl(mask->s_addr);
1201a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	/* shortcut for /32 networks */
120208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (maskaddr == 0xFFFFFFFFL)
1203a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return 32;
120408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
120508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	i = 32;
120608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	bits = 0xFFFFFFFEL;
120708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (--i >= 0 && maskaddr != bits)
120808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		bits <<= 1;
120908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (i >= 0)
1210a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return i;
1211a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso
1212a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	/* this mask cannot be converted to CIDR notation */
1213a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	return -1;
1214a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso}
1215a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso
1216a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayusoconst char *xtables_ipmask_to_numeric(const struct in_addr *mask)
1217a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso{
1218a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	static char buf[20];
1219a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	uint32_t cidr;
1220a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso
1221a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	cidr = xtables_ipmask_to_cidr(mask);
1222a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	if (cidr < 0) {
122308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		/* mask was not a decent combination of 1's and 0's */
1224e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
1225a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return buf;
1226a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	} else if (cidr == 32) {
1227a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		/* we don't want to see "/32" */
1228a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return "";
1229a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	}
123008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1231a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	sprintf(buf, "/%d", cidr);
123208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
123308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
123408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1235bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask)
1236bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1237bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1238bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned char *addrp;
1239bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int onebyte;
1240bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[20], *p, *q;
1241bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int i;
1242bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1243bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* copy dotted string, because we need to modify it */
1244bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, dotted, sizeof(buf) - 1);
1245bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1246bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = (void *)&addr.s_addr;
1247bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1248bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	p = buf;
1249bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0; i < 3; ++i) {
1250bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if ((q = strchr(p, '.')) == NULL) {
1251bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (is_mask)
1252bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1253bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1254bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			/* autocomplete, this is a network address */
12555f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt			if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1256bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1257bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1258bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			addrp[i] = onebyte;
1259bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			while (i < 3)
1260bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				addrp[++i] = 0;
1261bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1262bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return &addr;
1263bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		}
1264bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1265bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*q = '\0';
12665f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt		if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1267bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1268bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1269bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[i] = onebyte;
1270bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p = q + 1;
1271bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1272bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1273bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* we have checked 3 bytes, now we check the last one */
12745f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1275bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1276bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1277bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp[3] = onebyte;
1278bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &addr;
1279bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1280bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
12811e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted)
1282bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1283bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, false);
1284bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1285bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
12861e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipmask(const char *dotted)
1287bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1288bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, true);
1289bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1290bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1291bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name)
1292bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1293bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1294bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct netent *net;
1295bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1296bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((net = getnetbyname(name)) != NULL) {
1297bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (net->n_addrtype != AF_INET)
1298bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1299bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addr.s_addr = htonl(net->n_net);
1300bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &addr;
1301bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1302bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1303bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1304bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1305bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1306bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
1307bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1308bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct hostent *host;
1309bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addr;
1310bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i;
1311bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1312bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1313bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((host = gethostbyname(name)) != NULL) {
1314bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (host->h_addrtype != AF_INET ||
1315bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		    host->h_length != sizeof(struct in_addr))
1316bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1317bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1318bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		while (host->h_addr_list[*naddr] != NULL)
1319bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			++*naddr;
132011e250ba02349cb1e34058673db3d0b54eb56c44Wes Campaigne		addr = xtables_calloc(*naddr, sizeof(struct in_addr));
1321bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (i = 0; i < *naddr; i++)
1322bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			memcpy(&addr[i], host->h_addr_list[i],
1323bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			       sizeof(struct in_addr));
1324bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1325bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1326bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1327bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1328bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1329bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1330bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *
1331bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs)
1332bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1333bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrptmp, *addrp;
1334bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
13351e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL ||
1336bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ipaddr(name)) != NULL) {
1337630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in_addr));
1338bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1339bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1340bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1341bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1342bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL)
1343bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrptmp;
1344bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
13458b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1346bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1347bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1348bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask)
1349bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1350bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr maskaddr;
1351bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1352bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1353bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1354bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1355bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 32 bits */
1356bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = 0xFFFFFFFF;
1357bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1358bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
13591e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL)
1360bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* dotted_to_addr already returns a network byte order addr */
1361bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
13625f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 32))
13638b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1364bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1365bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1366bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
1367bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1368bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1369bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1370bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	maskaddr.s_addr = 0U;
1371bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1372bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1373bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1374332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
1375332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow                              struct in_addr **maskpp, unsigned int *naddrs)
1376332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
1377332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in_addr *addrp;
1378c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt	char buf[256], *p, *next;
1379332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1380332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1381332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1382332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1383332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1384332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1385332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1386332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1387332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
1388332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
1389332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1390332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1391332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1392332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count; ++i) {
13930c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt		while (isspace(*loop))
13940c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt			++loop;
1395c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		next = strchr(loop, ',');
1396c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next != NULL)
1397c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			len = next - loop;
1398332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1399332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1400c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (len > sizeof(buf) - 1)
1401c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
1402c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt				"Hostname too long");
1403332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1404332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1405332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1406332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1407332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1408332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(p + 1);
1409332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1410332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(NULL);
1411332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1412332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1413332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1414332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
1415332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((*maskpp + i)->s_addr == 0)
1416332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			/*
1417332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * A bit pointless to process multiple addresses
1418332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * in this case...
1419332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 */
1420332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "0.0.0.0");
1421332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1422332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ipparse_hostnetwork(buf, &n);
1423332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1424332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1425332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1426332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1427332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1428332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1429332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1430332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1431332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1432332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1433332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1434332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1435332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1436332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1437332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1438332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1439332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1440332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1441332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ipparse_hostnetwork had allocated: */
1442332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1443c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next == NULL)
1444c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			break;
1445c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		loop = next + 1;
1446332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1447332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
14484b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt	for (i = 0; i < count; ++i)
1449332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
1450332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1451332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1452332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1453a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt/**
1454a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * xtables_ipparse_any - transform arbitrary name to in_addr
1455a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt *
1456a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * Possible inputs (pseudo regex):
1457a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * 	m{^($hostname|$networkname|$ipaddr)(/$mask)?}
1458a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname"
1459a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt */
1460a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp,
1461a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                         struct in_addr *maskp, unsigned int *naddrs)
1462bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1463bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1464bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1465bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1466bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1467bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1468bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1469bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1470bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1471bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(p + 1);
1472bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1473bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(NULL);
1474bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1475bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1476bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1477bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
1478bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (maskp->s_addr == 0U)
1479bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "0.0.0.0");
1480bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1481bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ipparse_hostnetwork(buf, naddrs);
1482bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1483bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1484bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[j++].s_addr &= maskp->s_addr;
1485bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1486bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (addrp[k].s_addr == addrp[j-1].s_addr) {
1487adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				/*
1488adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * Nuke the dup by copying an address from the
1489adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * tail here, and check the current position
1490adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * again (--j).
1491adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 */
1492adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				memcpy(&addrp[--j], &addrp[--*naddrs],
1493adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				       sizeof(struct in_addr));
1494bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1495bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1496bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1497bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1498bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1499e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp)
150008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
1501cf3e52d00b7d3fedf98ef7710c337c441270d936Maciej Zenczykowski	/* 0000:0000:0000:0000:0000:0000:000.000.000.000
150208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	 * 0000:0000:0000:0000:0000:0000:0000:0000 */
150308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+1];
150408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
150508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
150608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
150708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr)
150808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
150908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char hostname[NI_MAXHOST];
151008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct sockaddr_in6 saddr;
151108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int err;
151208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
151308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memset(&saddr, 0, sizeof(struct sockaddr_in6));
151408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memcpy(&saddr.sin6_addr, addr, sizeof(*addr));
151508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	saddr.sin6_family = AF_INET6;
151608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
151708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6),
151808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	      hostname, sizeof(hostname) - 1, NULL, 0, 0);
151908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (err != 0) {
152008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
152108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		fprintf(stderr,"IP2Name: %s\n",gai_strerror(err));
152208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
152308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
152408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
152508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
152608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
152708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	fprintf (stderr, "\naddr2host: %s\n", hostname);
152808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
152908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return hostname;
153008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
153108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1532e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr)
153308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
153408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
153508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
153608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ip6addr_to_host(addr)) != NULL)
153708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
153808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1539e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ip6addr_to_numeric(addr);
154008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
154108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1542a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayusoint xtables_ip6mask_to_cidr(const struct in6_addr *k)
154308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
154408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	unsigned int bits = 0;
154508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t a, b, c, d;
154608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
154748607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	a = ntohl(k->s6_addr32[0]);
154848607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	b = ntohl(k->s6_addr32[1]);
154948607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	c = ntohl(k->s6_addr32[2]);
155048607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	d = ntohl(k->s6_addr32[3]);
155108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (a & 0x80000000U) {
155208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		++bits;
155308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a <<= 1;
155408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a  |= (b >> 31) & 1;
155508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b <<= 1;
155608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b  |= (c >> 31) & 1;
155708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c <<= 1;
155808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c  |= (d >> 31) & 1;
155908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		d <<= 1;
156008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
156108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (a != 0 || b != 0 || c != 0 || d != 0)
156208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return -1;
156308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return bits;
156408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
156508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1566e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
156708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
156808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+2];
1569a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	int l = xtables_ip6mask_to_cidr(addrp);
157008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
157108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (l == -1) {
157208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		strcpy(buf, "/");
1573e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		strcat(buf, xtables_ip6addr_to_numeric(addrp));
157408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return buf;
157508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
157608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "/%d", l);
157708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
157808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
1579bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
15801e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in6_addr *xtables_numeric_to_ip6addr(const char *num)
1581bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1582bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr ap;
1583bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
1584bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1585bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
1586bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &ap;
1587bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1588bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	fprintf(stderr, "\nnumeric2addr: %d\n", err);
1589bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1590bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1591bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1592bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1593bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1594bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr)
1595bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
15962ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	struct in6_addr *addr;
1597bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct addrinfo hints;
15982ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	struct addrinfo *res, *p;
1599bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
16002ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	unsigned int i;
1601bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1602bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&hints, 0, sizeof(hints));
1603bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_flags    = AI_CANONNAME;
1604bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_family   = AF_INET6;
1605bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_socktype = SOCK_RAW;
1606bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1607bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1608bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
1609bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1610bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr,"Name2IP: %s\n",gai_strerror(err));
1611bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1612bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1613bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
16142ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		/* Find length of address chain */
16152ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		for (p = res; p != NULL; p = p->ai_next)
16162ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			++*naddr;
1617bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1618bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr, "resolved: len=%d  %s ", res->ai_addrlen,
161930290aea009cf3fd76f27336fb4370be3467c4daPatrick McHardy		        xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr));
1620bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
16212ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		/* Copy each element of the address chain */
16222ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		addr = xtables_calloc(*naddr, sizeof(struct in6_addr));
16232ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		for (i = 0, p = res; p != NULL; p = p->ai_next)
16242ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			memcpy(&addr[i++],
16252ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			       &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr,
16262ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			       sizeof(struct in6_addr));
1627bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		freeaddrinfo(res);
1628bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1629bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1630bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1631bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1632bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1633bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1634bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name)
1635bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1636bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/*	abort();*/
1637bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* TODO: not implemented yet, but the exception breaks the
1638bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	 *       name resolvation */
1639bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1640bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1641bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1642bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1643bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs)
1644bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1645bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp, *addrptmp;
1646bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
16471e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL ||
1648bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ip6addr(name)) != NULL) {
1649630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in6_addr));
1650bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1651bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1652bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1653bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1654bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrp = host_to_ip6addr(name, naddrs)) != NULL)
1655bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1656bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
16578b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1658bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1659bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1660bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask)
1661bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1662bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr maskaddr;
1663bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1664bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1665bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1666bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1667bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 128 bits */
1668bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(&maskaddr, 0xff, sizeof maskaddr);
1669bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1670bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
16711e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL)
1672bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
16735f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
16748b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1675bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1676bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1677bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		char *p = (void *)&maskaddr;
1678bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p, 0xff, bits / 8);
1679bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
1680bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p[bits/8] = 0xff << (8 - (bits & 7));
1681bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1682bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1683bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1684bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&maskaddr, 0, sizeof(maskaddr));
1685bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1686bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1687bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1688332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid
1689332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowxtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
1690332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		      struct in6_addr **maskpp, unsigned int *naddrs)
1691332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
169258df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel	static const struct in6_addr zero_addr;
1693332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in6_addr *addrp;
1694c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt	char buf[256], *p, *next;
1695332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1696332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1697332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1698332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1699332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1700332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1701332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1702332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1703332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
1704332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
1705332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1706332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1707332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1708332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count /*NB: count can grow*/; ++i) {
17090c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt		while (isspace(*loop))
17100c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt			++loop;
1711c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		next = strchr(loop, ',');
1712c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next != NULL)
1713c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			len = next - loop;
1714332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1715332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1716c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (len > sizeof(buf) - 1)
1717c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
1718c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt				"Hostname too long");
1719332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1720332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1721332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1722332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1723332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1724332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(p + 1);
1725332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1726332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(NULL);
1727332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1728332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1729332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1730332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
173158df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel		if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0)
1732332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "::");
1733332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1734332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ip6parse_hostnetwork(buf, &n);
1735332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1736332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1737332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1738332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1739332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1740332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1741332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1742332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1743332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1744332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1745332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1746332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1747332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1748332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1749332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1750332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1751332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1752332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1753332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ip6parse_hostnetwork had allocated: */
1754332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1755c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next == NULL)
1756c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			break;
1757c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		loop = next + 1;
1758332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1759332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
17604b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt	for (i = 0; i < count; ++i)
1761332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		for (j = 0; j < 4; ++j)
1762332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
1763332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1764332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1765a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
1766a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                          struct in6_addr *maskp, unsigned int *naddrs)
1767bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
17689c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	static const struct in6_addr zero_addr;
1769bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1770bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1771bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1772bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1773bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1774bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf)-1] = '\0';
1775bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1776bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1777bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(p + 1);
1778bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1779bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(NULL);
1780bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1781bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1782bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1783bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
17849c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0)
1785bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "::");
1786bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1787bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs);
1788bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1789bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1790bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < 4; ++k)
17915a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai			addrp[j].s6_addr32[k] &= maskp->s6_addr32[k];
1792bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		++j;
1793bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1794bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
1795adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				/*
1796adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * Nuke the dup by copying an address from the
1797adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * tail here, and check the current position
1798adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * again (--j).
1799adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 */
1800adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				memcpy(&addrp[--j], &addrp[--*naddrs],
1801adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				       sizeof(struct in_addr));
1802bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1803bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1804bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1805bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1806a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1807a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_save_string(const char *value)
1808a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{
1809a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char no_quote_chars[] = "_-0123456789"
1810a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"abcdefghijklmnopqrstuvwxyz"
1811a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1812a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char escape_chars[] = "\"\\'";
1813a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	size_t length;
1814a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	const char *p;
1815a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
181687dc7c4c842deb1e2e3d38089ffcad9f238d98deMax Kellerman	length = strspn(value, no_quote_chars);
1817a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	if (length > 0 && value[length] == 0) {
1818a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* no quoting required */
1819a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		putchar(' ');
182073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		fputs(value, stdout);
1821a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	} else {
1822a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* there is at least one dangerous character in the
1823a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   value, which we have to quote.  Write double quotes
1824a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   around the value and escape special characters with
1825a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   a backslash */
182673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" \"");
1827a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1828a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		for (p = strpbrk(value, escape_chars); p != NULL;
1829a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		     p = strpbrk(value, escape_chars)) {
1830a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			if (p > value)
1831a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann				fwrite(value, 1, p - value, stdout);
1832a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar('\\');
1833a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar(*p);
1834a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			value = p + 1;
1835a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		}
1836a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1837a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* print the rest and finish the double quoted
1838a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   string */
1839a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		fputs(value, stdout);
184073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		putchar('\"');
1841a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	}
1842a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann}
18430f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
18441de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtconst struct xtables_pprot xtables_chain_protos[] = {
18451de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"tcp",       IPPROTO_TCP},
18461de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"sctp",      IPPROTO_SCTP},
18471de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udp",       IPPROTO_UDP},
18481de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udplite",   IPPROTO_UDPLITE},
18491de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmp",      IPPROTO_ICMP},
18501de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmpv6",    IPPROTO_ICMPV6},
18511de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-icmp", IPPROTO_ICMPV6},
18521de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"esp",       IPPROTO_ESP},
18531de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ah",        IPPROTO_AH},
18541de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-mh",   IPPROTO_MH},
18551de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"mh",        IPPROTO_MH},
18561de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"all",       0},
18571de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{NULL},
18581de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt};
18591de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
18607ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t
18611de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtxtables_parse_protocol(const char *s)
18621de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt{
186385f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	const struct protoent *pent;
186485f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	unsigned int proto, i;
18651de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
186685f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	if (xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX))
186785f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		return proto;
18681de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
186985f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	/* first deal with the special case of 'all' to prevent
187085f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	 * people from being able to redefine 'all' in nsswitch
187185f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	 * and/or provoke expensive [not working] ldap/nis/...
187285f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	 * lookups */
187385f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	if (strcmp(s, "all") == 0)
187485f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		return 0;
18751de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
187685f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	pent = getprotobyname(s);
187785f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	if (pent != NULL)
187885f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		return pent->p_proto;
1879e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso
188085f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
188185f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		if (xtables_chain_protos[i].name == NULL)
188285f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt			continue;
188385f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		if (strcmp(s, xtables_chain_protos[i].name) == 0)
188485f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt			return xtables_chain_protos[i].num;
18851de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	}
188685f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	xt_params->exit_err(PARAMETER_PROBLEM,
188785f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		"unknown protocol \"%s\" specified", s);
188885f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	return -1;
18891de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt}
1890f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1891f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardtint kernel_version;
1892f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1893f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardtvoid get_kernel_version(void)
1894f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt{
1895f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	static struct utsname uts;
1896f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	int x = 0, y = 0, z = 0;
1897f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1898f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	if (uname(&uts) == -1) {
1899f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt		fprintf(stderr, "Unable to retrieve kernel version.\n");
1900f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt		xtables_free_opts(1);
1901f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt		exit(1);
1902f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	}
1903f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1904f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
1905f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	kernel_version = LINUX_VERSION(x, y, z);
1906f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt}
1907