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