xtables.c revision 1dc27393b7ba401e6228a5ee2472a6eb72836c43
1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/*
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * (C) 2000-2006 by the netfilter coreteam <coreteam@netfilter.org>:
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath *
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
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 += 256;
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
733void xtables_register_match(struct xtables_match *me)
734{
735	struct xtables_match **i, *old;
736
737	if (me->version == NULL) {
738		fprintf(stderr, "%s: match %s<%u> is missing a version\n",
739		        xt_params->program_name, me->name, me->revision);
740		exit(1);
741	}
742	if (strcmp(me->version, XTABLES_VERSION) != 0) {
743		fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
744		        "but \"%s\" is required.\n",
745			xt_params->program_name, me->name,
746			me->version, XTABLES_VERSION);
747		exit(1);
748	}
749
750	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
751		fprintf(stderr, "%s: target `%s' has invalid name\n",
752			xt_params->program_name, me->name);
753		exit(1);
754	}
755
756	if (me->family >= NPROTO) {
757		fprintf(stderr,
758			"%s: BUG: match %s has invalid protocol family\n",
759			xt_params->program_name, me->name);
760		exit(1);
761	}
762
763	/* ignore not interested match */
764	if (me->family != afinfo->family && me->family != AF_UNSPEC)
765		return;
766
767	old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
768	if (old) {
769		if (old->revision == me->revision &&
770		    old->family == me->family) {
771			fprintf(stderr,
772				"%s: match `%s' already registered.\n",
773				xt_params->program_name, me->name);
774			exit(1);
775		}
776
777		/* Now we have two (or more) options, check compatibility. */
778		if (compatible_match_revision(old->name, old->revision)
779		    && old->revision > me->revision)
780			return;
781
782		/* See if new match can be used. */
783		if (!compatible_match_revision(me->name, me->revision))
784			return;
785
786		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
787		if (old->revision == me->revision && me->family == AF_UNSPEC)
788			return;
789
790		/* Delete old one. */
791		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
792		*i = old->next;
793	}
794
795	if (me->size != XT_ALIGN(me->size)) {
796		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
797		        xt_params->program_name, me->name,
798		        (unsigned int)me->size);
799		exit(1);
800	}
801
802	/* Append to list. */
803	for (i = &xtables_matches; *i; i = &(*i)->next);
804	me->next = NULL;
805	*i = me;
806
807	me->m = NULL;
808	me->mflags = 0;
809}
810
811void xtables_register_matches(struct xtables_match *match, unsigned int n)
812{
813	do {
814		xtables_register_match(&match[--n]);
815	} while (n > 0);
816}
817
818void xtables_register_target(struct xtables_target *me)
819{
820	struct xtables_target *old;
821
822	if (me->version == NULL) {
823		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
824		        xt_params->program_name, me->name, me->revision);
825		exit(1);
826	}
827	if (strcmp(me->version, XTABLES_VERSION) != 0) {
828		fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
829		        "but \"%s\" is required.\n",
830			xt_params->program_name, me->name,
831			me->version, XTABLES_VERSION);
832		exit(1);
833	}
834
835	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
836		fprintf(stderr, "%s: target `%s' has invalid name\n",
837			xt_params->program_name, me->name);
838		exit(1);
839	}
840
841	if (me->family >= NPROTO) {
842		fprintf(stderr,
843			"%s: BUG: target %s has invalid protocol family\n",
844			xt_params->program_name, me->name);
845		exit(1);
846	}
847
848	/* ignore not interested target */
849	if (me->family != afinfo->family && me->family != AF_UNSPEC)
850		return;
851
852	old = xtables_find_target(me->name, XTF_DURING_LOAD);
853	if (old) {
854		struct xtables_target **i;
855
856		if (old->revision == me->revision &&
857		    old->family == me->family) {
858			fprintf(stderr,
859				"%s: target `%s' already registered.\n",
860				xt_params->program_name, me->name);
861			exit(1);
862		}
863
864		/* Now we have two (or more) options, check compatibility. */
865		if (compatible_target_revision(old->name, old->revision)
866		    && old->revision > me->revision)
867			return;
868
869		/* See if new target can be used. */
870		if (!compatible_target_revision(me->name, me->revision))
871			return;
872
873		/* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
874		if (old->revision == me->revision && me->family == AF_UNSPEC)
875			return;
876
877		/* Delete old one. */
878		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
879		*i = old->next;
880	}
881
882	if (me->size != XT_ALIGN(me->size)) {
883		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
884		        xt_params->program_name, me->name,
885		        (unsigned int)me->size);
886		exit(1);
887	}
888
889	/* Prepend to list. */
890	me->next = xtables_targets;
891	xtables_targets = me;
892	me->t = NULL;
893	me->tflags = 0;
894}
895
896void xtables_register_targets(struct xtables_target *target, unsigned int n)
897{
898	do {
899		xtables_register_target(&target[--n]);
900	} while (n > 0);
901}
902
903/**
904 * xtables_param_act - act on condition
905 * @status:	a constant from enum xtables_exittype
906 *
907 * %XTF_ONLY_ONCE: print error message that option may only be used once.
908 * @p1:		module name (e.g. "mark")
909 * @p2(...):	option in conflict (e.g. "--mark")
910 * @p3(...):	condition to match on (see extensions/ for examples)
911 *
912 * %XTF_NO_INVERT: option does not support inversion
913 * @p1:		module name
914 * @p2:		option in conflict
915 * @p3:		condition to match on
916 *
917 * %XTF_BAD_VALUE: bad value for option
918 * @p1:		module name
919 * @p2:		option with which the problem occured (e.g. "--mark")
920 * @p3:		string the user passed in (e.g. "99999999999999")
921 *
922 * %XTF_ONE_ACTION: two mutually exclusive actions have been specified
923 * @p1:		module name
924 *
925 * Displays an error message and exits the program.
926 */
927void xtables_param_act(unsigned int status, const char *p1, ...)
928{
929	const char *p2, *p3;
930	va_list args;
931	bool b;
932
933	va_start(args, p1);
934
935	switch (status) {
936	case XTF_ONLY_ONCE:
937		p2 = va_arg(args, const char *);
938		b  = va_arg(args, unsigned int);
939		if (!b)
940			return;
941		xt_params->exit_err(PARAMETER_PROBLEM,
942		           "%s: \"%s\" option may only be specified once",
943		           p1, p2);
944		break;
945	case XTF_NO_INVERT:
946		p2 = va_arg(args, const char *);
947		b  = va_arg(args, unsigned int);
948		if (!b)
949			return;
950		xt_params->exit_err(PARAMETER_PROBLEM,
951		           "%s: \"%s\" option cannot be inverted", p1, p2);
952		break;
953	case XTF_BAD_VALUE:
954		p2 = va_arg(args, const char *);
955		p3 = va_arg(args, const char *);
956		xt_params->exit_err(PARAMETER_PROBLEM,
957		           "%s: Bad value for \"%s\" option: \"%s\"",
958		           p1, p2, p3);
959		break;
960	case XTF_ONE_ACTION:
961		b = va_arg(args, unsigned int);
962		if (!b)
963			return;
964		xt_params->exit_err(PARAMETER_PROBLEM,
965		           "%s: At most one action is possible", p1);
966		break;
967	default:
968		xt_params->exit_err(status, p1, args);
969		break;
970	}
971
972	va_end(args);
973}
974
975const char *xtables_ipaddr_to_numeric(const struct in_addr *addrp)
976{
977	static char buf[20];
978	const unsigned char *bytep = (const void *)&addrp->s_addr;
979
980	sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
981	return buf;
982}
983
984static const char *ipaddr_to_host(const struct in_addr *addr)
985{
986	struct hostent *host;
987
988	host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET);
989	if (host == NULL)
990		return NULL;
991
992	return host->h_name;
993}
994
995static const char *ipaddr_to_network(const struct in_addr *addr)
996{
997	struct netent *net;
998
999	if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL)
1000		return net->n_name;
1001
1002	return NULL;
1003}
1004
1005const char *xtables_ipaddr_to_anyname(const struct in_addr *addr)
1006{
1007	const char *name;
1008
1009	if ((name = ipaddr_to_host(addr)) != NULL ||
1010	    (name = ipaddr_to_network(addr)) != NULL)
1011		return name;
1012
1013	return xtables_ipaddr_to_numeric(addr);
1014}
1015
1016const char *xtables_ipmask_to_numeric(const struct in_addr *mask)
1017{
1018	static char buf[20];
1019	uint32_t maskaddr, bits;
1020	int i;
1021
1022	maskaddr = ntohl(mask->s_addr);
1023
1024	if (maskaddr == 0xFFFFFFFFL)
1025		/* we don't want to see "/32" */
1026		return "";
1027
1028	i = 32;
1029	bits = 0xFFFFFFFEL;
1030	while (--i >= 0 && maskaddr != bits)
1031		bits <<= 1;
1032	if (i >= 0)
1033		sprintf(buf, "/%d", i);
1034	else
1035		/* mask was not a decent combination of 1's and 0's */
1036		sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
1037
1038	return buf;
1039}
1040
1041static struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask)
1042{
1043	static struct in_addr addr;
1044	unsigned char *addrp;
1045	unsigned int onebyte;
1046	char buf[20], *p, *q;
1047	int i;
1048
1049	/* copy dotted string, because we need to modify it */
1050	strncpy(buf, dotted, sizeof(buf) - 1);
1051	buf[sizeof(buf) - 1] = '\0';
1052	addrp = (void *)&addr.s_addr;
1053
1054	p = buf;
1055	for (i = 0; i < 3; ++i) {
1056		if ((q = strchr(p, '.')) == NULL) {
1057			if (is_mask)
1058				return NULL;
1059
1060			/* autocomplete, this is a network address */
1061			if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1062				return NULL;
1063
1064			addrp[i] = onebyte;
1065			while (i < 3)
1066				addrp[++i] = 0;
1067
1068			return &addr;
1069		}
1070
1071		*q = '\0';
1072		if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1073			return NULL;
1074
1075		addrp[i] = onebyte;
1076		p = q + 1;
1077	}
1078
1079	/* we have checked 3 bytes, now we check the last one */
1080	if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1081		return NULL;
1082
1083	addrp[3] = onebyte;
1084	return &addr;
1085}
1086
1087struct in_addr *xtables_numeric_to_ipaddr(const char *dotted)
1088{
1089	return __numeric_to_ipaddr(dotted, false);
1090}
1091
1092struct in_addr *xtables_numeric_to_ipmask(const char *dotted)
1093{
1094	return __numeric_to_ipaddr(dotted, true);
1095}
1096
1097static struct in_addr *network_to_ipaddr(const char *name)
1098{
1099	static struct in_addr addr;
1100	struct netent *net;
1101
1102	if ((net = getnetbyname(name)) != NULL) {
1103		if (net->n_addrtype != AF_INET)
1104			return NULL;
1105		addr.s_addr = htonl(net->n_net);
1106		return &addr;
1107	}
1108
1109	return NULL;
1110}
1111
1112static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
1113{
1114	struct hostent *host;
1115	struct in_addr *addr;
1116	unsigned int i;
1117
1118	*naddr = 0;
1119	if ((host = gethostbyname(name)) != NULL) {
1120		if (host->h_addrtype != AF_INET ||
1121		    host->h_length != sizeof(struct in_addr))
1122			return NULL;
1123
1124		while (host->h_addr_list[*naddr] != NULL)
1125			++*naddr;
1126		addr = xtables_calloc(*naddr, sizeof(struct in_addr) * *naddr);
1127		for (i = 0; i < *naddr; i++)
1128			memcpy(&addr[i], host->h_addr_list[i],
1129			       sizeof(struct in_addr));
1130		return addr;
1131	}
1132
1133	return NULL;
1134}
1135
1136static struct in_addr *
1137ipparse_hostnetwork(const char *name, unsigned int *naddrs)
1138{
1139	struct in_addr *addrptmp, *addrp;
1140
1141	if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL ||
1142	    (addrptmp = network_to_ipaddr(name)) != NULL) {
1143		addrp = xtables_malloc(sizeof(struct in_addr));
1144		memcpy(addrp, addrptmp, sizeof(*addrp));
1145		*naddrs = 1;
1146		return addrp;
1147	}
1148	if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL)
1149		return addrptmp;
1150
1151	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1152}
1153
1154static struct in_addr *parse_ipmask(const char *mask)
1155{
1156	static struct in_addr maskaddr;
1157	struct in_addr *addrp;
1158	unsigned int bits;
1159
1160	if (mask == NULL) {
1161		/* no mask at all defaults to 32 bits */
1162		maskaddr.s_addr = 0xFFFFFFFF;
1163		return &maskaddr;
1164	}
1165	if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL)
1166		/* dotted_to_addr already returns a network byte order addr */
1167		return addrp;
1168	if (!xtables_strtoui(mask, NULL, &bits, 0, 32))
1169		xt_params->exit_err(PARAMETER_PROBLEM,
1170			   "invalid mask `%s' specified", mask);
1171	if (bits != 0) {
1172		maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
1173		return &maskaddr;
1174	}
1175
1176	maskaddr.s_addr = 0U;
1177	return &maskaddr;
1178}
1179
1180void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
1181                              struct in_addr **maskpp, unsigned int *naddrs)
1182{
1183	struct in_addr *addrp;
1184	char buf[256], *p;
1185	unsigned int len, i, j, n, count = 1;
1186	const char *loop = name;
1187
1188	while ((loop = strchr(loop, ',')) != NULL) {
1189		++count;
1190		++loop; /* skip ',' */
1191	}
1192
1193	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
1194	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
1195
1196	loop = name;
1197
1198	for (i = 0; i < count; ++i) {
1199		if (loop == NULL)
1200			break;
1201		if (*loop == ',')
1202			++loop;
1203		if (*loop == '\0')
1204			break;
1205		p = strchr(loop, ',');
1206		if (p != NULL)
1207			len = p - loop;
1208		else
1209			len = strlen(loop);
1210		if (len == 0 || sizeof(buf) - 1 < len)
1211			break;
1212
1213		strncpy(buf, loop, len);
1214		buf[len] = '\0';
1215		loop += len;
1216		if ((p = strrchr(buf, '/')) != NULL) {
1217			*p = '\0';
1218			addrp = parse_ipmask(p + 1);
1219		} else {
1220			addrp = parse_ipmask(NULL);
1221		}
1222		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1223
1224		/* if a null mask is given, the name is ignored, like in "any/0" */
1225		if ((*maskpp + i)->s_addr == 0)
1226			/*
1227			 * A bit pointless to process multiple addresses
1228			 * in this case...
1229			 */
1230			strcpy(buf, "0.0.0.0");
1231
1232		addrp = ipparse_hostnetwork(buf, &n);
1233		if (n > 1) {
1234			count += n - 1;
1235			*addrpp = xtables_realloc(*addrpp,
1236			          sizeof(struct in_addr) * count);
1237			*maskpp = xtables_realloc(*maskpp,
1238			          sizeof(struct in_addr) * count);
1239			for (j = 0; j < n; ++j)
1240				/* for each new addr */
1241				memcpy(*addrpp + i + j, addrp + j,
1242				       sizeof(*addrp));
1243			for (j = 1; j < n; ++j)
1244				/* for each new mask */
1245				memcpy(*maskpp + i + j, *maskpp + i,
1246				       sizeof(*addrp));
1247			i += n - 1;
1248		} else {
1249			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1250		}
1251		/* free what ipparse_hostnetwork had allocated: */
1252		free(addrp);
1253	}
1254	*naddrs = count;
1255	for (i = 0; i < n; ++i)
1256		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
1257}
1258
1259
1260/**
1261 * xtables_ipparse_any - transform arbitrary name to in_addr
1262 *
1263 * Possible inputs (pseudo regex):
1264 * 	m{^($hostname|$networkname|$ipaddr)(/$mask)?}
1265 * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname"
1266 */
1267void xtables_ipparse_any(const char *name, struct in_addr **addrpp,
1268                         struct in_addr *maskp, unsigned int *naddrs)
1269{
1270	unsigned int i, j, k, n;
1271	struct in_addr *addrp;
1272	char buf[256], *p;
1273
1274	strncpy(buf, name, sizeof(buf) - 1);
1275	buf[sizeof(buf) - 1] = '\0';
1276	if ((p = strrchr(buf, '/')) != NULL) {
1277		*p = '\0';
1278		addrp = parse_ipmask(p + 1);
1279	} else {
1280		addrp = parse_ipmask(NULL);
1281	}
1282	memcpy(maskp, addrp, sizeof(*maskp));
1283
1284	/* if a null mask is given, the name is ignored, like in "any/0" */
1285	if (maskp->s_addr == 0U)
1286		strcpy(buf, "0.0.0.0");
1287
1288	addrp = *addrpp = ipparse_hostnetwork(buf, naddrs);
1289	n = *naddrs;
1290	for (i = 0, j = 0; i < n; ++i) {
1291		addrp[j++].s_addr &= maskp->s_addr;
1292		for (k = 0; k < j - 1; ++k)
1293			if (addrp[k].s_addr == addrp[j-1].s_addr) {
1294				--*naddrs;
1295				--j;
1296				break;
1297			}
1298	}
1299}
1300
1301const char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp)
1302{
1303	/* 0000:0000:0000:0000:0000:000.000.000.000
1304	 * 0000:0000:0000:0000:0000:0000:0000:0000 */
1305	static char buf[50+1];
1306	return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
1307}
1308
1309static const char *ip6addr_to_host(const struct in6_addr *addr)
1310{
1311	static char hostname[NI_MAXHOST];
1312	struct sockaddr_in6 saddr;
1313	int err;
1314
1315	memset(&saddr, 0, sizeof(struct sockaddr_in6));
1316	memcpy(&saddr.sin6_addr, addr, sizeof(*addr));
1317	saddr.sin6_family = AF_INET6;
1318
1319	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6),
1320	      hostname, sizeof(hostname) - 1, NULL, 0, 0);
1321	if (err != 0) {
1322#ifdef DEBUG
1323		fprintf(stderr,"IP2Name: %s\n",gai_strerror(err));
1324#endif
1325		return NULL;
1326	}
1327
1328#ifdef DEBUG
1329	fprintf (stderr, "\naddr2host: %s\n", hostname);
1330#endif
1331	return hostname;
1332}
1333
1334const char *xtables_ip6addr_to_anyname(const struct in6_addr *addr)
1335{
1336	const char *name;
1337
1338	if ((name = ip6addr_to_host(addr)) != NULL)
1339		return name;
1340
1341	return xtables_ip6addr_to_numeric(addr);
1342}
1343
1344static int ip6addr_prefix_length(const struct in6_addr *k)
1345{
1346	unsigned int bits = 0;
1347	uint32_t a, b, c, d;
1348
1349	a = ntohl(k->s6_addr32[0]);
1350	b = ntohl(k->s6_addr32[1]);
1351	c = ntohl(k->s6_addr32[2]);
1352	d = ntohl(k->s6_addr32[3]);
1353	while (a & 0x80000000U) {
1354		++bits;
1355		a <<= 1;
1356		a  |= (b >> 31) & 1;
1357		b <<= 1;
1358		b  |= (c >> 31) & 1;
1359		c <<= 1;
1360		c  |= (d >> 31) & 1;
1361		d <<= 1;
1362	}
1363	if (a != 0 || b != 0 || c != 0 || d != 0)
1364		return -1;
1365	return bits;
1366}
1367
1368const char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
1369{
1370	static char buf[50+2];
1371	int l = ip6addr_prefix_length(addrp);
1372
1373	if (l == -1) {
1374		strcpy(buf, "/");
1375		strcat(buf, xtables_ip6addr_to_numeric(addrp));
1376		return buf;
1377	}
1378	sprintf(buf, "/%d", l);
1379	return buf;
1380}
1381
1382struct in6_addr *xtables_numeric_to_ip6addr(const char *num)
1383{
1384	static struct in6_addr ap;
1385	int err;
1386
1387	if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
1388		return &ap;
1389#ifdef DEBUG
1390	fprintf(stderr, "\nnumeric2addr: %d\n", err);
1391#endif
1392	return NULL;
1393}
1394
1395static struct in6_addr *
1396host_to_ip6addr(const char *name, unsigned int *naddr)
1397{
1398	static struct in6_addr *addr;
1399	struct addrinfo hints;
1400	struct addrinfo *res;
1401	int err;
1402
1403	memset(&hints, 0, sizeof(hints));
1404	hints.ai_flags    = AI_CANONNAME;
1405	hints.ai_family   = AF_INET6;
1406	hints.ai_socktype = SOCK_RAW;
1407	hints.ai_protocol = IPPROTO_IPV6;
1408	hints.ai_next     = NULL;
1409
1410	*naddr = 0;
1411	if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
1412#ifdef DEBUG
1413		fprintf(stderr,"Name2IP: %s\n",gai_strerror(err));
1414#endif
1415		return NULL;
1416	} else {
1417		if (res->ai_family != AF_INET6 ||
1418		    res->ai_addrlen != sizeof(struct sockaddr_in6))
1419			return NULL;
1420
1421#ifdef DEBUG
1422		fprintf(stderr, "resolved: len=%d  %s ", res->ai_addrlen,
1423		        xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr));
1424#endif
1425		/* Get the first element of the address-chain */
1426		addr = xtables_malloc(sizeof(struct in6_addr));
1427		memcpy(addr, &((const struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
1428		       sizeof(struct in6_addr));
1429		freeaddrinfo(res);
1430		*naddr = 1;
1431		return addr;
1432	}
1433
1434	return NULL;
1435}
1436
1437static struct in6_addr *network_to_ip6addr(const char *name)
1438{
1439	/*	abort();*/
1440	/* TODO: not implemented yet, but the exception breaks the
1441	 *       name resolvation */
1442	return NULL;
1443}
1444
1445static struct in6_addr *
1446ip6parse_hostnetwork(const char *name, unsigned int *naddrs)
1447{
1448	struct in6_addr *addrp, *addrptmp;
1449
1450	if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL ||
1451	    (addrptmp = network_to_ip6addr(name)) != NULL) {
1452		addrp = xtables_malloc(sizeof(struct in6_addr));
1453		memcpy(addrp, addrptmp, sizeof(*addrp));
1454		*naddrs = 1;
1455		return addrp;
1456	}
1457	if ((addrp = host_to_ip6addr(name, naddrs)) != NULL)
1458		return addrp;
1459
1460	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1461}
1462
1463static struct in6_addr *parse_ip6mask(char *mask)
1464{
1465	static struct in6_addr maskaddr;
1466	struct in6_addr *addrp;
1467	unsigned int bits;
1468
1469	if (mask == NULL) {
1470		/* no mask at all defaults to 128 bits */
1471		memset(&maskaddr, 0xff, sizeof maskaddr);
1472		return &maskaddr;
1473	}
1474	if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL)
1475		return addrp;
1476	if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
1477		xt_params->exit_err(PARAMETER_PROBLEM,
1478			   "invalid mask `%s' specified", mask);
1479	if (bits != 0) {
1480		char *p = (void *)&maskaddr;
1481		memset(p, 0xff, bits / 8);
1482		memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
1483		p[bits/8] = 0xff << (8 - (bits & 7));
1484		return &maskaddr;
1485	}
1486
1487	memset(&maskaddr, 0, sizeof(maskaddr));
1488	return &maskaddr;
1489}
1490
1491void
1492xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
1493		      struct in6_addr **maskpp, unsigned int *naddrs)
1494{
1495	static const struct in6_addr zero_addr;
1496	struct in6_addr *addrp;
1497	char buf[256], *p;
1498	unsigned int len, i, j, n, count = 1;
1499	const char *loop = name;
1500
1501	while ((loop = strchr(loop, ',')) != NULL) {
1502		++count;
1503		++loop; /* skip ',' */
1504	}
1505
1506	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
1507	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
1508
1509	loop = name;
1510
1511	for (i = 0; i < count /*NB: count can grow*/; ++i) {
1512		if (loop == NULL)
1513			break;
1514		if (*loop == ',')
1515			++loop;
1516		if (*loop == '\0')
1517			break;
1518		p = strchr(loop, ',');
1519		if (p != NULL)
1520			len = p - loop;
1521		else
1522			len = strlen(loop);
1523		if (len == 0 || sizeof(buf) - 1 < len)
1524			break;
1525
1526		strncpy(buf, loop, len);
1527		buf[len] = '\0';
1528		loop += len;
1529		if ((p = strrchr(buf, '/')) != NULL) {
1530			*p = '\0';
1531			addrp = parse_ip6mask(p + 1);
1532		} else {
1533			addrp = parse_ip6mask(NULL);
1534		}
1535		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1536
1537		/* if a null mask is given, the name is ignored, like in "any/0" */
1538		if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0)
1539			strcpy(buf, "::");
1540
1541		addrp = ip6parse_hostnetwork(buf, &n);
1542		/* ip6parse_hostnetwork only ever returns one IP
1543		address (it exits if the resolution fails).
1544		Therefore, n will always be 1 here.  Leaving the
1545		code below in anyway in case ip6parse_hostnetwork
1546		is improved some day to behave like
1547		ipparse_hostnetwork: */
1548		if (n > 1) {
1549			count += n - 1;
1550			*addrpp = xtables_realloc(*addrpp,
1551			          sizeof(struct in6_addr) * count);
1552			*maskpp = xtables_realloc(*maskpp,
1553			          sizeof(struct in6_addr) * count);
1554			for (j = 0; j < n; ++j)
1555				/* for each new addr */
1556				memcpy(*addrpp + i + j, addrp + j,
1557				       sizeof(*addrp));
1558			for (j = 1; j < n; ++j)
1559				/* for each new mask */
1560				memcpy(*maskpp + i + j, *maskpp + i,
1561				       sizeof(*addrp));
1562			i += n - 1;
1563		} else {
1564			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1565		}
1566		/* free what ip6parse_hostnetwork had allocated: */
1567		free(addrp);
1568	}
1569	*naddrs = count;
1570	for (i = 0; i < n; ++i)
1571		for (j = 0; j < 4; ++j)
1572			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
1573}
1574
1575void xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
1576                          struct in6_addr *maskp, unsigned int *naddrs)
1577{
1578	static const struct in6_addr zero_addr;
1579	struct in6_addr *addrp;
1580	unsigned int i, j, k, n;
1581	char buf[256], *p;
1582
1583	strncpy(buf, name, sizeof(buf) - 1);
1584	buf[sizeof(buf)-1] = '\0';
1585	if ((p = strrchr(buf, '/')) != NULL) {
1586		*p = '\0';
1587		addrp = parse_ip6mask(p + 1);
1588	} else {
1589		addrp = parse_ip6mask(NULL);
1590	}
1591	memcpy(maskp, addrp, sizeof(*maskp));
1592
1593	/* if a null mask is given, the name is ignored, like in "any/0" */
1594	if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0)
1595		strcpy(buf, "::");
1596
1597	addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs);
1598	n = *naddrs;
1599	for (i = 0, j = 0; i < n; ++i) {
1600		for (k = 0; k < 4; ++k)
1601			addrp[j].s6_addr32[k] &= maskp->s6_addr32[k];
1602		++j;
1603		for (k = 0; k < j - 1; ++k)
1604			if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
1605				--*naddrs;
1606				--j;
1607				break;
1608			}
1609	}
1610}
1611
1612void xtables_save_string(const char *value)
1613{
1614	static const char no_quote_chars[] = "_-0123456789"
1615		"abcdefghijklmnopqrstuvwxyz"
1616		"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1617	static const char escape_chars[] = "\"\\'";
1618	size_t length;
1619	const char *p;
1620
1621	length = strcspn(value, no_quote_chars);
1622	if (length > 0 && value[length] == 0) {
1623		/* no quoting required */
1624		fputs(value, stdout);
1625		putchar(' ');
1626	} else {
1627		/* there is at least one dangerous character in the
1628		   value, which we have to quote.  Write double quotes
1629		   around the value and escape special characters with
1630		   a backslash */
1631		putchar('"');
1632
1633		for (p = strpbrk(value, escape_chars); p != NULL;
1634		     p = strpbrk(value, escape_chars)) {
1635			if (p > value)
1636				fwrite(value, 1, p - value, stdout);
1637			putchar('\\');
1638			putchar(*p);
1639			value = p + 1;
1640		}
1641
1642		/* print the rest and finish the double quoted
1643		   string */
1644		fputs(value, stdout);
1645		printf("\" ");
1646	}
1647}
1648
1649/**
1650 * Check for option-intrapositional negation.
1651 * Do not use in new code.
1652 */
1653int xtables_check_inverse(const char option[], int *invert,
1654			  int *my_optind, int argc, char **argv)
1655{
1656	if (option == NULL || strcmp(option, "!") != 0)
1657		return false;
1658
1659	fprintf(stderr, "Using intrapositioned negation "
1660	        "(`--option ! this`) is deprecated in favor of "
1661	        "extrapositioned (`! --option this`).\n");
1662
1663	if (*invert)
1664		xt_params->exit_err(PARAMETER_PROBLEM,
1665			   "Multiple `!' flags not allowed");
1666	*invert = true;
1667	if (my_optind != NULL) {
1668		optarg = argv[*my_optind];
1669		++*my_optind;
1670		if (argc && *my_optind > argc)
1671			xt_params->exit_err(PARAMETER_PROBLEM,
1672				   "no argument following `!'");
1673	}
1674
1675	return true;
1676}
1677
1678const struct xtables_pprot xtables_chain_protos[] = {
1679	{"tcp",       IPPROTO_TCP},
1680	{"sctp",      IPPROTO_SCTP},
1681	{"udp",       IPPROTO_UDP},
1682	{"udplite",   IPPROTO_UDPLITE},
1683	{"icmp",      IPPROTO_ICMP},
1684	{"icmpv6",    IPPROTO_ICMPV6},
1685	{"ipv6-icmp", IPPROTO_ICMPV6},
1686	{"esp",       IPPROTO_ESP},
1687	{"ah",        IPPROTO_AH},
1688	{"ipv6-mh",   IPPROTO_MH},
1689	{"mh",        IPPROTO_MH},
1690	{"all",       0},
1691	{NULL},
1692};
1693
1694uint16_t
1695xtables_parse_protocol(const char *s)
1696{
1697	unsigned int proto;
1698
1699	if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) {
1700		struct protoent *pent;
1701
1702		/* first deal with the special case of 'all' to prevent
1703		 * people from being able to redefine 'all' in nsswitch
1704		 * and/or provoke expensive [not working] ldap/nis/...
1705		 * lookups */
1706		if (!strcmp(s, "all"))
1707			return 0;
1708
1709		if ((pent = getprotobyname(s)))
1710			proto = pent->p_proto;
1711		else {
1712			unsigned int i;
1713			for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
1714				if (xtables_chain_protos[i].name == NULL)
1715					continue;
1716
1717				if (strcmp(s, xtables_chain_protos[i].name) == 0) {
1718					proto = xtables_chain_protos[i].num;
1719					break;
1720				}
1721			}
1722			if (i == ARRAY_SIZE(xtables_chain_protos))
1723				xt_params->exit_err(PARAMETER_PROBLEM,
1724					   "unknown protocol `%s' specified",
1725					   s);
1726		}
1727	}
1728
1729	return proto;
1730}
1731