xtables.c revision a96166c24eaac1c91bed4815c09e91733409d888
15208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI/*
25208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * (C) 2000-2006 by the netfilter coreteam <coreteam@netfilter.org>:
35208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *
45208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	This program is free software; you can redistribute it and/or modify
55208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	it under the terms of the GNU General Public License as published by
65208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	the Free Software Foundation; either version 2 of the License, or
75208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	(at your option) any later version.
85208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *
95208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	This program is distributed in the hope that it will be useful,
105208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	but WITHOUT ANY WARRANTY; without even the implied warranty of
115208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
125208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	GNU General Public License for more details.
135208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *
145208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	You should have received a copy of the GNU General Public License
155208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	along with this program; if not, write to the Free Software
165208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
175208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI */
183c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#include "config.h"
19d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt#include <ctype.h>
203dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <errno.h>
210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <fcntl.h>
220b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt#include <inttypes.h>
2304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI#include <netdb.h>
24aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt#include <stdarg.h>
25cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt#include <stdbool.h>
263dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdio.h>
273dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdlib.h>
280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <string.h>
290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <unistd.h>
300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#include <sys/socket.h>
310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/stat.h>
32b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski#include <sys/statfs.h>
330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/types.h>
34f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt#include <sys/utsname.h>
350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/wait.h>
3608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#include <arpa/inet.h>
373c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#if defined(HAVE_LINUX_MAGIC_H)
383c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#	include <linux/magic.h> /* for PROC_SUPER_MAGIC */
393c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#elif defined(HAVE_LINUX_PROC_FS_H)
403c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#	include <linux/proc_fs.h>	/* Linux 2.4 */
4141a9b481693b4c43c16d0588cc558dd455168af0Jan Engelhardt#else
4241a9b481693b4c43c16d0588cc558dd455168af0Jan Engelhardt#	define PROC_SUPER_MAGIC	0x9fa0
433c871010888e1479ef8fca2048485b979ec2661aJan Engelhardt#endif
443dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
455208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI#include <xtables.h>
464e41854423b529d3107c23b85434d50a75d08057Jan Engelhardt#include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */
4777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt#include <linux/netfilter_ipv4/ip_tables.h>
4877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt#include <linux/netfilter_ipv6/ip6_tables.h>
49ef18e8147903885708d1c264904129af4fb636d6Jan Engelhardt#include <libiptc/libxtc.h>
503dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
515a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#ifndef NO_SHARED_LIBS
525a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#include <dlfcn.h>
535a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#endif
54c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */
55c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IPT_SO_GET_REVISION_MATCH	(IPT_BASE_CTL + 2)
56c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IPT_SO_GET_REVISION_TARGET	(IPT_BASE_CTL + 3)
57c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#endif
58c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */
59c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IP6T_SO_GET_REVISION_MATCH	68
60c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#	define IP6T_SO_GET_REVISION_TARGET	69
61c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#endif
6270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim#include <getopt.h>
63aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "iptables/internal.h"
641e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt#include "xshared.h"
655a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger
660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#define NPROTO	255
670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
680b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#ifndef PROC_SYS_MODPROBE
690b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
700b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#endif
710b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
7237911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski/* we need this for ip6?tables-restore.  ip6?tables-restore.c sets line to the
7337911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski * current line of the input file, in order  to give a more precise error
7437911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski * message.  ip6?tables itself doesn't need this, so it is initialized to the
7537911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski * magic number of -1 */
7637911de507d0597980ad218a044a482501a21b01Maciej Zenczykowskiint line = -1;
7737911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski
788b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
798b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim
8040a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salimstruct xtables_globals *xt_params = NULL;
8140a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim
828b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...)
8340a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim{
8440a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	va_list args;
8540a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim
8640a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	va_start(args, msg);
8740a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version);
8840a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	vfprintf(stderr, msg, args);
8940a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	va_end(args);
9040a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	fprintf(stderr, "\n");
9140a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim	exit(status);
9240a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim}
9340a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim
94600f38db82548a683775fd89b6e136673e924097Jan Engelhardtvoid xtables_free_opts(int unused)
9584c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim{
96df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt	if (xt_params->opts != xt_params->orig_opts) {
9759e8114c6792242e80785f4461d5e663fb9a3d64Jan Engelhardt		free(xt_params->opts);
98df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt		xt_params->opts = NULL;
99df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt	}
10084c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim}
10184c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim
102600f38db82548a683775fd89b6e136673e924097Jan Engelhardtstruct option *xtables_merge_options(struct option *orig_opts,
103600f38db82548a683775fd89b6e136673e924097Jan Engelhardt				     struct option *oldopts,
10470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim				     const struct option *newopts,
10570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim				     unsigned int *option_offset)
10670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim{
107600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	unsigned int num_oold = 0, num_old = 0, num_new = 0, i;
108600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	struct option *merge, *mp;
10970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
11070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	if (newopts == NULL)
11170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim		return oldopts;
11270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
113600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ;
114600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	if (oldopts != NULL)
115600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		for (num_old = 0; oldopts[num_old].name; num_old++) ;
11670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	for (num_new = 0; newopts[num_new].name; num_new++) ;
11770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
1181dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	/*
1191dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 * Since @oldopts also has @orig_opts already (and does so at the
1201dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 * start), skip these entries.
1211dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	 */
1221dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	oldopts += num_oold;
1231dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt	num_old -= num_oold;
1241dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt
125600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1));
126600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	if (merge == NULL)
127600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		return NULL;
128600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
129600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Let the base options -[ADI...] have precedence over everything */
130600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(merge, orig_opts, sizeof(*mp) * num_oold);
131600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	mp = merge + num_oold;
132600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
133600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Second, the new options */
1341e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt	xt_params->option_offset += XT_OPTION_OFFSET_SCALE;
13570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	*option_offset = xt_params->option_offset;
136600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(mp, newopts, sizeof(*mp) * num_new);
13770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
138600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	for (i = 0; i < num_new; ++i, ++mp)
139600f38db82548a683775fd89b6e136673e924097Jan Engelhardt		mp->val += *option_offset;
140600f38db82548a683775fd89b6e136673e924097Jan Engelhardt
141600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Third, the old options */
142600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memcpy(mp, oldopts, sizeof(*mp) * num_old);
143600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	mp += num_old;
144600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	xtables_free_opts(0);
14570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
146600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	/* Clear trailing entry */
147600f38db82548a683775fd89b6e136673e924097Jan Engelhardt	memset(mp, 0, sizeof(*mp));
14870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim	return merge;
14970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim}
15070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim
15177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv4 = {
15277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.kmod          = "ip_tables",
153b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	.proc_exists   = "/proc/net/ip_tables_names",
15477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.libprefix     = "libipt_",
15577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.family	       = NFPROTO_IPV4,
15677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.ipproto       = IPPROTO_IP,
15777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_match  = IPT_SO_GET_REVISION_MATCH,
15877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_target = IPT_SO_GET_REVISION_TARGET,
15977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
16077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
16177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv6 = {
16277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.kmod          = "ip6_tables",
163b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	.proc_exists   = "/proc/net/ip6_tables_names",
16477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.libprefix     = "libip6t_",
16577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.family        = NFPROTO_IPV6,
16677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.ipproto       = IPPROTO_IPV6,
16777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_match  = IP6T_SO_GET_REVISION_MATCH,
16877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	.so_rev_target = IP6T_SO_GET_REVISION_TARGET,
16977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt};
17077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
171aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtconst struct xtables_afinfo *afinfo;
17277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
17339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt/* Search path for Xtables .so files */
17439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtstatic const char *xtables_libdir;
1750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1760b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */
177c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtconst char *xtables_modprobe_program;
1780b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1792c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski/* Keep track of matches/targets pending full registration: linked lists. */
1802c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistruct xtables_match *xtables_pending_matches;
1812c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistruct xtables_target *xtables_pending_targets;
1822c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
1832c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski/* Keep track of fully registered external matches/targets: linked lists. */
1840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches;
1850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets;
1860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1872c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski/* Fully register a match/target which was previously partially registered. */
1882c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_match(struct xtables_match *me);
1892c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_target(struct xtables_target *me);
1902c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
19139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtvoid xtables_init(void)
19239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt{
19339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = getenv("XTABLES_LIBDIR");
19439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	if (xtables_libdir != NULL)
19539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		return;
19639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = getenv("IPTABLES_LIB_DIR");
19739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	if (xtables_libdir != NULL) {
19839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, "
19939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		        "use XTABLES_LIBDIR.\n");
20039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		return;
20139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	}
202ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	/*
203ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * Well yes, IP6TABLES_LIB_DIR is of lower priority over
204ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok
205ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * for these env vars are deprecated anyhow, and in light of the
206ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * (shared) libxt_*.so files, makes less sense to have
207ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR.
208ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	 */
209ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	xtables_libdir = getenv("IP6TABLES_LIB_DIR");
210ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	if (xtables_libdir != NULL) {
211ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, "
212ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		        "use XTABLES_LIBDIR.\n");
213ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt		return;
214ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt	}
21539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt	xtables_libdir = XTABLES_LIBDIR;
21639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt}
21739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt
21877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtvoid xtables_set_nfproto(uint8_t nfproto)
21977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt{
22077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	switch (nfproto) {
22177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	case NFPROTO_IPV4:
22277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		afinfo = &afinfo_ipv4;
22377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		break;
22477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	case NFPROTO_IPV6:
22577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		afinfo = &afinfo_ipv6;
22677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		break;
22777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	default:
22877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n",
22977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		        __func__);
23077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	}
23177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}
23277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt
233630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt/**
2347e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * xtables_set_params - set the global parameters used by xtables
2357e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp:	input xtables_globals structure
2367e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim *
2377e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * The app is expected to pass a valid xtables_globals data-filled
2387e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * with proper values
2397e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp cannot be NULL
2407e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim *
2417e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * Returns -1 on failure to set and 0 on success
2427e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim */
2437e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_set_params(struct xtables_globals *xtp)
2447e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{
2457e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	if (!xtp) {
2467e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		fprintf(stderr, "%s: Illegal global params\n",__func__);
2477e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		return -1;
2487e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	}
2497e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2507e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xt_params = xtp;
2517e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2527e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	if (!xt_params->exit_err)
2537e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim		xt_params->exit_err = basic_exit_err;
2547e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2557e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	return 0;
2567e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim}
2577e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2587e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto)
2597e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{
2607e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xtables_init();
2617e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	xtables_set_nfproto(nfproto);
2627e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim	return xtables_set_params(xtp);
2637e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim}
2647e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim
2657e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim/**
266630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt * xtables_*alloc - wrappers that exit on failure
267630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt */
268630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_calloc(size_t count, size_t size)
2693dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
2703dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
2713dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2723dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = calloc(count, size)) == NULL) {
2733dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: calloc failed");
2743dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
2753dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
2763dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2773dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
2783dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
2793dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
280630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_malloc(size_t size)
2813dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
2823dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
2833dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2843dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = malloc(size)) == NULL) {
2853dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: malloc failed");
2863dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
2873dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
2883dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
2893dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
2903dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
2910b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
292332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid *xtables_realloc(void *ptr, size_t size)
293332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
294332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	void *p;
295332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
296332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	if ((p = realloc(ptr, size)) == NULL) {
297332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		perror("ip[6]tables: realloc failed");
298332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		exit(1);
299332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
300332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
301332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	return p;
302332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
303332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
3040b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void)
3050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
3060b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int procfile;
3070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *ret;
3080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ	1024
3100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
3110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (procfile < 0)
3120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return NULL;
313a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) {
314a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		fprintf(stderr, "Could not set close on exec: %s\n",
315a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski			strerror(errno));
316a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		exit(1);
317a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	}
3180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
319371cea299f0b2eb100b9fc9fb99089640d2d606fJan Engelhardt	ret = malloc(PROCFILE_BUFSIZ);
3200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (ret) {
3210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		memset(ret, 0, PROCFILE_BUFSIZ);
3220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
3230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case -1: goto fail;
3240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
3250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
3260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (ret[strlen(ret)-1]=='\n')
3270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			ret[strlen(ret)-1]=0;
3280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		close(procfile);
3290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return ret;
3300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail:
3320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(ret);
3330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	close(procfile);
3340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return NULL;
3350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
337c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_insmod(const char *modname, const char *modprobe, bool quiet)
3380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
3390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *buf = NULL;
3400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *argv[4];
3410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int status;
3420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	/* If they don't explicitly set it, read out of kernel */
3440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (!modprobe) {
3450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		buf = get_modprobe();
3460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (!buf)
3470b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			return -1;
3480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		modprobe = buf;
3490b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
351c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	/*
352c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * Need to flush the buffer, or the child may output it again
353c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 * when switching the program thru execv.
354c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	 */
355c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt	fflush(stdout);
356c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt
35794aa2ea67d7b8a669e8541f094661a1dc89722a3Jan Engelhardt	switch (vfork()) {
3580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case 0:
3590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[0] = (char *)modprobe;
3600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[1] = (char *)modname;
3610b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (quiet) {
3620b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = "-q";
3630b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3640b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		} else {
3650b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = NULL;
3660b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
3670b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
3680b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		execv(argv[0], argv);
3690b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3700b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		/* not usually reached */
3710b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		exit(1);
3720b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case -1:
373f53710b16c2bae1843c3f5fee390f496dfa82526Jiri Popelka		free(buf);
3740b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return -1;
3750b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3760b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	default: /* parent */
3770b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		wait(&status);
3780b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
3790b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
3800b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(buf);
3810b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
3820b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return 0;
3830b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return -1;
3840b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
3850b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
386b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski/* return true if a given file exists within procfs */
387b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowskistatic bool proc_file_exists(const char *filename)
388b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski{
389b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	struct stat s;
390b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	struct statfs f;
391b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski
392b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (lstat(filename, &s))
393b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return false;
394b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (!S_ISREG(s.st_mode))
395b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return false;
396b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (statfs(filename, &f))
397b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return false;
398b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (f.f_type != PROC_SUPER_MAGIC)
399b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return false;
400b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	return true;
401b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski}
402b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski
403c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_load_ko(const char *modprobe, bool quiet)
4040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
405c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	static bool loaded = false;
406b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	int ret;
4070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
408b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (loaded)
409b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return 0;
410b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski
411b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (proc_file_exists(afinfo->proc_exists)) {
412b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		loaded = true;
413b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		return 0;
414b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	};
415b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski
416b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	ret = xtables_insmod(afinfo->kmod, modprobe, quiet);
417b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski	if (ret == 0)
418b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski		loaded = true;
4190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ret;
4210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
4220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4235f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt/**
4245f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * xtables_strtou{i,l} - string to number conversion
4255f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @s:	input string
4265f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @end:	like strtoul's "end" pointer
4275f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @value:	pointer for result
4285f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @min:	minimum accepted value
4295f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @max:	maximum accepted value
4305f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt *
4315f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * If @end is NULL, we assume the caller wants a "strict strtoul", and hence
4325f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * "15a" is rejected.
4335f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * In either case, the value obtained is compared for min-max compliance.
4345f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Base is always 0, i.e. autodetect depending on @s.
435cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *
4365f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Returns true/false whether number was accepted. On failure, *value has
4375f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * undefined contents.
438cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */
4390b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardtbool xtables_strtoul(const char *s, char **end, uintmax_t *value,
4400b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt                     uintmax_t min, uintmax_t max)
441cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
4420b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt	uintmax_t v;
443d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt	const char *p;
444cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	char *my_end;
445cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
446cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	errno = 0;
447d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt	/* Since strtoul allows leading minus, we have to check for ourself. */
448d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt	for (p = s; isspace(*p); ++p)
449d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt		;
450d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt	if (*p == '-')
451d61b02fbbbe7f6e643aad8649c8559c175c68c52Jan Engelhardt		return false;
4520b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt	v = strtoumax(s, &my_end, 0);
453cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (my_end == s)
454cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return false;
455cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (end != NULL)
456cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*end = my_end;
457cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
458cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (errno != ERANGE && min <= v && (max == 0 || v <= max)) {
459cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (value != NULL)
460cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			*value = v;
461cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (end == NULL)
462cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			return *my_end == '\0';
463cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return true;
464cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	}
465cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
466cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return false;
467cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
468cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4695f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoui(const char *s, char **end, unsigned int *value,
4705f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt                     unsigned int min, unsigned int max)
471cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
4720b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt	uintmax_t v;
473cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	bool ret;
474cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
4755f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	ret = xtables_strtoul(s, end, &v, min, max);
476cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (value != NULL)
477cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*value = v;
478cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return ret;
479cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
480cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
481aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtint xtables_service_to_port(const char *name, const char *proto)
48204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
48304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	struct servent *service;
48404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
48504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((service = getservbyname(name, proto)) != NULL)
48604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		return ntohs((unsigned short) service->s_port);
48704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
48804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return -1;
48904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
49004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4917ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t xtables_parse_port(const char *port, const char *proto)
49204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
4937a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt	unsigned int portnum;
49404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4955f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) ||
496aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt	    (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1)
497213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt		return portnum;
49804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
4998b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM,
50004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		   "invalid port/service `%s' specified", port);
50104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
50204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
503aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtvoid xtables_parse_interface(const char *arg, char *vianame,
504aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt			     unsigned char *mask)
50504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
506fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	unsigned int vialen = strlen(arg);
50704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned int i;
50804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
50904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(mask, 0, IFNAMSIZ);
51004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(vianame, 0, IFNAMSIZ);
51104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
51204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if (vialen + 1 > IFNAMSIZ)
5138b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
51404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   "interface name `%s' must be shorter than IFNAMSIZ"
51504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   " (%i)", arg, IFNAMSIZ-1);
51604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
51704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	strcpy(vianame, arg);
518fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt	if (vialen == 0)
5192ca6273c73b42e8c74afd5f8b1fe10c5c93ce363Richard Weinberger		return;
52004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	else if (vianame[vialen - 1] == '+') {
52104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen - 1);
52204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Don't remove `+' here! -HW */
52304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	} else {
52404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Include nul-terminator in match */
52504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen + 1);
52604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		for (i = 0; vianame[i]; i++) {
527fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			if (vianame[i] == '/' ||
528fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt			    vianame[i] == ' ') {
529aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann				fprintf(stderr,
530aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					"Warning: weird character in interface"
531fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt					" `%s' ('/' and ' ' are not allowed by the kernel).\n",
532aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					vianame);
53304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI				break;
53404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			}
53504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		}
53604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	}
53704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
53804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
539cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS
540927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardtstatic void *load_extension(const char *search_path, const char *af_prefix,
54121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt    const char *name, bool is_target)
54221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{
543927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt	const char *all_prefixes[] = {"libxt_", af_prefix, NULL};
544927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt	const char **prefix;
54521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	const char *dir = search_path, *next;
54621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	void *ptr = NULL;
54721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	struct stat sb;
54821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	char path[256];
54921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
55021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	do {
55121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		next = strchr(dir, ':');
55221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		if (next == NULL)
55321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			next = dir + strlen(dir);
55421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
555927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt		for (prefix = all_prefixes; *prefix != NULL; ++prefix) {
556927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			snprintf(path, sizeof(path), "%.*s/%s%s.so",
557927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			         (unsigned int)(next - dir), dir,
558927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			         *prefix, name);
559927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt
560927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (stat(path, &sb) != 0) {
561927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				if (errno == ENOENT)
562927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt					continue;
563927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				fprintf(stderr, "%s: %s\n", path,
564927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt					strerror(errno));
565927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				return NULL;
566927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			}
567927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (dlopen(path, RTLD_NOW) == NULL) {
568927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				fprintf(stderr, "%s: %s\n", path, dlerror());
569927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				break;
570927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			}
57121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
57221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			if (is_target)
5732338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_target(name, XTF_DONT_LOAD);
57421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt			else
5752338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				ptr = xtables_find_match(name,
5762338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				      XTF_DONT_LOAD, NULL);
57721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
578927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			if (ptr != NULL)
579927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				return ptr;
58021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
581927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			fprintf(stderr, "%s: no \"%s\" extension found for "
582927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				"this protocol\n", path, name);
583927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			errno = ENOENT;
584927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt			return NULL;
585927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt		}
58621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt		dir = next + 1;
58721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	} while (*next != '\0');
58821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
58921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt	return NULL;
59021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt}
591cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif
59221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt
5932338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_match *
5942338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_match(const char *name, enum xtables_tryload tryload,
5952338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		   struct xtables_rule_match **matches)
5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
5972c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	struct xtables_match **dptr;
5980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match *ptr;
5990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	const char *icmp6 = "icmp6";
6000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6010cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(name) >= XT_EXTENSION_MAXNAMELEN)
60221d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt		xtables_error(PARAMETER_PROBLEM,
60321d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt			   "Invalid match name \"%s\" (%u chars max)",
6040cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt			   name, XT_EXTENSION_MAXNAMELEN - 1);
60521d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt
6060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* This is ugly as hell. Nonetheless, there is no way of changing
6070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	 * this without hurting backwards compatibility */
6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if ( (strcmp(name,"icmpv6") == 0) ||
6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"ipv6-icmp") == 0) ||
6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"icmp6") == 0) )
6110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = icmp6;
6120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6132c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	/* Trigger delayed initialization */
6142c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	for (dptr = &xtables_pending_matches; *dptr; ) {
6152c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		if (strcmp(name, (*dptr)->name) == 0) {
6162c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			ptr = *dptr;
6172c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			*dptr = (*dptr)->next;
6182c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			ptr->next = NULL;
6192c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			xtables_fully_register_pending_match(ptr);
6202c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		} else {
6212c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			dptr = &((*dptr)->next);
6222c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		}
6232c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	}
6242c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
6250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_matches; ptr; ptr = ptr->next) {
6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0) {
6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			struct xtables_match *clone;
6280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* First match of this type: */
6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (ptr->m == NULL)
6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				break;
6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Second and subsequent clones */
634630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt			clone = xtables_malloc(sizeof(struct xtables_match));
6350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			memcpy(clone, ptr, sizeof(struct xtables_match));
6363eab786d6a687187556c92b3dc0f0664d8352471Jan Engelhardt			clone->udata = NULL;
6370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->mflags = 0;
6380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* This is a clone: */
6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->next = clone;
6400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = clone;
6420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
6430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
6440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
6472338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
64877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
64939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, false);
650170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
6512338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
6528b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
6530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load match `%s':%s\n",
654927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				   name, strerror(errno));
6550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
6570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
6582338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
6590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
6600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
6610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
6620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6632338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) {
6648b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
6650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find match `%s'\n", name);
6660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
6680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && matches) {
6700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match **i;
6710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match *newentry;
6720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
673630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		newentry = xtables_malloc(sizeof(struct xtables_rule_match));
6740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = matches; *i; i = &(*i)->next) {
6760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (strcmp(name, (*i)->match->name) == 0)
6772338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt				(*i)->completed = true;
6780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
6790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->match = ptr;
6802338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		newentry->completed = false;
6810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->next = NULL;
6820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = newentry;
6830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
6860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
6870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6882338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_target *
6892338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_target(const char *name, enum xtables_tryload tryload)
6900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
6912c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	struct xtables_target **dptr;
6920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *ptr;
6930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Standard target? */
6950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(name, "") == 0
6960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_ACCEPT) == 0
6970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_DROP) == 0
6980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_QUEUE) == 0
6990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_RETURN) == 0)
7000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = "standard";
7010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7022c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	/* Trigger delayed initialization */
7032c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	for (dptr = &xtables_pending_targets; *dptr; ) {
7042c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		if (strcmp(name, (*dptr)->name) == 0) {
7052c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			ptr = *dptr;
7062c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			*dptr = (*dptr)->next;
7072c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			ptr->next = NULL;
7082c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			xtables_fully_register_pending_target(ptr);
7092c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		} else {
7102c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski			dptr = &((*dptr)->next);
7112c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski		}
7122c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	}
7132c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
7140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_targets; ptr; ptr = ptr->next) {
7150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0)
7160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
7170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
7202338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
72177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt		ptr = load_extension(xtables_libdir, afinfo->libprefix,
72239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt		      name, true);
723170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
7242338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
7258b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim			xt_params->exit_err(PARAMETER_PROBLEM,
7260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load target `%s':%s\n",
727927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt				   name, strerror(errno));
7280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
7300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
7312338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt		if (tryload != XTF_DONT_LOAD)
7320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
7330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
7340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
7350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
736854d2d9bd7556cfd8a676b0bc18dc059a9a2dd25Peter Volkov	if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) {
7378b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
7380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find target `%s'\n", name);
7390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
7410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr)
7430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		ptr->used = 1;
7440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
7460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
7470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7487ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_revision(const char *name, uint8_t revision, int opt)
7490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
7500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xt_get_revision rev;
7510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	socklen_t s = sizeof(rev);
7520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	int max_rev, sockfd;
7530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
75477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);
7550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (sockfd < 0) {
756df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		if (errno == EPERM) {
757df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			/* revision 0 is always supported. */
758df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			if (revision != 0)
759e1639b0bc28420ca01d733749c8db16d5a3fbd0cJan Engelhardt				fprintf(stderr, "%s: Could not determine whether "
760df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"revision %u is supported, "
761df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"assuming it is.\n",
762e1639b0bc28420ca01d733749c8db16d5a3fbd0cJan Engelhardt					name, revision);
763df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			return 1;
764df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		}
7650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "Could not open socket to kernel: %s\n",
7660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			strerror(errno));
7670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
7680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
770a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) {
771a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		fprintf(stderr, "Could not set close on exec: %s\n",
772a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski			strerror(errno));
773a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski		exit(1);
774a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski	}
775a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski
776c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt	xtables_load_ko(xtables_modprobe_program, true);
7770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
7780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	strcpy(rev.name, name);
7790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	rev.revision = revision;
7800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
78177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s);
7820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (max_rev < 0) {
7830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Definitely don't support this? */
7840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (errno == ENOENT || errno == EPROTONOSUPPORT) {
7850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
7860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return 0;
7870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else if (errno == ENOPROTOOPT) {
7880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
7890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Assume only revision 0 support (old kernel) */
7900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return (revision == 0);
7910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else {
7920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr, "getsockopt failed strangely: %s\n",
7930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				strerror(errno));
7940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
7950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
7960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
7970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	close(sockfd);
7980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return 1;
7990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
8000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8027ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_match_revision(const char *name, uint8_t revision)
8030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
80477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_match);
8050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
8060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8077ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_target_revision(const char *name, uint8_t revision)
8080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
80977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	return compatible_revision(name, revision, afinfo->so_rev_target);
8100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
8110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
812dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardtstatic void xtables_check_options(const char *name, const struct option *opt)
813dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt{
814dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	for (; opt->name != NULL; ++opt)
815dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) {
816dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			fprintf(stderr, "%s: Extension %s uses invalid "
817dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			        "option value %d\n",xt_params->program_name,
818dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			        name, opt->val);
819dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt			exit(1);
820dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		}
821dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt}
822dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
8230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me)
8240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
825c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
826c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: match %s<%u> is missing a version\n",
827c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
828c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
829c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
830dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
831dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
832dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
8335dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
834dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
8350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8380cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
839281439ba6b96b729ef1400a49ec53eda298bb9f8Li Yewang		fprintf(stderr, "%s: match `%s' has invalid name\n",
8405dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
8450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
8460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: match %s has invalid protocol family\n",
8475dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
8480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
8490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
851aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (me->x6_options != NULL)
852aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_option_metavalidate(me->name, me->x6_options);
853dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	if (me->extra_opts != NULL)
854dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		xtables_check_options(me->name, me->extra_opts);
855dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
8560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested match */
85777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
8580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
8590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8602c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	/* place on linked list of matches pending full registration */
8612c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	me->next = xtables_pending_matches;
8622c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	xtables_pending_matches = me;
8632c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski}
8642c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
8652c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_match(struct xtables_match *me)
8662c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski{
8672c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	struct xtables_match **i, *old;
8682c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
8692338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
8700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
87123545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision &&
87223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		    old->family == me->family) {
8730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
8740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: match `%s' already registered.\n",
8755dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
8760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
8770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
8780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
8800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_match_revision(old->name, old->revision)
8810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
8820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
88423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new match can be used. */
8850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_match_revision(me->name, me->revision))
8860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
8870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
88823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
88923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision && me->family == AF_UNSPEC)
89023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt			return;
89123545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt
8920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
8930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
8940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
8950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
8960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
8970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
8980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
8995dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
9005dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
9010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Append to list. */
9050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (i = &xtables_matches; *i; i = &(*i)->next);
9060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = NULL;
9070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	*i = me;
9080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->m = NULL;
9100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->mflags = 0;
9110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
9120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9139a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_matches(struct xtables_match *match, unsigned int n)
9149a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
9159a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
9169a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_match(&match[--n]);
9179a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
9189a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
9199a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
9200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me)
9210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
922c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	if (me->version == NULL) {
923c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
924c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		        xt_params->program_name, me->name, me->revision);
925c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt		exit(1);
926c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt	}
927dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt	if (strcmp(me->version, XTABLES_VERSION) != 0) {
928dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
929dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt		        "but \"%s\" is required.\n",
9305dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name,
931dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt			me->version, XTABLES_VERSION);
9320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9350cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
9360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
9375dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
9380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
9420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
9430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: target %s has invalid protocol family\n",
9445dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim			xt_params->program_name, me->name);
9450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
9460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
948aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (me->x6_options != NULL)
949aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_option_metavalidate(me->name, me->x6_options);
950dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt	if (me->extra_opts != NULL)
951dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt		xtables_check_options(me->name, me->extra_opts);
952dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt
9530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested target */
95477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt	if (me->family != afinfo->family && me->family != AF_UNSPEC)
9550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
9560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9572c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	/* place on linked list of targets pending full registration */
9582c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	me->next = xtables_pending_targets;
9592c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	xtables_pending_targets = me;
9602c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski}
9612c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
9622c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_target(struct xtables_target *me)
9632c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski{
9642c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski	struct xtables_target *old;
9652c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski
9662338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt	old = xtables_find_target(me->name, XTF_DURING_LOAD);
9670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
9680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_target **i;
9690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
97023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision &&
97123545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		    old->family == me->family) {
9720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
9730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: target `%s' already registered.\n",
9745dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim				xt_params->program_name, me->name);
9750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
9760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
9770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
9790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_target_revision(old->name, old->revision)
9800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
9810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
9820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
98323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* See if new target can be used. */
9840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_target_revision(me->name, me->revision))
9850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
9860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
98723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
98823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt		if (old->revision == me->revision && me->family == AF_UNSPEC)
98923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt			return;
99023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt
9910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
9920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
9930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
9940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
9950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
9960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
9970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
9985dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        xt_params->program_name, me->name,
9995dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim		        (unsigned int)me->size);
10000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
10010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
10020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
10030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Prepend to list. */
10040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = xtables_targets;
10050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	xtables_targets = me;
10060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->t = NULL;
10070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->tflags = 0;
10080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
1009aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
10109a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_targets(struct xtables_target *target, unsigned int n)
10119a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{
10129a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	do {
10139a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt		xtables_register_target(&target[--n]);
10149a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt	} while (n > 0);
10159a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt}
10169a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt
1017a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt/**
1018a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * xtables_param_act - act on condition
1019a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @status:	a constant from enum xtables_exittype
1020a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1021a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONLY_ONCE: print error message that option may only be used once.
1022a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name (e.g. "mark")
1023a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2(...):	option in conflict (e.g. "--mark")
1024a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3(...):	condition to match on (see extensions/ for examples)
1025a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1026a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_NO_INVERT: option does not support inversion
1027a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
1028a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option in conflict
1029a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		condition to match on
1030a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1031a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_BAD_VALUE: bad value for option
1032a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
1033a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2:		option with which the problem occured (e.g. "--mark")
1034a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3:		string the user passed in (e.g. "99999999999999")
1035a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1036a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONE_ACTION: two mutually exclusive actions have been specified
1037a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1:		module name
1038a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt *
1039a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * Displays an error message and exits the program.
1040a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt */
1041a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardtvoid xtables_param_act(unsigned int status, const char *p1, ...)
1042aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{
1043aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	const char *p2, *p3;
1044aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_list args;
1045aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	bool b;
1046aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
1047aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_start(args, p1);
1048aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
1049aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	switch (status) {
1050a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONLY_ONCE:
1051aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
1052aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
1053d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		if (!b) {
1054d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka			va_end(args);
1055aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
1056d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		}
10578b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1058aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option may only be specified once",
1059aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2);
1060aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1061a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_NO_INVERT:
1062aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
1063aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b  = va_arg(args, unsigned int);
1064d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		if (!b) {
1065d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka			va_end(args);
1066aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
1067d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		}
10688b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1069aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: \"%s\" option cannot be inverted", p1, p2);
1070aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1071a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_BAD_VALUE:
1072aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p2 = va_arg(args, const char *);
1073aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		p3 = va_arg(args, const char *);
10748b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1075aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: Bad value for \"%s\" option: \"%s\"",
1076aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           p1, p2, p3);
1077aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1078a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt	case XTF_ONE_ACTION:
1079aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		b = va_arg(args, unsigned int);
1080d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		if (!b) {
1081d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka			va_end(args);
1082aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt			return;
1083d0101690d9ae347d8a8ee9e340c5db72480046a3Jiri Popelka		}
10848b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1085aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		           "%s: At most one action is possible", p1);
1086aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1087aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	default:
10888b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(status, p1, args);
1089aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt		break;
1090aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	}
1091aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt
1092aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt	va_end(args);
1093aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt}
109408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1095e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp)
109608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
109708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[20];
109808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const unsigned char *bytep = (const void *)&addrp->s_addr;
109908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
110008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
110108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
110208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
110308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
110408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr)
110508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
110608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct hostent *host;
110708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
110808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET);
110908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (host == NULL)
111008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
111108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
111208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return host->h_name;
111308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
111408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
111508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr)
111608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
111708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct netent *net;
111808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
111908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL)
112008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return net->n_name;
112108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
112208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return NULL;
112308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
112408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1125e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr)
112608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
112708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
112808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
112908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ipaddr_to_host(addr)) != NULL ||
113008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	    (name = ipaddr_to_network(addr)) != NULL)
113108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
113208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1133e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ipaddr_to_numeric(addr);
113408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
113508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1136a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayusoint xtables_ipmask_to_cidr(const struct in_addr *mask)
113708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
113808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t maskaddr, bits;
113908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int i;
114008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
114108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	maskaddr = ntohl(mask->s_addr);
1142a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	/* shortcut for /32 networks */
114308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (maskaddr == 0xFFFFFFFFL)
1144a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return 32;
114508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
114608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	i = 32;
114708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	bits = 0xFFFFFFFEL;
114808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (--i >= 0 && maskaddr != bits)
114908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		bits <<= 1;
115008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (i >= 0)
1151a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return i;
1152a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso
1153a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	/* this mask cannot be converted to CIDR notation */
1154a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	return -1;
1155a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso}
1156a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso
1157a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayusoconst char *xtables_ipmask_to_numeric(const struct in_addr *mask)
1158a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso{
1159a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	static char buf[20];
1160a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	uint32_t cidr;
1161a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso
1162a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	cidr = xtables_ipmask_to_cidr(mask);
1163a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	if (cidr < 0) {
116408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		/* mask was not a decent combination of 1's and 0's */
1165e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
1166a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return buf;
1167a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	} else if (cidr == 32) {
1168a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		/* we don't want to see "/32" */
1169a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso		return "";
1170a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	}
117108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1172a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	sprintf(buf, "/%d", cidr);
117308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
117408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
117508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1176bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask)
1177bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1178bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1179bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned char *addrp;
1180bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int onebyte;
1181bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[20], *p, *q;
1182bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int i;
1183bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1184bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* copy dotted string, because we need to modify it */
1185bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, dotted, sizeof(buf) - 1);
1186bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1187bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = (void *)&addr.s_addr;
1188bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1189bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	p = buf;
1190bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0; i < 3; ++i) {
1191bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if ((q = strchr(p, '.')) == NULL) {
1192bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (is_mask)
1193bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1194bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1195bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			/* autocomplete, this is a network address */
11965f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt			if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1197bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				return NULL;
1198bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1199bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			addrp[i] = onebyte;
1200bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			while (i < 3)
1201bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				addrp[++i] = 0;
1202bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1203bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return &addr;
1204bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		}
1205bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1206bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*q = '\0';
12075f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt		if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1208bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1209bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1210bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[i] = onebyte;
1211bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p = q + 1;
1212bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1213bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1214bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* we have checked 3 bytes, now we check the last one */
12155f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1216bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1217bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1218bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp[3] = onebyte;
1219bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &addr;
1220bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1221bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
12221e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted)
1223bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1224bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, false);
1225bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1226bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
12271e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipmask(const char *dotted)
1228bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1229bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return __numeric_to_ipaddr(dotted, true);
1230bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1231bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1232bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name)
1233bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1234bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr addr;
1235bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct netent *net;
1236bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1237bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((net = getnetbyname(name)) != NULL) {
1238bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (net->n_addrtype != AF_INET)
1239bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1240bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addr.s_addr = htonl(net->n_net);
1241bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &addr;
1242bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1243bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1244bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1245bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1246bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1247bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
1248bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1249bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct hostent *host;
1250bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addr;
1251bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i;
1252bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1253bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1254bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((host = gethostbyname(name)) != NULL) {
1255bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		if (host->h_addrtype != AF_INET ||
1256bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		    host->h_length != sizeof(struct in_addr))
1257bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			return NULL;
1258bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1259bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		while (host->h_addr_list[*naddr] != NULL)
1260bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			++*naddr;
126111e250ba02349cb1e34058673db3d0b54eb56c44Wes Campaigne		addr = xtables_calloc(*naddr, sizeof(struct in_addr));
1262bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (i = 0; i < *naddr; i++)
1263bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			memcpy(&addr[i], host->h_addr_list[i],
1264bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			       sizeof(struct in_addr));
1265bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1266bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1267bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1268bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1269bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1270bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1271bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *
1272bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs)
1273bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1274bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrptmp, *addrp;
1275bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
12761e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL ||
1277bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ipaddr(name)) != NULL) {
1278630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in_addr));
1279bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1280bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1281bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1282bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1283bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL)
1284bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrptmp;
1285bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
12868b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1287bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1288bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1289bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask)
1290bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1291bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in_addr maskaddr;
1292bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1293bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1294bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1295bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1296bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 32 bits */
1297bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = 0xFFFFFFFF;
1298bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1299bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
13001e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL)
1301bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* dotted_to_addr already returns a network byte order addr */
1302bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
13035f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 32))
13048b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1305bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1306bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1307bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
1308bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1309bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1310bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1311bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	maskaddr.s_addr = 0U;
1312bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1313bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1314bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1315332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
1316332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow                              struct in_addr **maskpp, unsigned int *naddrs)
1317332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
1318332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in_addr *addrp;
1319c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt	char buf[256], *p, *next;
1320332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1321332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1322332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1323332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1324332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1325332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1326332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1327332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1328332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
1329332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
1330332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1331332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1332332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1333332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count; ++i) {
13340c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt		while (isspace(*loop))
13350c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt			++loop;
1336c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		next = strchr(loop, ',');
1337c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next != NULL)
1338c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			len = next - loop;
1339332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1340332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1341c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (len > sizeof(buf) - 1)
1342c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
1343c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt				"Hostname too long");
1344332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1345332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1346332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1347332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1348332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1349332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(p + 1);
1350332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1351332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ipmask(NULL);
1352332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1353332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1354332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1355332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
1356332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((*maskpp + i)->s_addr == 0)
1357332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			/*
1358332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * A bit pointless to process multiple addresses
1359332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 * in this case...
1360332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			 */
1361332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "0.0.0.0");
1362332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1363332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ipparse_hostnetwork(buf, &n);
1364332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1365332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1366332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1367332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1368332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1369332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in_addr) * count);
1370332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1371332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1372332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1373332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1374332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1375332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1376332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1377332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1378332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1379332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1380332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1381332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1382332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ipparse_hostnetwork had allocated: */
1383332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1384c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next == NULL)
1385c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			break;
1386c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		loop = next + 1;
1387332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1388332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
13894b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt	for (i = 0; i < count; ++i)
1390332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
1391332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1392332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1393332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1394a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt/**
1395a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * xtables_ipparse_any - transform arbitrary name to in_addr
1396a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt *
1397a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * Possible inputs (pseudo regex):
1398a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * 	m{^($hostname|$networkname|$ipaddr)(/$mask)?}
1399a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname"
1400a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt */
1401a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp,
1402a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                         struct in_addr *maskp, unsigned int *naddrs)
1403bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1404bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1405bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in_addr *addrp;
1406bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1407bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1408bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1409bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf) - 1] = '\0';
1410bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1411bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1412bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(p + 1);
1413bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1414bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ipmask(NULL);
1415bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1416bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1417bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1418bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
1419bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (maskp->s_addr == 0U)
1420bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "0.0.0.0");
1421bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1422bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ipparse_hostnetwork(buf, naddrs);
1423bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1424bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1425bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp[j++].s_addr &= maskp->s_addr;
1426bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1427bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (addrp[k].s_addr == addrp[j-1].s_addr) {
1428adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				/*
1429adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * Nuke the dup by copying an address from the
1430adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * tail here, and check the current position
1431adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * again (--j).
1432adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 */
1433adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				memcpy(&addrp[--j], &addrp[--*naddrs],
1434adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				       sizeof(struct in_addr));
1435bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1436bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1437bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1438bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1439bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1440e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp)
144108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
1442cf3e52d00b7d3fedf98ef7710c337c441270d936Maciej Zenczykowski	/* 0000:0000:0000:0000:0000:0000:000.000.000.000
144308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	 * 0000:0000:0000:0000:0000:0000:0000:0000 */
144408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+1];
144508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
144608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
144708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
144808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr)
144908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
145008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char hostname[NI_MAXHOST];
145108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	struct sockaddr_in6 saddr;
145208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	int err;
145308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
145408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memset(&saddr, 0, sizeof(struct sockaddr_in6));
145508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	memcpy(&saddr.sin6_addr, addr, sizeof(*addr));
145608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	saddr.sin6_family = AF_INET6;
145708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
145808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6),
145908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	      hostname, sizeof(hostname) - 1, NULL, 0, 0);
146008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (err != 0) {
146108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
146208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		fprintf(stderr,"IP2Name: %s\n",gai_strerror(err));
146308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
146408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return NULL;
146508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
146608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
146708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG
146808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	fprintf (stderr, "\naddr2host: %s\n", hostname);
146908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif
147008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return hostname;
147108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
147208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1473e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr)
147408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
147508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	const char *name;
147608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
147708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if ((name = ip6addr_to_host(addr)) != NULL)
147808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return name;
147908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1480e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt	return xtables_ip6addr_to_numeric(addr);
148108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
148208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1483a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayusoint xtables_ip6mask_to_cidr(const struct in6_addr *k)
148408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
148508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	unsigned int bits = 0;
148608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	uint32_t a, b, c, d;
148708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
148848607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	a = ntohl(k->s6_addr32[0]);
148948607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	b = ntohl(k->s6_addr32[1]);
149048607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	c = ntohl(k->s6_addr32[2]);
149148607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt	d = ntohl(k->s6_addr32[3]);
149208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	while (a & 0x80000000U) {
149308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		++bits;
149408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a <<= 1;
149508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		a  |= (b >> 31) & 1;
149608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b <<= 1;
149708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		b  |= (c >> 31) & 1;
149808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c <<= 1;
149908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		c  |= (d >> 31) & 1;
150008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		d <<= 1;
150108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
150208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (a != 0 || b != 0 || c != 0 || d != 0)
150308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return -1;
150408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return bits;
150508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
150608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
1507e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
150808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{
150908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	static char buf[50+2];
1510a96166c24eaac1c91bed4815c09e91733409d888Pablo Neira Ayuso	int l = xtables_ip6mask_to_cidr(addrp);
151108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt
151208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	if (l == -1) {
151308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		strcpy(buf, "/");
1514e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt		strcat(buf, xtables_ip6addr_to_numeric(addrp));
151508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt		return buf;
151608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	}
151708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	sprintf(buf, "/%d", l);
151808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt	return buf;
151908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt}
1520bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
15211e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in6_addr *xtables_numeric_to_ip6addr(const char *num)
1522bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1523bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr ap;
1524bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
1525bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1526bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
1527bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &ap;
1528bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1529bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	fprintf(stderr, "\nnumeric2addr: %d\n", err);
1530bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1531bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1532bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1533bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1534bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1535bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr)
1536bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
15372ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	struct in6_addr *addr;
1538bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct addrinfo hints;
15392ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	struct addrinfo *res, *p;
1540bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	int err;
15412ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne	unsigned int i;
1542bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1543bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&hints, 0, sizeof(hints));
1544bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_flags    = AI_CANONNAME;
1545bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_family   = AF_INET6;
1546bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	hints.ai_socktype = SOCK_RAW;
1547bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1548bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	*naddr = 0;
1549bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
1550bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1551bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr,"Name2IP: %s\n",gai_strerror(err));
1552bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
1553bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return NULL;
1554bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
15552ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		/* Find length of address chain */
15562ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		for (p = res; p != NULL; p = p->ai_next)
15572ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			++*naddr;
1558bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG
1559bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		fprintf(stderr, "resolved: len=%d  %s ", res->ai_addrlen,
156030290aea009cf3fd76f27336fb4370be3467c4daPatrick McHardy		        xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr));
1561bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif
15622ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		/* Copy each element of the address chain */
15632ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		addr = xtables_calloc(*naddr, sizeof(struct in6_addr));
15642ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne		for (i = 0, p = res; p != NULL; p = p->ai_next)
15652ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			memcpy(&addr[i++],
15662ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			       &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr,
15672ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne			       sizeof(struct in6_addr));
1568bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		freeaddrinfo(res);
1569bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addr;
1570bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1571bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1572bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1573bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1574bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1575bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name)
1576bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1577bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/*	abort();*/
1578bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* TODO: not implemented yet, but the exception breaks the
1579bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	 *       name resolvation */
1580bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return NULL;
1581bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1582bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1583bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *
1584bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs)
1585bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1586bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp, *addrptmp;
1587bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
15881e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL ||
1589bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	    (addrptmp = network_to_ip6addr(name)) != NULL) {
1590630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt		addrp = xtables_malloc(sizeof(struct in6_addr));
1591bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memcpy(addrp, addrptmp, sizeof(*addrp));
1592bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*naddrs = 1;
1593bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1594bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1595bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((addrp = host_to_ip6addr(name, naddrs)) != NULL)
1596bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
1597bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
15988b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1599bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1600bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1601bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask)
1602bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
1603bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	static struct in6_addr maskaddr;
1604bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1605bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int bits;
1606bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1607bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (mask == NULL) {
1608bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		/* no mask at all defaults to 128 bits */
1609bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(&maskaddr, 0xff, sizeof maskaddr);
1610bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1611bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
16121e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt	if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL)
1613bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return addrp;
16145f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt	if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
16158b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim		xt_params->exit_err(PARAMETER_PROBLEM,
1616bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			   "invalid mask `%s' specified", mask);
1617bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if (bits != 0) {
1618bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		char *p = (void *)&maskaddr;
1619bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p, 0xff, bits / 8);
1620bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
1621bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		p[bits/8] = 0xff << (8 - (bits & 7));
1622bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		return &maskaddr;
1623bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1624bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1625bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memset(&maskaddr, 0, sizeof(maskaddr));
1626bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	return &maskaddr;
1627bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1628bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1629332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid
1630332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowxtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
1631332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		      struct in6_addr **maskpp, unsigned int *naddrs)
1632332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{
163358df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel	static const struct in6_addr zero_addr;
1634332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	struct in6_addr *addrp;
1635c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt	char buf[256], *p, *next;
1636332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	unsigned int len, i, j, n, count = 1;
1637332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	const char *loop = name;
1638332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1639332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	while ((loop = strchr(loop, ',')) != NULL) {
1640332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++count;
1641332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		++loop; /* skip ',' */
1642332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1643332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1644332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
1645332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
1646332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1647332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	loop = name;
1648332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1649332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	for (i = 0; i < count /*NB: count can grow*/; ++i) {
16500c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt		while (isspace(*loop))
16510c384449ae9511157cd9b34d73f8f4cb71123a45Jan Engelhardt			++loop;
1652c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		next = strchr(loop, ',');
1653c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next != NULL)
1654c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			len = next - loop;
1655332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		else
1656332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			len = strlen(loop);
1657c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (len > sizeof(buf) - 1)
1658c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
1659c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt				"Hostname too long");
1660332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1661332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		strncpy(buf, loop, len);
1662332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		buf[len] = '\0';
1663332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if ((p = strrchr(buf, '/')) != NULL) {
1664332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*p = '\0';
1665332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(p + 1);
1666332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1667332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			addrp = parse_ip6mask(NULL);
1668332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1669332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1670332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1671332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* if a null mask is given, the name is ignored, like in "any/0" */
167258df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel		if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0)
1673332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			strcpy(buf, "::");
1674332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1675332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		addrp = ip6parse_hostnetwork(buf, &n);
1676332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		if (n > 1) {
1677332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			count += n - 1;
1678332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*addrpp = xtables_realloc(*addrpp,
1679332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1680332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			*maskpp = xtables_realloc(*maskpp,
1681332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			          sizeof(struct in6_addr) * count);
1682332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 0; j < n; ++j)
1683332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new addr */
1684332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*addrpp + i + j, addrp + j,
1685332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1686332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			for (j = 1; j < n; ++j)
1687332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				/* for each new mask */
1688332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				memcpy(*maskpp + i + j, *maskpp + i,
1689332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow				       sizeof(*addrp));
1690332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			i += n - 1;
1691332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		} else {
1692332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1693332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		}
1694332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		/* free what ip6parse_hostnetwork had allocated: */
1695332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		free(addrp);
1696c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		if (next == NULL)
1697c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt			break;
1698c0e69db337540b22a3b3f739b1143341e7b759b7Jan Engelhardt		loop = next + 1;
1699332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	}
1700332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow	*naddrs = count;
17014b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt	for (i = 0; i < count; ++i)
1702332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow		for (j = 0; j < 4; ++j)
1703332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
1704332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow}
1705332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow
1706a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
1707a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt                          struct in6_addr *maskp, unsigned int *naddrs)
1708bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{
17099c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	static const struct in6_addr zero_addr;
1710bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	struct in6_addr *addrp;
1711bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	unsigned int i, j, k, n;
1712bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	char buf[256], *p;
1713bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1714bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	strncpy(buf, name, sizeof(buf) - 1);
1715bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	buf[sizeof(buf)-1] = '\0';
1716bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	if ((p = strrchr(buf, '/')) != NULL) {
1717bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		*p = '\0';
1718bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(p + 1);
1719bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	} else {
1720bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		addrp = parse_ip6mask(NULL);
1721bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1722bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	memcpy(maskp, addrp, sizeof(*maskp));
1723bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1724bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	/* if a null mask is given, the name is ignored, like in "any/0" */
17259c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt	if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0)
1726bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		strcpy(buf, "::");
1727bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt
1728bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs);
1729bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	n = *naddrs;
1730bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	for (i = 0, j = 0; i < n; ++i) {
1731bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < 4; ++k)
17325a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai			addrp[j].s6_addr32[k] &= maskp->s6_addr32[k];
1733bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		++j;
1734bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt		for (k = 0; k < j - 1; ++k)
1735bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
1736adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				/*
1737adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * Nuke the dup by copying an address from the
1738adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * tail here, and check the current position
1739adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 * again (--j).
1740adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				 */
1741adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				memcpy(&addrp[--j], &addrp[--*naddrs],
1742adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne				       sizeof(struct in_addr));
1743bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt				break;
1744bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt			}
1745bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt	}
1746bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt}
1747a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1748a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_save_string(const char *value)
1749a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{
1750a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char no_quote_chars[] = "_-0123456789"
1751a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"abcdefghijklmnopqrstuvwxyz"
1752a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1753a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	static const char escape_chars[] = "\"\\'";
1754a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	size_t length;
1755a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	const char *p;
1756a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
175787dc7c4c842deb1e2e3d38089ffcad9f238d98deMax Kellerman	length = strspn(value, no_quote_chars);
1758a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	if (length > 0 && value[length] == 0) {
1759a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* no quoting required */
1760a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		putchar(' ');
176173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		fputs(value, stdout);
1762a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	} else {
1763a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* there is at least one dangerous character in the
1764a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   value, which we have to quote.  Write double quotes
1765a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   around the value and escape special characters with
1766a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   a backslash */
176773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" \"");
1768a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1769a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		for (p = strpbrk(value, escape_chars); p != NULL;
1770a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		     p = strpbrk(value, escape_chars)) {
1771a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			if (p > value)
1772a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann				fwrite(value, 1, p - value, stdout);
1773a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar('\\');
1774a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			putchar(*p);
1775a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann			value = p + 1;
1776a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		}
1777a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann
1778a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		/* print the rest and finish the double quoted
1779a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		   string */
1780a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann		fputs(value, stdout);
178173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		putchar('\"');
1782a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann	}
1783a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann}
17840f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt
17851de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtconst struct xtables_pprot xtables_chain_protos[] = {
17861de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"tcp",       IPPROTO_TCP},
17871de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"sctp",      IPPROTO_SCTP},
17881de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udp",       IPPROTO_UDP},
17891de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"udplite",   IPPROTO_UDPLITE},
17901de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmp",      IPPROTO_ICMP},
17911de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"icmpv6",    IPPROTO_ICMPV6},
17921de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-icmp", IPPROTO_ICMPV6},
17931de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"esp",       IPPROTO_ESP},
17941de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ah",        IPPROTO_AH},
17951de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"ipv6-mh",   IPPROTO_MH},
17961de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"mh",        IPPROTO_MH},
17971de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{"all",       0},
17981de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	{NULL},
17991de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt};
18001de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
18017ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t
18021de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtxtables_parse_protocol(const char *s)
18031de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt{
180485f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	const struct protoent *pent;
180585f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	unsigned int proto, i;
18061de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
180785f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	if (xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX))
180885f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		return proto;
18091de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
181085f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	/* first deal with the special case of 'all' to prevent
181185f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	 * people from being able to redefine 'all' in nsswitch
181285f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	 * and/or provoke expensive [not working] ldap/nis/...
181385f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	 * lookups */
181485f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	if (strcmp(s, "all") == 0)
181585f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		return 0;
18161de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt
181785f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	pent = getprotobyname(s);
181885f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	if (pent != NULL)
181985f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		return pent->p_proto;
1820e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso
182185f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
182285f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		if (xtables_chain_protos[i].name == NULL)
182385f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt			continue;
182485f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		if (strcmp(s, xtables_chain_protos[i].name) == 0)
182585f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt			return xtables_chain_protos[i].num;
18261de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt	}
182785f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	xt_params->exit_err(PARAMETER_PROBLEM,
182885f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt		"unknown protocol \"%s\" specified", s);
182985f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt	return -1;
18301de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt}
1831f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1832f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardtint kernel_version;
1833f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1834f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardtvoid get_kernel_version(void)
1835f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt{
1836f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	static struct utsname uts;
1837f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	int x = 0, y = 0, z = 0;
1838f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1839f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	if (uname(&uts) == -1) {
1840f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt		fprintf(stderr, "Unable to retrieve kernel version.\n");
1841f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt		xtables_free_opts(1);
1842f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt		exit(1);
1843f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	}
1844f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt
1845f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
1846f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt	kernel_version = LINUX_VERSION(x, y, z);
1847f56b8a8bf4b1041cb875fd8439778f35276bdb30Jan Engelhardt}
1848