xtables.c revision 281439ba6b96b729ef1400a49ec53eda298bb9f8
1/*
2 * (C) 2000-2006 by the netfilter coreteam <coreteam@netfilter.org>:
3 *
4 *	This program is free software; you can redistribute it and/or modify
5 *	it under the terms of the GNU General Public License as published by
6 *	the Free Software Foundation; either version 2 of the License, or
7 *	(at your option) any later version.
8 *
9 *	This program is distributed in the hope that it will be useful,
10 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 *	GNU General Public License for more details.
13 *
14 *	You should have received a copy of the GNU General Public License
15 *	along with this program; if not, write to the Free Software
16 *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19#include <errno.h>
20#include <fcntl.h>
21#include <netdb.h>
22#include <stdarg.h>
23#include <stdbool.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28#include <sys/socket.h>
29#include <sys/stat.h>
30#include <sys/types.h>
31#include <sys/wait.h>
32#include <arpa/inet.h>
33
34#include <xtables.h>
35#include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */
36#include <linux/netfilter_ipv4/ip_tables.h>
37#include <linux/netfilter_ipv6/ip6_tables.h>
38#include <libiptc/libxtc.h>
39
40#ifndef NO_SHARED_LIBS
41#include <dlfcn.h>
42#endif
43#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */
44#	define IPT_SO_GET_REVISION_MATCH	(IPT_BASE_CTL + 2)
45#	define IPT_SO_GET_REVISION_TARGET	(IPT_BASE_CTL + 3)
46#endif
47#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */
48#	define IP6T_SO_GET_REVISION_MATCH	68
49#	define IP6T_SO_GET_REVISION_TARGET	69
50#endif
51#include <getopt.h>
52#include "xshared.h"
53
54#define NPROTO	255
55
56#ifndef PROC_SYS_MODPROBE
57#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
58#endif
59
60void basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
61
62struct xtables_globals *xt_params = NULL;
63
64void basic_exit_err(enum xtables_exittype status, const char *msg, ...)
65{
66	va_list args;
67
68	va_start(args, msg);
69	fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version);
70	vfprintf(stderr, msg, args);
71	va_end(args);
72	fprintf(stderr, "\n");
73	exit(status);
74}
75
76void xtables_free_opts(int unused)
77{
78	if (xt_params->opts != xt_params->orig_opts)
79		free(xt_params->opts);
80}
81
82struct option *xtables_merge_options(struct option *orig_opts,
83				     struct option *oldopts,
84				     const struct option *newopts,
85				     unsigned int *option_offset)
86{
87	unsigned int num_oold = 0, num_old = 0, num_new = 0, i;
88	struct option *merge, *mp;
89
90	if (newopts == NULL)
91		return oldopts;
92
93	for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ;
94	if (oldopts != NULL)
95		for (num_old = 0; oldopts[num_old].name; num_old++) ;
96	for (num_new = 0; newopts[num_new].name; num_new++) ;
97
98	/*
99	 * Since @oldopts also has @orig_opts already (and does so at the
100	 * start), skip these entries.
101	 */
102	oldopts += num_oold;
103	num_old -= num_oold;
104
105	merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1));
106	if (merge == NULL)
107		return NULL;
108
109	/* Let the base options -[ADI...] have precedence over everything */
110	memcpy(merge, orig_opts, sizeof(*mp) * num_oold);
111	mp = merge + num_oold;
112
113	/* Second, the new options */
114	xt_params->option_offset += XT_OPTION_OFFSET_SCALE;
115	*option_offset = xt_params->option_offset;
116	memcpy(mp, newopts, sizeof(*mp) * num_new);
117
118	for (i = 0; i < num_new; ++i, ++mp)
119		mp->val += *option_offset;
120
121	/* Third, the old options */
122	memcpy(mp, oldopts, sizeof(*mp) * num_old);
123	mp += num_old;
124	xtables_free_opts(0);
125
126	/* Clear trailing entry */
127	memset(mp, 0, sizeof(*mp));
128	return merge;
129}
130
131/**
132 * xtables_afinfo - protocol family dependent information
133 * @kmod:		kernel module basename (e.g. "ip_tables")
134 * @libprefix:		prefix of .so library name (e.g. "libipt_")
135 * @family:		nfproto family
136 * @ipproto:		used by setsockopt (e.g. IPPROTO_IP)
137 * @so_rev_match:	optname to check revision support of match
138 * @so_rev_target:	optname to check revision support of target
139 */
140struct xtables_afinfo {
141	const char *kmod;
142	const char *libprefix;
143	uint8_t family;
144	uint8_t ipproto;
145	int so_rev_match;
146	int so_rev_target;
147};
148
149static const struct xtables_afinfo afinfo_ipv4 = {
150	.kmod          = "ip_tables",
151	.libprefix     = "libipt_",
152	.family	       = NFPROTO_IPV4,
153	.ipproto       = IPPROTO_IP,
154	.so_rev_match  = IPT_SO_GET_REVISION_MATCH,
155	.so_rev_target = IPT_SO_GET_REVISION_TARGET,
156};
157
158static const struct xtables_afinfo afinfo_ipv6 = {
159	.kmod          = "ip6_tables",
160	.libprefix     = "libip6t_",
161	.family        = NFPROTO_IPV6,
162	.ipproto       = IPPROTO_IPV6,
163	.so_rev_match  = IP6T_SO_GET_REVISION_MATCH,
164	.so_rev_target = IP6T_SO_GET_REVISION_TARGET,
165};
166
167static const struct xtables_afinfo *afinfo;
168
169/* Search path for Xtables .so files */
170static const char *xtables_libdir;
171
172/* the path to command to load kernel module */
173const char *xtables_modprobe_program;
174
175/* Keeping track of external matches and targets: linked lists.  */
176struct xtables_match *xtables_matches;
177struct xtables_target *xtables_targets;
178
179void xtables_init(void)
180{
181	xtables_libdir = getenv("XTABLES_LIBDIR");
182	if (xtables_libdir != NULL)
183		return;
184	xtables_libdir = getenv("IPTABLES_LIB_DIR");
185	if (xtables_libdir != NULL) {
186		fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, "
187		        "use XTABLES_LIBDIR.\n");
188		return;
189	}
190	/*
191	 * Well yes, IP6TABLES_LIB_DIR is of lower priority over
192	 * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok
193	 * for these env vars are deprecated anyhow, and in light of the
194	 * (shared) libxt_*.so files, makes less sense to have
195	 * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR.
196	 */
197	xtables_libdir = getenv("IP6TABLES_LIB_DIR");
198	if (xtables_libdir != NULL) {
199		fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, "
200		        "use XTABLES_LIBDIR.\n");
201		return;
202	}
203	xtables_libdir = XTABLES_LIBDIR;
204}
205
206void xtables_set_nfproto(uint8_t nfproto)
207{
208	switch (nfproto) {
209	case NFPROTO_IPV4:
210		afinfo = &afinfo_ipv4;
211		break;
212	case NFPROTO_IPV6:
213		afinfo = &afinfo_ipv6;
214		break;
215	default:
216		fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n",
217		        __func__);
218	}
219}
220
221/**
222 * xtables_set_params - set the global parameters used by xtables
223 * @xtp:	input xtables_globals structure
224 *
225 * The app is expected to pass a valid xtables_globals data-filled
226 * with proper values
227 * @xtp cannot be NULL
228 *
229 * Returns -1 on failure to set and 0 on success
230 */
231int xtables_set_params(struct xtables_globals *xtp)
232{
233	if (!xtp) {
234		fprintf(stderr, "%s: Illegal global params\n",__func__);
235		return -1;
236	}
237
238	xt_params = xtp;
239
240	if (!xt_params->exit_err)
241		xt_params->exit_err = basic_exit_err;
242
243	return 0;
244}
245
246int xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto)
247{
248	xtables_init();
249	xtables_set_nfproto(nfproto);
250	return xtables_set_params(xtp);
251}
252
253/**
254 * xtables_*alloc - wrappers that exit on failure
255 */
256void *xtables_calloc(size_t count, size_t size)
257{
258	void *p;
259
260	if ((p = calloc(count, size)) == NULL) {
261		perror("ip[6]tables: calloc failed");
262		exit(1);
263	}
264
265	return p;
266}
267
268void *xtables_malloc(size_t size)
269{
270	void *p;
271
272	if ((p = malloc(size)) == NULL) {
273		perror("ip[6]tables: malloc failed");
274		exit(1);
275	}
276
277	return p;
278}
279
280void *xtables_realloc(void *ptr, size_t size)
281{
282	void *p;
283
284	if ((p = realloc(ptr, size)) == NULL) {
285		perror("ip[6]tables: realloc failed");
286		exit(1);
287	}
288
289	return p;
290}
291
292static char *get_modprobe(void)
293{
294	int procfile;
295	char *ret;
296
297#define PROCFILE_BUFSIZ	1024
298	procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
299	if (procfile < 0)
300		return NULL;
301
302	ret = malloc(PROCFILE_BUFSIZ);
303	if (ret) {
304		memset(ret, 0, PROCFILE_BUFSIZ);
305		switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
306		case -1: goto fail;
307		case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
308		}
309		if (ret[strlen(ret)-1]=='\n')
310			ret[strlen(ret)-1]=0;
311		close(procfile);
312		return ret;
313	}
314 fail:
315	free(ret);
316	close(procfile);
317	return NULL;
318}
319
320int xtables_insmod(const char *modname, const char *modprobe, bool quiet)
321{
322	char *buf = NULL;
323	char *argv[4];
324	int status;
325
326	/* If they don't explicitly set it, read out of kernel */
327	if (!modprobe) {
328		buf = get_modprobe();
329		if (!buf)
330			return -1;
331		modprobe = buf;
332	}
333
334	/*
335	 * Need to flush the buffer, or the child may output it again
336	 * when switching the program thru execv.
337	 */
338	fflush(stdout);
339
340	switch (vfork()) {
341	case 0:
342		argv[0] = (char *)modprobe;
343		argv[1] = (char *)modname;
344		if (quiet) {
345			argv[2] = "-q";
346			argv[3] = NULL;
347		} else {
348			argv[2] = NULL;
349			argv[3] = NULL;
350		}
351		execv(argv[0], argv);
352
353		/* not usually reached */
354		exit(1);
355	case -1:
356		return -1;
357
358	default: /* parent */
359		wait(&status);
360	}
361
362	free(buf);
363	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
364		return 0;
365	return -1;
366}
367
368int xtables_load_ko(const char *modprobe, bool quiet)
369{
370	static bool loaded = false;
371	static int ret = -1;
372
373	if (!loaded) {
374		ret = xtables_insmod(afinfo->kmod, modprobe, quiet);
375		loaded = (ret == 0);
376	}
377
378	return ret;
379}
380
381/**
382 * xtables_strtou{i,l} - string to number conversion
383 * @s:	input string
384 * @end:	like strtoul's "end" pointer
385 * @value:	pointer for result
386 * @min:	minimum accepted value
387 * @max:	maximum accepted value
388 *
389 * If @end is NULL, we assume the caller wants a "strict strtoul", and hence
390 * "15a" is rejected.
391 * In either case, the value obtained is compared for min-max compliance.
392 * Base is always 0, i.e. autodetect depending on @s.
393 *
394 * Returns true/false whether number was accepted. On failure, *value has
395 * undefined contents.
396 */
397bool xtables_strtoul(const char *s, char **end, unsigned long *value,
398                     unsigned long min, unsigned long max)
399{
400	unsigned long v;
401	char *my_end;
402
403	errno = 0;
404	v = strtoul(s, &my_end, 0);
405
406	if (my_end == s)
407		return false;
408	if (end != NULL)
409		*end = my_end;
410
411	if (errno != ERANGE && min <= v && (max == 0 || v <= max)) {
412		if (value != NULL)
413			*value = v;
414		if (end == NULL)
415			return *my_end == '\0';
416		return true;
417	}
418
419	return false;
420}
421
422bool xtables_strtoui(const char *s, char **end, unsigned int *value,
423                     unsigned int min, unsigned int max)
424{
425	unsigned long v;
426	bool ret;
427
428	ret = xtables_strtoul(s, end, &v, min, max);
429	if (value != NULL)
430		*value = v;
431	return ret;
432}
433
434int xtables_service_to_port(const char *name, const char *proto)
435{
436	struct servent *service;
437
438	if ((service = getservbyname(name, proto)) != NULL)
439		return ntohs((unsigned short) service->s_port);
440
441	return -1;
442}
443
444uint16_t xtables_parse_port(const char *port, const char *proto)
445{
446	unsigned int portnum;
447
448	if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) ||
449	    (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1)
450		return portnum;
451
452	xt_params->exit_err(PARAMETER_PROBLEM,
453		   "invalid port/service `%s' specified", port);
454}
455
456void xtables_parse_interface(const char *arg, char *vianame,
457			     unsigned char *mask)
458{
459	unsigned int vialen = strlen(arg);
460	unsigned int i;
461
462	memset(mask, 0, IFNAMSIZ);
463	memset(vianame, 0, IFNAMSIZ);
464
465	if (vialen + 1 > IFNAMSIZ)
466		xt_params->exit_err(PARAMETER_PROBLEM,
467			   "interface name `%s' must be shorter than IFNAMSIZ"
468			   " (%i)", arg, IFNAMSIZ-1);
469
470	strcpy(vianame, arg);
471	if (vialen == 0)
472		memset(mask, 0, IFNAMSIZ);
473	else if (vianame[vialen - 1] == '+') {
474		memset(mask, 0xFF, vialen - 1);
475		memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
476		/* Don't remove `+' here! -HW */
477	} else {
478		/* Include nul-terminator in match */
479		memset(mask, 0xFF, vialen + 1);
480		memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
481		for (i = 0; vianame[i]; i++) {
482			if (vianame[i] == '/' ||
483			    vianame[i] == ' ') {
484				fprintf(stderr,
485					"Warning: weird character in interface"
486					" `%s' ('/' and ' ' are not allowed by the kernel).\n",
487					vianame);
488				break;
489			}
490		}
491	}
492}
493
494#ifndef NO_SHARED_LIBS
495static void *load_extension(const char *search_path, const char *prefix,
496    const char *name, bool is_target)
497{
498	const char *dir = search_path, *next;
499	void *ptr = NULL;
500	struct stat sb;
501	char path[256];
502
503	do {
504		next = strchr(dir, ':');
505		if (next == NULL)
506			next = dir + strlen(dir);
507		snprintf(path, sizeof(path), "%.*s/libxt_%s.so",
508		         (unsigned int)(next - dir), dir, name);
509
510		if (dlopen(path, RTLD_NOW) != NULL) {
511			/* Found library.  If it didn't register itself,
512			   maybe they specified target as match. */
513			if (is_target)
514				ptr = xtables_find_target(name, XTF_DONT_LOAD);
515			else
516				ptr = xtables_find_match(name,
517				      XTF_DONT_LOAD, NULL);
518		} else if (stat(path, &sb) == 0) {
519			fprintf(stderr, "%s: %s\n", path, dlerror());
520		}
521
522		if (ptr != NULL)
523			return ptr;
524
525		snprintf(path, sizeof(path), "%.*s/%s%s.so",
526		         (unsigned int)(next - dir), dir, prefix, name);
527		if (dlopen(path, RTLD_NOW) != NULL) {
528			if (is_target)
529				ptr = xtables_find_target(name, XTF_DONT_LOAD);
530			else
531				ptr = xtables_find_match(name,
532				      XTF_DONT_LOAD, NULL);
533		} else if (stat(path, &sb) == 0) {
534			fprintf(stderr, "%s: %s\n", path, dlerror());
535		}
536
537		if (ptr != NULL)
538			return ptr;
539
540		dir = next + 1;
541	} while (*next != '\0');
542
543	return NULL;
544}
545#endif
546
547struct xtables_match *
548xtables_find_match(const char *name, enum xtables_tryload tryload,
549		   struct xtables_rule_match **matches)
550{
551	struct xtables_match *ptr;
552	const char *icmp6 = "icmp6";
553
554	if (strlen(name) >= XT_EXTENSION_MAXNAMELEN)
555		xtables_error(PARAMETER_PROBLEM,
556			   "Invalid match name \"%s\" (%u chars max)",
557			   name, XT_EXTENSION_MAXNAMELEN - 1);
558
559	/* This is ugly as hell. Nonetheless, there is no way of changing
560	 * this without hurting backwards compatibility */
561	if ( (strcmp(name,"icmpv6") == 0) ||
562	     (strcmp(name,"ipv6-icmp") == 0) ||
563	     (strcmp(name,"icmp6") == 0) )
564		name = icmp6;
565
566	for (ptr = xtables_matches; ptr; ptr = ptr->next) {
567		if (strcmp(name, ptr->name) == 0) {
568			struct xtables_match *clone;
569
570			/* First match of this type: */
571			if (ptr->m == NULL)
572				break;
573
574			/* Second and subsequent clones */
575			clone = xtables_malloc(sizeof(struct xtables_match));
576			memcpy(clone, ptr, sizeof(struct xtables_match));
577			clone->mflags = 0;
578			/* This is a clone: */
579			clone->next = clone;
580
581			ptr = clone;
582			break;
583		}
584	}
585
586#ifndef NO_SHARED_LIBS
587	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
588		ptr = load_extension(xtables_libdir, afinfo->libprefix,
589		      name, false);
590
591		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
592			xt_params->exit_err(PARAMETER_PROBLEM,
593				   "Couldn't load match `%s':%s\n",
594				   name, dlerror());
595	}
596#else
597	if (ptr && !ptr->loaded) {
598		if (tryload != XTF_DONT_LOAD)
599			ptr->loaded = 1;
600		else
601			ptr = NULL;
602	}
603	if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) {
604		xt_params->exit_err(PARAMETER_PROBLEM,
605			   "Couldn't find match `%s'\n", name);
606	}
607#endif
608
609	if (ptr && matches) {
610		struct xtables_rule_match **i;
611		struct xtables_rule_match *newentry;
612
613		newentry = xtables_malloc(sizeof(struct xtables_rule_match));
614
615		for (i = matches; *i; i = &(*i)->next) {
616			if (strcmp(name, (*i)->match->name) == 0)
617				(*i)->completed = true;
618		}
619		newentry->match = ptr;
620		newentry->completed = false;
621		newentry->next = NULL;
622		*i = newentry;
623	}
624
625	return ptr;
626}
627
628struct xtables_target *
629xtables_find_target(const char *name, enum xtables_tryload tryload)
630{
631	struct xtables_target *ptr;
632
633	/* Standard target? */
634	if (strcmp(name, "") == 0
635	    || strcmp(name, XTC_LABEL_ACCEPT) == 0
636	    || strcmp(name, XTC_LABEL_DROP) == 0
637	    || strcmp(name, XTC_LABEL_QUEUE) == 0
638	    || strcmp(name, XTC_LABEL_RETURN) == 0)
639		name = "standard";
640
641	for (ptr = xtables_targets; ptr; ptr = ptr->next) {
642		if (strcmp(name, ptr->name) == 0)
643			break;
644	}
645
646#ifndef NO_SHARED_LIBS
647	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
648		ptr = load_extension(xtables_libdir, afinfo->libprefix,
649		      name, true);
650
651		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
652			xt_params->exit_err(PARAMETER_PROBLEM,
653				   "Couldn't load target `%s':%s\n",
654				   name, dlerror());
655	}
656#else
657	if (ptr && !ptr->loaded) {
658		if (tryload != XTF_DONT_LOAD)
659			ptr->loaded = 1;
660		else
661			ptr = NULL;
662	}
663	if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) {
664		xt_params->exit_err(PARAMETER_PROBLEM,
665			   "Couldn't find target `%s'\n", name);
666	}
667#endif
668
669	if (ptr)
670		ptr->used = 1;
671
672	return ptr;
673}
674
675static int compatible_revision(const char *name, uint8_t revision, int opt)
676{
677	struct xt_get_revision rev;
678	socklen_t s = sizeof(rev);
679	int max_rev, sockfd;
680
681	sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);
682	if (sockfd < 0) {
683		if (errno == EPERM) {
684			/* revision 0 is always supported. */
685			if (revision != 0)
686				fprintf(stderr, "Could not determine whether "
687						"revision %u is supported, "
688						"assuming it is.\n",
689					revision);
690			return 1;
691		}
692		fprintf(stderr, "Could not open socket to kernel: %s\n",
693			strerror(errno));
694		exit(1);
695	}
696
697	xtables_load_ko(xtables_modprobe_program, true);
698
699	strcpy(rev.name, name);
700	rev.revision = revision;
701
702	max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s);
703	if (max_rev < 0) {
704		/* Definitely don't support this? */
705		if (errno == ENOENT || errno == EPROTONOSUPPORT) {
706			close(sockfd);
707			return 0;
708		} else if (errno == ENOPROTOOPT) {
709			close(sockfd);
710			/* Assume only revision 0 support (old kernel) */
711			return (revision == 0);
712		} else {
713			fprintf(stderr, "getsockopt failed strangely: %s\n",
714				strerror(errno));
715			exit(1);
716		}
717	}
718	close(sockfd);
719	return 1;
720}
721
722
723static int compatible_match_revision(const char *name, uint8_t revision)
724{
725	return compatible_revision(name, revision, afinfo->so_rev_match);
726}
727
728static int compatible_target_revision(const char *name, uint8_t revision)
729{
730	return compatible_revision(name, revision, afinfo->so_rev_target);
731}
732
733static void xtables_check_options(const char *name, const struct option *opt)
734{
735	for (; opt->name != NULL; ++opt)
736		if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) {
737			fprintf(stderr, "%s: Extension %s uses invalid "
738			        "option value %d\n",xt_params->program_name,
739			        name, opt->val);
740			exit(1);
741		}
742}
743
744void xtables_register_match(struct xtables_match *me)
745{
746	struct xtables_match **i, *old;
747
748	if (me->version == NULL) {
749		fprintf(stderr, "%s: match %s<%u> is missing a version\n",
750		        xt_params->program_name, me->name, me->revision);
751		exit(1);
752	}
753	if (strcmp(me->version, XTABLES_VERSION) != 0) {
754		fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
755		        "but \"%s\" is required.\n",
756			xt_params->program_name, me->name,
757			me->version, XTABLES_VERSION);
758		exit(1);
759	}
760
761	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
762		fprintf(stderr, "%s: match `%s' has invalid name\n",
763			xt_params->program_name, me->name);
764		exit(1);
765	}
766
767	if (me->family >= NPROTO) {
768		fprintf(stderr,
769			"%s: BUG: match %s has invalid protocol family\n",
770			xt_params->program_name, me->name);
771		exit(1);
772	}
773
774	if (me->extra_opts != NULL)
775		xtables_check_options(me->name, me->extra_opts);
776
777	/* ignore not interested match */
778	if (me->family != afinfo->family && me->family != AF_UNSPEC)
779		return;
780
781	old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
782	if (old) {
783		if (old->revision == me->revision &&
784		    old->family == me->family) {
785			fprintf(stderr,
786				"%s: match `%s' already registered.\n",
787				xt_params->program_name, me->name);
788			exit(1);
789		}
790
791		/* Now we have two (or more) options, check compatibility. */
792		if (compatible_match_revision(old->name, old->revision)
793		    && old->revision > me->revision)
794			return;
795
796		/* See if new match can be used. */
797		if (!compatible_match_revision(me->name, me->revision))
798			return;
799
800		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
801		if (old->revision == me->revision && me->family == AF_UNSPEC)
802			return;
803
804		/* Delete old one. */
805		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
806		*i = old->next;
807	}
808
809	if (me->size != XT_ALIGN(me->size)) {
810		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
811		        xt_params->program_name, me->name,
812		        (unsigned int)me->size);
813		exit(1);
814	}
815
816	/* Append to list. */
817	for (i = &xtables_matches; *i; i = &(*i)->next);
818	me->next = NULL;
819	*i = me;
820
821	me->m = NULL;
822	me->mflags = 0;
823}
824
825void xtables_register_matches(struct xtables_match *match, unsigned int n)
826{
827	do {
828		xtables_register_match(&match[--n]);
829	} while (n > 0);
830}
831
832void xtables_register_target(struct xtables_target *me)
833{
834	struct xtables_target *old;
835
836	if (me->version == NULL) {
837		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
838		        xt_params->program_name, me->name, me->revision);
839		exit(1);
840	}
841	if (strcmp(me->version, XTABLES_VERSION) != 0) {
842		fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
843		        "but \"%s\" is required.\n",
844			xt_params->program_name, me->name,
845			me->version, XTABLES_VERSION);
846		exit(1);
847	}
848
849	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
850		fprintf(stderr, "%s: target `%s' has invalid name\n",
851			xt_params->program_name, me->name);
852		exit(1);
853	}
854
855	if (me->family >= NPROTO) {
856		fprintf(stderr,
857			"%s: BUG: target %s has invalid protocol family\n",
858			xt_params->program_name, me->name);
859		exit(1);
860	}
861
862	if (me->extra_opts != NULL)
863		xtables_check_options(me->name, me->extra_opts);
864
865	/* ignore not interested target */
866	if (me->family != afinfo->family && me->family != AF_UNSPEC)
867		return;
868
869	old = xtables_find_target(me->name, XTF_DURING_LOAD);
870	if (old) {
871		struct xtables_target **i;
872
873		if (old->revision == me->revision &&
874		    old->family == me->family) {
875			fprintf(stderr,
876				"%s: target `%s' already registered.\n",
877				xt_params->program_name, me->name);
878			exit(1);
879		}
880
881		/* Now we have two (or more) options, check compatibility. */
882		if (compatible_target_revision(old->name, old->revision)
883		    && old->revision > me->revision)
884			return;
885
886		/* See if new target can be used. */
887		if (!compatible_target_revision(me->name, me->revision))
888			return;
889
890		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
891		if (old->revision == me->revision && me->family == AF_UNSPEC)
892			return;
893
894		/* Delete old one. */
895		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
896		*i = old->next;
897	}
898
899	if (me->size != XT_ALIGN(me->size)) {
900		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
901		        xt_params->program_name, me->name,
902		        (unsigned int)me->size);
903		exit(1);
904	}
905
906	/* Prepend to list. */
907	me->next = xtables_targets;
908	xtables_targets = me;
909	me->t = NULL;
910	me->tflags = 0;
911}
912
913void xtables_register_targets(struct xtables_target *target, unsigned int n)
914{
915	do {
916		xtables_register_target(&target[--n]);
917	} while (n > 0);
918}
919
920/**
921 * xtables_param_act - act on condition
922 * @status:	a constant from enum xtables_exittype
923 *
924 * %XTF_ONLY_ONCE: print error message that option may only be used once.
925 * @p1:		module name (e.g. "mark")
926 * @p2(...):	option in conflict (e.g. "--mark")
927 * @p3(...):	condition to match on (see extensions/ for examples)
928 *
929 * %XTF_NO_INVERT: option does not support inversion
930 * @p1:		module name
931 * @p2:		option in conflict
932 * @p3:		condition to match on
933 *
934 * %XTF_BAD_VALUE: bad value for option
935 * @p1:		module name
936 * @p2:		option with which the problem occured (e.g. "--mark")
937 * @p3:		string the user passed in (e.g. "99999999999999")
938 *
939 * %XTF_ONE_ACTION: two mutually exclusive actions have been specified
940 * @p1:		module name
941 *
942 * Displays an error message and exits the program.
943 */
944void xtables_param_act(unsigned int status, const char *p1, ...)
945{
946	const char *p2, *p3;
947	va_list args;
948	bool b;
949
950	va_start(args, p1);
951
952	switch (status) {
953	case XTF_ONLY_ONCE:
954		p2 = va_arg(args, const char *);
955		b  = va_arg(args, unsigned int);
956		if (!b)
957			return;
958		xt_params->exit_err(PARAMETER_PROBLEM,
959		           "%s: \"%s\" option may only be specified once",
960		           p1, p2);
961		break;
962	case XTF_NO_INVERT:
963		p2 = va_arg(args, const char *);
964		b  = va_arg(args, unsigned int);
965		if (!b)
966			return;
967		xt_params->exit_err(PARAMETER_PROBLEM,
968		           "%s: \"%s\" option cannot be inverted", p1, p2);
969		break;
970	case XTF_BAD_VALUE:
971		p2 = va_arg(args, const char *);
972		p3 = va_arg(args, const char *);
973		xt_params->exit_err(PARAMETER_PROBLEM,
974		           "%s: Bad value for \"%s\" option: \"%s\"",
975		           p1, p2, p3);
976		break;
977	case XTF_ONE_ACTION:
978		b = va_arg(args, unsigned int);
979		if (!b)
980			return;
981		xt_params->exit_err(PARAMETER_PROBLEM,
982		           "%s: At most one action is possible", p1);
983		break;
984	default:
985		xt_params->exit_err(status, p1, args);
986		break;
987	}
988
989	va_end(args);
990}
991
992const char *xtables_ipaddr_to_numeric(const struct in_addr *addrp)
993{
994	static char buf[20];
995	const unsigned char *bytep = (const void *)&addrp->s_addr;
996
997	sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
998	return buf;
999}
1000
1001static const char *ipaddr_to_host(const struct in_addr *addr)
1002{
1003	struct hostent *host;
1004
1005	host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET);
1006	if (host == NULL)
1007		return NULL;
1008
1009	return host->h_name;
1010}
1011
1012static const char *ipaddr_to_network(const struct in_addr *addr)
1013{
1014	struct netent *net;
1015
1016	if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL)
1017		return net->n_name;
1018
1019	return NULL;
1020}
1021
1022const char *xtables_ipaddr_to_anyname(const struct in_addr *addr)
1023{
1024	const char *name;
1025
1026	if ((name = ipaddr_to_host(addr)) != NULL ||
1027	    (name = ipaddr_to_network(addr)) != NULL)
1028		return name;
1029
1030	return xtables_ipaddr_to_numeric(addr);
1031}
1032
1033const char *xtables_ipmask_to_numeric(const struct in_addr *mask)
1034{
1035	static char buf[20];
1036	uint32_t maskaddr, bits;
1037	int i;
1038
1039	maskaddr = ntohl(mask->s_addr);
1040
1041	if (maskaddr == 0xFFFFFFFFL)
1042		/* we don't want to see "/32" */
1043		return "";
1044
1045	i = 32;
1046	bits = 0xFFFFFFFEL;
1047	while (--i >= 0 && maskaddr != bits)
1048		bits <<= 1;
1049	if (i >= 0)
1050		sprintf(buf, "/%d", i);
1051	else
1052		/* mask was not a decent combination of 1's and 0's */
1053		sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
1054
1055	return buf;
1056}
1057
1058static struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask)
1059{
1060	static struct in_addr addr;
1061	unsigned char *addrp;
1062	unsigned int onebyte;
1063	char buf[20], *p, *q;
1064	int i;
1065
1066	/* copy dotted string, because we need to modify it */
1067	strncpy(buf, dotted, sizeof(buf) - 1);
1068	buf[sizeof(buf) - 1] = '\0';
1069	addrp = (void *)&addr.s_addr;
1070
1071	p = buf;
1072	for (i = 0; i < 3; ++i) {
1073		if ((q = strchr(p, '.')) == NULL) {
1074			if (is_mask)
1075				return NULL;
1076
1077			/* autocomplete, this is a network address */
1078			if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1079				return NULL;
1080
1081			addrp[i] = onebyte;
1082			while (i < 3)
1083				addrp[++i] = 0;
1084
1085			return &addr;
1086		}
1087
1088		*q = '\0';
1089		if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1090			return NULL;
1091
1092		addrp[i] = onebyte;
1093		p = q + 1;
1094	}
1095
1096	/* we have checked 3 bytes, now we check the last one */
1097	if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1098		return NULL;
1099
1100	addrp[3] = onebyte;
1101	return &addr;
1102}
1103
1104struct in_addr *xtables_numeric_to_ipaddr(const char *dotted)
1105{
1106	return __numeric_to_ipaddr(dotted, false);
1107}
1108
1109struct in_addr *xtables_numeric_to_ipmask(const char *dotted)
1110{
1111	return __numeric_to_ipaddr(dotted, true);
1112}
1113
1114static struct in_addr *network_to_ipaddr(const char *name)
1115{
1116	static struct in_addr addr;
1117	struct netent *net;
1118
1119	if ((net = getnetbyname(name)) != NULL) {
1120		if (net->n_addrtype != AF_INET)
1121			return NULL;
1122		addr.s_addr = htonl(net->n_net);
1123		return &addr;
1124	}
1125
1126	return NULL;
1127}
1128
1129static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
1130{
1131	struct hostent *host;
1132	struct in_addr *addr;
1133	unsigned int i;
1134
1135	*naddr = 0;
1136	if ((host = gethostbyname(name)) != NULL) {
1137		if (host->h_addrtype != AF_INET ||
1138		    host->h_length != sizeof(struct in_addr))
1139			return NULL;
1140
1141		while (host->h_addr_list[*naddr] != NULL)
1142			++*naddr;
1143		addr = xtables_calloc(*naddr, sizeof(struct in_addr) * *naddr);
1144		for (i = 0; i < *naddr; i++)
1145			memcpy(&addr[i], host->h_addr_list[i],
1146			       sizeof(struct in_addr));
1147		return addr;
1148	}
1149
1150	return NULL;
1151}
1152
1153static struct in_addr *
1154ipparse_hostnetwork(const char *name, unsigned int *naddrs)
1155{
1156	struct in_addr *addrptmp, *addrp;
1157
1158	if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL ||
1159	    (addrptmp = network_to_ipaddr(name)) != NULL) {
1160		addrp = xtables_malloc(sizeof(struct in_addr));
1161		memcpy(addrp, addrptmp, sizeof(*addrp));
1162		*naddrs = 1;
1163		return addrp;
1164	}
1165	if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL)
1166		return addrptmp;
1167
1168	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1169}
1170
1171static struct in_addr *parse_ipmask(const char *mask)
1172{
1173	static struct in_addr maskaddr;
1174	struct in_addr *addrp;
1175	unsigned int bits;
1176
1177	if (mask == NULL) {
1178		/* no mask at all defaults to 32 bits */
1179		maskaddr.s_addr = 0xFFFFFFFF;
1180		return &maskaddr;
1181	}
1182	if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL)
1183		/* dotted_to_addr already returns a network byte order addr */
1184		return addrp;
1185	if (!xtables_strtoui(mask, NULL, &bits, 0, 32))
1186		xt_params->exit_err(PARAMETER_PROBLEM,
1187			   "invalid mask `%s' specified", mask);
1188	if (bits != 0) {
1189		maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
1190		return &maskaddr;
1191	}
1192
1193	maskaddr.s_addr = 0U;
1194	return &maskaddr;
1195}
1196
1197void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
1198                              struct in_addr **maskpp, unsigned int *naddrs)
1199{
1200	struct in_addr *addrp;
1201	char buf[256], *p;
1202	unsigned int len, i, j, n, count = 1;
1203	const char *loop = name;
1204
1205	while ((loop = strchr(loop, ',')) != NULL) {
1206		++count;
1207		++loop; /* skip ',' */
1208	}
1209
1210	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
1211	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
1212
1213	loop = name;
1214
1215	for (i = 0; i < count; ++i) {
1216		if (loop == NULL)
1217			break;
1218		if (*loop == ',')
1219			++loop;
1220		if (*loop == '\0')
1221			break;
1222		p = strchr(loop, ',');
1223		if (p != NULL)
1224			len = p - loop;
1225		else
1226			len = strlen(loop);
1227		if (len == 0 || sizeof(buf) - 1 < len)
1228			break;
1229
1230		strncpy(buf, loop, len);
1231		buf[len] = '\0';
1232		loop += len;
1233		if ((p = strrchr(buf, '/')) != NULL) {
1234			*p = '\0';
1235			addrp = parse_ipmask(p + 1);
1236		} else {
1237			addrp = parse_ipmask(NULL);
1238		}
1239		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1240
1241		/* if a null mask is given, the name is ignored, like in "any/0" */
1242		if ((*maskpp + i)->s_addr == 0)
1243			/*
1244			 * A bit pointless to process multiple addresses
1245			 * in this case...
1246			 */
1247			strcpy(buf, "0.0.0.0");
1248
1249		addrp = ipparse_hostnetwork(buf, &n);
1250		if (n > 1) {
1251			count += n - 1;
1252			*addrpp = xtables_realloc(*addrpp,
1253			          sizeof(struct in_addr) * count);
1254			*maskpp = xtables_realloc(*maskpp,
1255			          sizeof(struct in_addr) * count);
1256			for (j = 0; j < n; ++j)
1257				/* for each new addr */
1258				memcpy(*addrpp + i + j, addrp + j,
1259				       sizeof(*addrp));
1260			for (j = 1; j < n; ++j)
1261				/* for each new mask */
1262				memcpy(*maskpp + i + j, *maskpp + i,
1263				       sizeof(*addrp));
1264			i += n - 1;
1265		} else {
1266			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1267		}
1268		/* free what ipparse_hostnetwork had allocated: */
1269		free(addrp);
1270	}
1271	*naddrs = count;
1272	for (i = 0; i < n; ++i)
1273		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
1274}
1275
1276
1277/**
1278 * xtables_ipparse_any - transform arbitrary name to in_addr
1279 *
1280 * Possible inputs (pseudo regex):
1281 * 	m{^($hostname|$networkname|$ipaddr)(/$mask)?}
1282 * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname"
1283 */
1284void xtables_ipparse_any(const char *name, struct in_addr **addrpp,
1285                         struct in_addr *maskp, unsigned int *naddrs)
1286{
1287	unsigned int i, j, k, n;
1288	struct in_addr *addrp;
1289	char buf[256], *p;
1290
1291	strncpy(buf, name, sizeof(buf) - 1);
1292	buf[sizeof(buf) - 1] = '\0';
1293	if ((p = strrchr(buf, '/')) != NULL) {
1294		*p = '\0';
1295		addrp = parse_ipmask(p + 1);
1296	} else {
1297		addrp = parse_ipmask(NULL);
1298	}
1299	memcpy(maskp, addrp, sizeof(*maskp));
1300
1301	/* if a null mask is given, the name is ignored, like in "any/0" */
1302	if (maskp->s_addr == 0U)
1303		strcpy(buf, "0.0.0.0");
1304
1305	addrp = *addrpp = ipparse_hostnetwork(buf, naddrs);
1306	n = *naddrs;
1307	for (i = 0, j = 0; i < n; ++i) {
1308		addrp[j++].s_addr &= maskp->s_addr;
1309		for (k = 0; k < j - 1; ++k)
1310			if (addrp[k].s_addr == addrp[j-1].s_addr) {
1311				--*naddrs;
1312				--j;
1313				break;
1314			}
1315	}
1316}
1317
1318const char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp)
1319{
1320	/* 0000:0000:0000:0000:0000:000.000.000.000
1321	 * 0000:0000:0000:0000:0000:0000:0000:0000 */
1322	static char buf[50+1];
1323	return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
1324}
1325
1326static const char *ip6addr_to_host(const struct in6_addr *addr)
1327{
1328	static char hostname[NI_MAXHOST];
1329	struct sockaddr_in6 saddr;
1330	int err;
1331
1332	memset(&saddr, 0, sizeof(struct sockaddr_in6));
1333	memcpy(&saddr.sin6_addr, addr, sizeof(*addr));
1334	saddr.sin6_family = AF_INET6;
1335
1336	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6),
1337	      hostname, sizeof(hostname) - 1, NULL, 0, 0);
1338	if (err != 0) {
1339#ifdef DEBUG
1340		fprintf(stderr,"IP2Name: %s\n",gai_strerror(err));
1341#endif
1342		return NULL;
1343	}
1344
1345#ifdef DEBUG
1346	fprintf (stderr, "\naddr2host: %s\n", hostname);
1347#endif
1348	return hostname;
1349}
1350
1351const char *xtables_ip6addr_to_anyname(const struct in6_addr *addr)
1352{
1353	const char *name;
1354
1355	if ((name = ip6addr_to_host(addr)) != NULL)
1356		return name;
1357
1358	return xtables_ip6addr_to_numeric(addr);
1359}
1360
1361static int ip6addr_prefix_length(const struct in6_addr *k)
1362{
1363	unsigned int bits = 0;
1364	uint32_t a, b, c, d;
1365
1366	a = ntohl(k->s6_addr32[0]);
1367	b = ntohl(k->s6_addr32[1]);
1368	c = ntohl(k->s6_addr32[2]);
1369	d = ntohl(k->s6_addr32[3]);
1370	while (a & 0x80000000U) {
1371		++bits;
1372		a <<= 1;
1373		a  |= (b >> 31) & 1;
1374		b <<= 1;
1375		b  |= (c >> 31) & 1;
1376		c <<= 1;
1377		c  |= (d >> 31) & 1;
1378		d <<= 1;
1379	}
1380	if (a != 0 || b != 0 || c != 0 || d != 0)
1381		return -1;
1382	return bits;
1383}
1384
1385const char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
1386{
1387	static char buf[50+2];
1388	int l = ip6addr_prefix_length(addrp);
1389
1390	if (l == -1) {
1391		strcpy(buf, "/");
1392		strcat(buf, xtables_ip6addr_to_numeric(addrp));
1393		return buf;
1394	}
1395	sprintf(buf, "/%d", l);
1396	return buf;
1397}
1398
1399struct in6_addr *xtables_numeric_to_ip6addr(const char *num)
1400{
1401	static struct in6_addr ap;
1402	int err;
1403
1404	if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
1405		return &ap;
1406#ifdef DEBUG
1407	fprintf(stderr, "\nnumeric2addr: %d\n", err);
1408#endif
1409	return NULL;
1410}
1411
1412static struct in6_addr *
1413host_to_ip6addr(const char *name, unsigned int *naddr)
1414{
1415	static struct in6_addr *addr;
1416	struct addrinfo hints;
1417	struct addrinfo *res;
1418	int err;
1419
1420	memset(&hints, 0, sizeof(hints));
1421	hints.ai_flags    = AI_CANONNAME;
1422	hints.ai_family   = AF_INET6;
1423	hints.ai_socktype = SOCK_RAW;
1424	hints.ai_protocol = IPPROTO_IPV6;
1425	hints.ai_next     = NULL;
1426
1427	*naddr = 0;
1428	if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
1429#ifdef DEBUG
1430		fprintf(stderr,"Name2IP: %s\n",gai_strerror(err));
1431#endif
1432		return NULL;
1433	} else {
1434		if (res->ai_family != AF_INET6 ||
1435		    res->ai_addrlen != sizeof(struct sockaddr_in6))
1436			return NULL;
1437
1438#ifdef DEBUG
1439		fprintf(stderr, "resolved: len=%d  %s ", res->ai_addrlen,
1440		        xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr));
1441#endif
1442		/* Get the first element of the address-chain */
1443		addr = xtables_malloc(sizeof(struct in6_addr));
1444		memcpy(addr, &((const struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
1445		       sizeof(struct in6_addr));
1446		freeaddrinfo(res);
1447		*naddr = 1;
1448		return addr;
1449	}
1450
1451	return NULL;
1452}
1453
1454static struct in6_addr *network_to_ip6addr(const char *name)
1455{
1456	/*	abort();*/
1457	/* TODO: not implemented yet, but the exception breaks the
1458	 *       name resolvation */
1459	return NULL;
1460}
1461
1462static struct in6_addr *
1463ip6parse_hostnetwork(const char *name, unsigned int *naddrs)
1464{
1465	struct in6_addr *addrp, *addrptmp;
1466
1467	if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL ||
1468	    (addrptmp = network_to_ip6addr(name)) != NULL) {
1469		addrp = xtables_malloc(sizeof(struct in6_addr));
1470		memcpy(addrp, addrptmp, sizeof(*addrp));
1471		*naddrs = 1;
1472		return addrp;
1473	}
1474	if ((addrp = host_to_ip6addr(name, naddrs)) != NULL)
1475		return addrp;
1476
1477	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1478}
1479
1480static struct in6_addr *parse_ip6mask(char *mask)
1481{
1482	static struct in6_addr maskaddr;
1483	struct in6_addr *addrp;
1484	unsigned int bits;
1485
1486	if (mask == NULL) {
1487		/* no mask at all defaults to 128 bits */
1488		memset(&maskaddr, 0xff, sizeof maskaddr);
1489		return &maskaddr;
1490	}
1491	if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL)
1492		return addrp;
1493	if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
1494		xt_params->exit_err(PARAMETER_PROBLEM,
1495			   "invalid mask `%s' specified", mask);
1496	if (bits != 0) {
1497		char *p = (void *)&maskaddr;
1498		memset(p, 0xff, bits / 8);
1499		memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
1500		p[bits/8] = 0xff << (8 - (bits & 7));
1501		return &maskaddr;
1502	}
1503
1504	memset(&maskaddr, 0, sizeof(maskaddr));
1505	return &maskaddr;
1506}
1507
1508void
1509xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
1510		      struct in6_addr **maskpp, unsigned int *naddrs)
1511{
1512	static const struct in6_addr zero_addr;
1513	struct in6_addr *addrp;
1514	char buf[256], *p;
1515	unsigned int len, i, j, n, count = 1;
1516	const char *loop = name;
1517
1518	while ((loop = strchr(loop, ',')) != NULL) {
1519		++count;
1520		++loop; /* skip ',' */
1521	}
1522
1523	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
1524	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
1525
1526	loop = name;
1527
1528	for (i = 0; i < count /*NB: count can grow*/; ++i) {
1529		if (loop == NULL)
1530			break;
1531		if (*loop == ',')
1532			++loop;
1533		if (*loop == '\0')
1534			break;
1535		p = strchr(loop, ',');
1536		if (p != NULL)
1537			len = p - loop;
1538		else
1539			len = strlen(loop);
1540		if (len == 0 || sizeof(buf) - 1 < len)
1541			break;
1542
1543		strncpy(buf, loop, len);
1544		buf[len] = '\0';
1545		loop += len;
1546		if ((p = strrchr(buf, '/')) != NULL) {
1547			*p = '\0';
1548			addrp = parse_ip6mask(p + 1);
1549		} else {
1550			addrp = parse_ip6mask(NULL);
1551		}
1552		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1553
1554		/* if a null mask is given, the name is ignored, like in "any/0" */
1555		if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0)
1556			strcpy(buf, "::");
1557
1558		addrp = ip6parse_hostnetwork(buf, &n);
1559		/* ip6parse_hostnetwork only ever returns one IP
1560		address (it exits if the resolution fails).
1561		Therefore, n will always be 1 here.  Leaving the
1562		code below in anyway in case ip6parse_hostnetwork
1563		is improved some day to behave like
1564		ipparse_hostnetwork: */
1565		if (n > 1) {
1566			count += n - 1;
1567			*addrpp = xtables_realloc(*addrpp,
1568			          sizeof(struct in6_addr) * count);
1569			*maskpp = xtables_realloc(*maskpp,
1570			          sizeof(struct in6_addr) * count);
1571			for (j = 0; j < n; ++j)
1572				/* for each new addr */
1573				memcpy(*addrpp + i + j, addrp + j,
1574				       sizeof(*addrp));
1575			for (j = 1; j < n; ++j)
1576				/* for each new mask */
1577				memcpy(*maskpp + i + j, *maskpp + i,
1578				       sizeof(*addrp));
1579			i += n - 1;
1580		} else {
1581			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1582		}
1583		/* free what ip6parse_hostnetwork had allocated: */
1584		free(addrp);
1585	}
1586	*naddrs = count;
1587	for (i = 0; i < n; ++i)
1588		for (j = 0; j < 4; ++j)
1589			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
1590}
1591
1592void xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
1593                          struct in6_addr *maskp, unsigned int *naddrs)
1594{
1595	static const struct in6_addr zero_addr;
1596	struct in6_addr *addrp;
1597	unsigned int i, j, k, n;
1598	char buf[256], *p;
1599
1600	strncpy(buf, name, sizeof(buf) - 1);
1601	buf[sizeof(buf)-1] = '\0';
1602	if ((p = strrchr(buf, '/')) != NULL) {
1603		*p = '\0';
1604		addrp = parse_ip6mask(p + 1);
1605	} else {
1606		addrp = parse_ip6mask(NULL);
1607	}
1608	memcpy(maskp, addrp, sizeof(*maskp));
1609
1610	/* if a null mask is given, the name is ignored, like in "any/0" */
1611	if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0)
1612		strcpy(buf, "::");
1613
1614	addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs);
1615	n = *naddrs;
1616	for (i = 0, j = 0; i < n; ++i) {
1617		for (k = 0; k < 4; ++k)
1618			addrp[j].s6_addr32[k] &= maskp->s6_addr32[k];
1619		++j;
1620		for (k = 0; k < j - 1; ++k)
1621			if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
1622				--*naddrs;
1623				--j;
1624				break;
1625			}
1626	}
1627}
1628
1629void xtables_save_string(const char *value)
1630{
1631	static const char no_quote_chars[] = "_-0123456789"
1632		"abcdefghijklmnopqrstuvwxyz"
1633		"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1634	static const char escape_chars[] = "\"\\'";
1635	size_t length;
1636	const char *p;
1637
1638	length = strcspn(value, no_quote_chars);
1639	if (length > 0 && value[length] == 0) {
1640		/* no quoting required */
1641		fputs(value, stdout);
1642		putchar(' ');
1643	} else {
1644		/* there is at least one dangerous character in the
1645		   value, which we have to quote.  Write double quotes
1646		   around the value and escape special characters with
1647		   a backslash */
1648		putchar('"');
1649
1650		for (p = strpbrk(value, escape_chars); p != NULL;
1651		     p = strpbrk(value, escape_chars)) {
1652			if (p > value)
1653				fwrite(value, 1, p - value, stdout);
1654			putchar('\\');
1655			putchar(*p);
1656			value = p + 1;
1657		}
1658
1659		/* print the rest and finish the double quoted
1660		   string */
1661		fputs(value, stdout);
1662		printf("\" ");
1663	}
1664}
1665
1666/**
1667 * Check for option-intrapositional negation.
1668 * Do not use in new code.
1669 */
1670int xtables_check_inverse(const char option[], int *invert,
1671			  int *my_optind, int argc, char **argv)
1672{
1673	if (option == NULL || strcmp(option, "!") != 0)
1674		return false;
1675
1676	fprintf(stderr, "Using intrapositioned negation "
1677	        "(`--option ! this`) is deprecated in favor of "
1678	        "extrapositioned (`! --option this`).\n");
1679
1680	if (*invert)
1681		xt_params->exit_err(PARAMETER_PROBLEM,
1682			   "Multiple `!' flags not allowed");
1683	*invert = true;
1684	if (my_optind != NULL) {
1685		optarg = argv[*my_optind];
1686		++*my_optind;
1687		if (argc && *my_optind > argc)
1688			xt_params->exit_err(PARAMETER_PROBLEM,
1689				   "no argument following `!'");
1690	}
1691
1692	return true;
1693}
1694
1695const struct xtables_pprot xtables_chain_protos[] = {
1696	{"tcp",       IPPROTO_TCP},
1697	{"sctp",      IPPROTO_SCTP},
1698	{"udp",       IPPROTO_UDP},
1699	{"udplite",   IPPROTO_UDPLITE},
1700	{"icmp",      IPPROTO_ICMP},
1701	{"icmpv6",    IPPROTO_ICMPV6},
1702	{"ipv6-icmp", IPPROTO_ICMPV6},
1703	{"esp",       IPPROTO_ESP},
1704	{"ah",        IPPROTO_AH},
1705	{"ipv6-mh",   IPPROTO_MH},
1706	{"mh",        IPPROTO_MH},
1707	{"all",       0},
1708	{NULL},
1709};
1710
1711uint16_t
1712xtables_parse_protocol(const char *s)
1713{
1714	unsigned int proto;
1715
1716	if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) {
1717		struct protoent *pent;
1718
1719		/* first deal with the special case of 'all' to prevent
1720		 * people from being able to redefine 'all' in nsswitch
1721		 * and/or provoke expensive [not working] ldap/nis/...
1722		 * lookups */
1723		if (!strcmp(s, "all"))
1724			return 0;
1725
1726		if ((pent = getprotobyname(s)))
1727			proto = pent->p_proto;
1728		else {
1729			unsigned int i;
1730			for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
1731				if (xtables_chain_protos[i].name == NULL)
1732					continue;
1733
1734				if (strcmp(s, xtables_chain_protos[i].name) == 0) {
1735					proto = xtables_chain_protos[i].num;
1736					break;
1737				}
1738			}
1739			if (i == ARRAY_SIZE(xtables_chain_protos))
1740				xt_params->exit_err(PARAMETER_PROBLEM,
1741					   "unknown protocol `%s' specified",
1742					   s);
1743		}
1744	}
1745
1746	return proto;
1747}
1748