• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 #include "config.h"
19 #include <ctype.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <inttypes.h>
23 #include <netdb.h>
24 #include <spawn.h>
25 #include <stdarg.h>
26 #include <stdbool.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <sys/socket.h>
32 #include <sys/stat.h>
33 #include <sys/statfs.h>
34 #include <sys/types.h>
35 #include <sys/utsname.h>
36 #include <sys/wait.h>
37 #include <arpa/inet.h>
38 #if defined(HAVE_LINUX_MAGIC_H)
39 #	include <linux/magic.h> /* for PROC_SUPER_MAGIC */
40 #elif defined(HAVE_LINUX_PROC_FS_H)
41 #	include <linux/proc_fs.h>	/* Linux 2.4 */
42 #else
43 #	define PROC_SUPER_MAGIC	0x9fa0
44 #endif
45 
46 #include <xtables.h>
47 #include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */
48 #ifdef __BIONIC__
49 #include <linux/if_ether.h> /* ETH_ALEN */
50 #endif
51 #include <linux/netfilter_ipv4/ip_tables.h>
52 #include <linux/netfilter_ipv6/ip6_tables.h>
53 #include <libiptc/libxtc.h>
54 
55 #ifndef NO_SHARED_LIBS
56 #include <dlfcn.h>
57 #endif
58 #ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */
59 #	define IPT_SO_GET_REVISION_MATCH	(IPT_BASE_CTL + 2)
60 #	define IPT_SO_GET_REVISION_TARGET	(IPT_BASE_CTL + 3)
61 #endif
62 #ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */
63 #	define IP6T_SO_GET_REVISION_MATCH	68
64 #	define IP6T_SO_GET_REVISION_TARGET	69
65 #endif
66 #include <getopt.h>
67 #include "iptables/internal.h"
68 #include "xshared.h"
69 
70 #define NPROTO	255
71 
72 #ifndef PROC_SYS_MODPROBE
73 #define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
74 #endif
75 
76 /* we need this for ip6?tables-restore.  ip6?tables-restore.c sets line to the
77  * current line of the input file, in order  to give a more precise error
78  * message.  ip6?tables itself doesn't need this, so it is initialized to the
79  * magic number of -1 */
80 int line = -1;
81 
82 void basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
83 
84 struct xtables_globals *xt_params = NULL;
85 
basic_exit_err(enum xtables_exittype status,const char * msg,...)86 void basic_exit_err(enum xtables_exittype status, const char *msg, ...)
87 {
88 	va_list args;
89 
90 	va_start(args, msg);
91 	fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version);
92 	vfprintf(stderr, msg, args);
93 	va_end(args);
94 	fprintf(stderr, "\n");
95 	exit(status);
96 }
97 
xtables_free_opts(int unused)98 void xtables_free_opts(int unused)
99 {
100 	if (xt_params->opts != xt_params->orig_opts) {
101 		free(xt_params->opts);
102 		xt_params->opts = NULL;
103 	}
104 }
105 
xtables_merge_options(struct option * orig_opts,struct option * oldopts,const struct option * newopts,unsigned int * option_offset)106 struct option *xtables_merge_options(struct option *orig_opts,
107 				     struct option *oldopts,
108 				     const struct option *newopts,
109 				     unsigned int *option_offset)
110 {
111 	unsigned int num_oold = 0, num_old = 0, num_new = 0, i;
112 	struct option *merge, *mp;
113 
114 	if (newopts == NULL)
115 		return oldopts;
116 
117 	for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ;
118 	if (oldopts != NULL)
119 		for (num_old = 0; oldopts[num_old].name; num_old++) ;
120 	for (num_new = 0; newopts[num_new].name; num_new++) ;
121 
122 	/*
123 	 * Since @oldopts also has @orig_opts already (and does so at the
124 	 * start), skip these entries.
125 	 */
126 	if (oldopts != NULL) {
127 		oldopts += num_oold;
128 		num_old -= num_oold;
129 	}
130 
131 	merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1));
132 	if (merge == NULL)
133 		return NULL;
134 
135 	/* Let the base options -[ADI...] have precedence over everything */
136 	memcpy(merge, orig_opts, sizeof(*mp) * num_oold);
137 	mp = merge + num_oold;
138 
139 	/* Second, the new options */
140 	xt_params->option_offset += XT_OPTION_OFFSET_SCALE;
141 	*option_offset = xt_params->option_offset;
142 	memcpy(mp, newopts, sizeof(*mp) * num_new);
143 
144 	for (i = 0; i < num_new; ++i, ++mp)
145 		mp->val += *option_offset;
146 
147 	/* Third, the old options */
148 	if (oldopts != NULL) {
149 		memcpy(mp, oldopts, sizeof(*mp) * num_old);
150 		mp += num_old;
151 	}
152 	xtables_free_opts(0);
153 
154 	/* Clear trailing entry */
155 	memset(mp, 0, sizeof(*mp));
156 	return merge;
157 }
158 
159 static const struct xtables_afinfo afinfo_ipv4 = {
160 	.kmod          = "ip_tables",
161 	.proc_exists   = "/proc/net/ip_tables_names",
162 	.libprefix     = "libipt_",
163 	.family	       = NFPROTO_IPV4,
164 	.ipproto       = IPPROTO_IP,
165 	.so_rev_match  = IPT_SO_GET_REVISION_MATCH,
166 	.so_rev_target = IPT_SO_GET_REVISION_TARGET,
167 };
168 
169 static const struct xtables_afinfo afinfo_ipv6 = {
170 	.kmod          = "ip6_tables",
171 	.proc_exists   = "/proc/net/ip6_tables_names",
172 	.libprefix     = "libip6t_",
173 	.family        = NFPROTO_IPV6,
174 	.ipproto       = IPPROTO_IPV6,
175 	.so_rev_match  = IP6T_SO_GET_REVISION_MATCH,
176 	.so_rev_target = IP6T_SO_GET_REVISION_TARGET,
177 };
178 
179 /* Dummy families for arptables-compat and ebtables-compat. Leave structure
180  * fields that we don't use unset.
181  */
182 static const struct xtables_afinfo afinfo_bridge = {
183 	.libprefix     = "libebt_",
184 	.family        = NFPROTO_BRIDGE,
185 };
186 
187 static const struct xtables_afinfo afinfo_arp = {
188 	.libprefix     = "libarpt_",
189 	.family        = NFPROTO_ARP,
190 };
191 
192 const struct xtables_afinfo *afinfo;
193 
194 /* Search path for Xtables .so files */
195 static const char *xtables_libdir;
196 
197 /* the path to command to load kernel module */
198 const char *xtables_modprobe_program;
199 
200 /* Keep track of matches/targets pending full registration: linked lists. */
201 struct xtables_match *xtables_pending_matches;
202 struct xtables_target *xtables_pending_targets;
203 
204 /* Keep track of fully registered external matches/targets: linked lists. */
205 struct xtables_match *xtables_matches;
206 struct xtables_target *xtables_targets;
207 
208 /* Fully register a match/target which was previously partially registered. */
209 static bool xtables_fully_register_pending_match(struct xtables_match *me,
210 						 struct xtables_match *prev);
211 static bool xtables_fully_register_pending_target(struct xtables_target *me,
212 						  struct xtables_target *prev);
213 
214 #ifndef NO_SHARED_LIBS
215 /* registry for loaded shared objects to close later */
216 struct dlreg {
217 	struct dlreg *next;
218 	void *handle;
219 };
220 static struct dlreg *dlreg = NULL;
221 
dlreg_add(void * handle)222 static int dlreg_add(void *handle)
223 {
224 	struct dlreg *new = malloc(sizeof(*new));
225 
226 	if (!new)
227 		return -1;
228 
229 	new->handle = handle;
230 	new->next = dlreg;
231 	dlreg = new;
232 	return 0;
233 }
234 
dlreg_free(void)235 static void dlreg_free(void)
236 {
237 	struct dlreg *next;
238 
239 	while (dlreg) {
240 		next = dlreg->next;
241 		dlclose(dlreg->handle);
242 		free(dlreg);
243 		dlreg = next;
244 	}
245 }
246 #endif
247 
xtables_init(void)248 void xtables_init(void)
249 {
250 	xtables_libdir = getenv("XTABLES_LIBDIR");
251 	if (xtables_libdir != NULL)
252 		return;
253 	xtables_libdir = getenv("IPTABLES_LIB_DIR");
254 	if (xtables_libdir != NULL) {
255 		fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, "
256 		        "use XTABLES_LIBDIR.\n");
257 		return;
258 	}
259 	/*
260 	 * Well yes, IP6TABLES_LIB_DIR is of lower priority over
261 	 * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok
262 	 * for these env vars are deprecated anyhow, and in light of the
263 	 * (shared) libxt_*.so files, makes less sense to have
264 	 * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR.
265 	 */
266 	xtables_libdir = getenv("IP6TABLES_LIB_DIR");
267 	if (xtables_libdir != NULL) {
268 		fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, "
269 		        "use XTABLES_LIBDIR.\n");
270 		return;
271 	}
272 	xtables_libdir = XTABLES_LIBDIR;
273 }
274 
xtables_fini(void)275 void xtables_fini(void)
276 {
277 #ifndef NO_SHARED_LIBS
278 	dlreg_free();
279 #endif
280 }
281 
xtables_set_nfproto(uint8_t nfproto)282 void xtables_set_nfproto(uint8_t nfproto)
283 {
284 	switch (nfproto) {
285 	case NFPROTO_IPV4:
286 		afinfo = &afinfo_ipv4;
287 		break;
288 	case NFPROTO_IPV6:
289 		afinfo = &afinfo_ipv6;
290 		break;
291 	case NFPROTO_BRIDGE:
292 		afinfo = &afinfo_bridge;
293 		break;
294 	case NFPROTO_ARP:
295 		afinfo = &afinfo_arp;
296 		break;
297 	default:
298 		fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n",
299 		        __func__);
300 	}
301 }
302 
303 /**
304  * xtables_set_params - set the global parameters used by xtables
305  * @xtp:	input xtables_globals structure
306  *
307  * The app is expected to pass a valid xtables_globals data-filled
308  * with proper values
309  * @xtp cannot be NULL
310  *
311  * Returns -1 on failure to set and 0 on success
312  */
xtables_set_params(struct xtables_globals * xtp)313 int xtables_set_params(struct xtables_globals *xtp)
314 {
315 	if (!xtp) {
316 		fprintf(stderr, "%s: Illegal global params\n",__func__);
317 		return -1;
318 	}
319 
320 	xt_params = xtp;
321 
322 	if (!xt_params->exit_err)
323 		xt_params->exit_err = basic_exit_err;
324 
325 	return 0;
326 }
327 
xtables_init_all(struct xtables_globals * xtp,uint8_t nfproto)328 int xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto)
329 {
330 	xtables_init();
331 	xtables_set_nfproto(nfproto);
332 	return xtables_set_params(xtp);
333 }
334 
335 /**
336  * xtables_*alloc - wrappers that exit on failure
337  */
xtables_calloc(size_t count,size_t size)338 void *xtables_calloc(size_t count, size_t size)
339 {
340 	void *p;
341 
342 	if ((p = calloc(count, size)) == NULL) {
343 		perror("ip[6]tables: calloc failed");
344 		exit(1);
345 	}
346 
347 	return p;
348 }
349 
xtables_malloc(size_t size)350 void *xtables_malloc(size_t size)
351 {
352 	void *p;
353 
354 	if ((p = malloc(size)) == NULL) {
355 		perror("ip[6]tables: malloc failed");
356 		exit(1);
357 	}
358 
359 	return p;
360 }
361 
xtables_realloc(void * ptr,size_t size)362 void *xtables_realloc(void *ptr, size_t size)
363 {
364 	void *p;
365 
366 	if ((p = realloc(ptr, size)) == NULL) {
367 		perror("ip[6]tables: realloc failed");
368 		exit(1);
369 	}
370 
371 	return p;
372 }
373 
get_modprobe(void)374 static char *get_modprobe(void)
375 {
376 	int procfile;
377 	char *ret;
378 	int count;
379 
380 	procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
381 	if (procfile < 0)
382 		return NULL;
383 	if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) {
384 		fprintf(stderr, "Could not set close on exec: %s\n",
385 			strerror(errno));
386 		exit(1);
387 	}
388 
389 	ret = malloc(PATH_MAX);
390 	if (ret) {
391 		count = read(procfile, ret, PATH_MAX);
392 		if (count > 0 && count < PATH_MAX)
393 		{
394 			if (ret[count - 1] == '\n')
395 				ret[count - 1] = '\0';
396 			else
397 				ret[count] = '\0';
398 			close(procfile);
399 			return ret;
400 		}
401 	}
402 	free(ret);
403 	close(procfile);
404 	return NULL;
405 }
406 
xtables_insmod(const char * modname,const char * modprobe,bool quiet)407 int xtables_insmod(const char *modname, const char *modprobe, bool quiet)
408 {
409 	char *buf = NULL;
410 	char *argv[4];
411 	int status;
412 	pid_t pid;
413 
414 	/* If they don't explicitly set it, read out of kernel */
415 	if (!modprobe) {
416 		buf = get_modprobe();
417 		if (!buf)
418 			return -1;
419 		modprobe = buf;
420 	}
421 
422 	argv[0] = (char *)modprobe;
423 	argv[1] = (char *)modname;
424 	argv[2] = quiet ? "-q" : NULL;
425 	argv[3] = NULL;
426 
427 	/*
428 	 * Need to flush the buffer, or the child may output it again
429 	 * when switching the program thru execv.
430 	 */
431 	fflush(stdout);
432 
433 	if (posix_spawn(&pid, argv[0], NULL, NULL, argv, NULL)) {
434 		free(buf);
435 		return -1;
436 	} else {
437 		waitpid(pid, &status, 0);
438 	}
439 
440 	free(buf);
441 	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
442 		return 0;
443 	return -1;
444 }
445 
446 /* return true if a given file exists within procfs */
proc_file_exists(const char * filename)447 static bool proc_file_exists(const char *filename)
448 {
449 	struct stat s;
450 	struct statfs f;
451 
452 	if (lstat(filename, &s))
453 		return false;
454 	if (!S_ISREG(s.st_mode))
455 		return false;
456 	if (statfs(filename, &f))
457 		return false;
458 	if (f.f_type != PROC_SUPER_MAGIC)
459 		return false;
460 	return true;
461 }
462 
xtables_load_ko(const char * modprobe,bool quiet)463 int xtables_load_ko(const char *modprobe, bool quiet)
464 {
465 	static bool loaded = false;
466 	int ret;
467 
468 	if (loaded)
469 		return 0;
470 
471 	if (proc_file_exists(afinfo->proc_exists)) {
472 		loaded = true;
473 		return 0;
474 	};
475 
476 	ret = xtables_insmod(afinfo->kmod, modprobe, quiet);
477 	if (ret == 0)
478 		loaded = true;
479 
480 	return ret;
481 }
482 
483 /**
484  * xtables_strtou{i,l} - string to number conversion
485  * @s:	input string
486  * @end:	like strtoul's "end" pointer
487  * @value:	pointer for result
488  * @min:	minimum accepted value
489  * @max:	maximum accepted value
490  *
491  * If @end is NULL, we assume the caller wants a "strict strtoul", and hence
492  * "15a" is rejected.
493  * In either case, the value obtained is compared for min-max compliance.
494  * Base is always 0, i.e. autodetect depending on @s.
495  *
496  * Returns true/false whether number was accepted. On failure, *value has
497  * undefined contents.
498  */
xtables_strtoul(const char * s,char ** end,uintmax_t * value,uintmax_t min,uintmax_t max)499 bool xtables_strtoul(const char *s, char **end, uintmax_t *value,
500                      uintmax_t min, uintmax_t max)
501 {
502 	uintmax_t v;
503 	const char *p;
504 	char *my_end;
505 
506 	errno = 0;
507 	/* Since strtoul allows leading minus, we have to check for ourself. */
508 	for (p = s; isspace(*p); ++p)
509 		;
510 	if (*p == '-')
511 		return false;
512 	v = strtoumax(s, &my_end, 0);
513 	if (my_end == s)
514 		return false;
515 	if (end != NULL)
516 		*end = my_end;
517 
518 	if (errno != ERANGE && min <= v && (max == 0 || v <= max)) {
519 		if (value != NULL)
520 			*value = v;
521 		if (end == NULL)
522 			return *my_end == '\0';
523 		return true;
524 	}
525 
526 	return false;
527 }
528 
xtables_strtoui(const char * s,char ** end,unsigned int * value,unsigned int min,unsigned int max)529 bool xtables_strtoui(const char *s, char **end, unsigned int *value,
530                      unsigned int min, unsigned int max)
531 {
532 	uintmax_t v;
533 	bool ret;
534 
535 	ret = xtables_strtoul(s, end, &v, min, max);
536 	if (ret && value != NULL)
537 		*value = v;
538 	return ret;
539 }
540 
xtables_service_to_port(const char * name,const char * proto)541 int xtables_service_to_port(const char *name, const char *proto)
542 {
543 	struct servent *service;
544 
545 	if ((service = getservbyname(name, proto)) != NULL)
546 		return ntohs((unsigned short) service->s_port);
547 
548 	return -1;
549 }
550 
xtables_parse_port(const char * port,const char * proto)551 uint16_t xtables_parse_port(const char *port, const char *proto)
552 {
553 	unsigned int portnum;
554 
555 	if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) ||
556 	    (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1)
557 		return portnum;
558 
559 	xt_params->exit_err(PARAMETER_PROBLEM,
560 		   "invalid port/service `%s' specified", port);
561 }
562 
xtables_parse_interface(const char * arg,char * vianame,unsigned char * mask)563 void xtables_parse_interface(const char *arg, char *vianame,
564 			     unsigned char *mask)
565 {
566 	unsigned int vialen = strlen(arg);
567 	unsigned int i;
568 
569 	memset(mask, 0, IFNAMSIZ);
570 	memset(vianame, 0, IFNAMSIZ);
571 
572 	if (vialen + 1 > IFNAMSIZ)
573 		xt_params->exit_err(PARAMETER_PROBLEM,
574 			   "interface name `%s' must be shorter than IFNAMSIZ"
575 			   " (%i)", arg, IFNAMSIZ-1);
576 
577 	strcpy(vianame, arg);
578 	if (vialen == 0)
579 		return;
580 	else if (vianame[vialen - 1] == '+') {
581 		memset(mask, 0xFF, vialen - 1);
582 		/* Don't remove `+' here! -HW */
583 	} else {
584 		/* Include nul-terminator in match */
585 		memset(mask, 0xFF, vialen + 1);
586 	}
587 
588 	/* Display warning on invalid characters */
589 	for (i = 0; vianame[i]; i++) {
590 		if (vianame[i] == '/' || vianame[i] == ' ') {
591 			fprintf(stderr,	"Warning: weird character in interface"
592 				" `%s' ('/' and ' ' are not allowed by the kernel).\n",
593 				vianame);
594 			break;
595 		}
596 	}
597 }
598 
599 #ifndef NO_SHARED_LIBS
load_extension(const char * search_path,const char * af_prefix,const char * name,bool is_target)600 static void *load_extension(const char *search_path, const char *af_prefix,
601     const char *name, bool is_target)
602 {
603 	const char *all_prefixes[] = {af_prefix, "libxt_", NULL};
604 	const char **prefix;
605 	const char *dir = search_path, *next;
606 	void *ptr = NULL;
607 	struct stat sb;
608 	char path[256];
609 
610 	do {
611 		next = strchr(dir, ':');
612 		if (next == NULL)
613 			next = dir + strlen(dir);
614 
615 		for (prefix = all_prefixes; *prefix != NULL; ++prefix) {
616 			void *handle;
617 
618 			snprintf(path, sizeof(path), "%.*s/%s%s.so",
619 			         (unsigned int)(next - dir), dir,
620 			         *prefix, name);
621 
622 			if (stat(path, &sb) != 0) {
623 				if (errno == ENOENT)
624 					continue;
625 				fprintf(stderr, "%s: %s\n", path,
626 					strerror(errno));
627 				return NULL;
628 			}
629 			handle = dlopen(path, RTLD_NOW);
630 			if (handle == NULL) {
631 				fprintf(stderr, "%s: %s\n", path, dlerror());
632 				break;
633 			}
634 
635 			dlreg_add(handle);
636 
637 			if (is_target)
638 				ptr = xtables_find_target(name, XTF_DONT_LOAD);
639 			else
640 				ptr = xtables_find_match(name,
641 				      XTF_DONT_LOAD, NULL);
642 
643 			if (ptr != NULL)
644 				return ptr;
645 
646 			errno = ENOENT;
647 			return NULL;
648 		}
649 		dir = next + 1;
650 	} while (*next != '\0');
651 
652 	return NULL;
653 }
654 #endif
655 
extension_cmp(const char * name1,const char * name2,uint32_t family)656 static bool extension_cmp(const char *name1, const char *name2, uint32_t family)
657 {
658 	if (strcmp(name1, name2) == 0 &&
659 	    (family == afinfo->family ||
660 	     family == NFPROTO_UNSPEC))
661 		return true;
662 
663 	return false;
664 }
665 
666 struct xtables_match *
xtables_find_match(const char * name,enum xtables_tryload tryload,struct xtables_rule_match ** matches)667 xtables_find_match(const char *name, enum xtables_tryload tryload,
668 		   struct xtables_rule_match **matches)
669 {
670 	struct xtables_match *prev = NULL;
671 	struct xtables_match **dptr;
672 	struct xtables_match *ptr;
673 	const char *icmp6 = "icmp6";
674 
675 	if (strlen(name) >= XT_EXTENSION_MAXNAMELEN)
676 		xtables_error(PARAMETER_PROBLEM,
677 			   "Invalid match name \"%s\" (%u chars max)",
678 			   name, XT_EXTENSION_MAXNAMELEN - 1);
679 
680 	/* This is ugly as hell. Nonetheless, there is no way of changing
681 	 * this without hurting backwards compatibility */
682 	if ( (strcmp(name,"icmpv6") == 0) ||
683 	     (strcmp(name,"ipv6-icmp") == 0) ||
684 	     (strcmp(name,"icmp6") == 0) )
685 		name = icmp6;
686 
687 	/* Trigger delayed initialization */
688 	for (dptr = &xtables_pending_matches; *dptr; ) {
689 		if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) {
690 			ptr = *dptr;
691 			*dptr = (*dptr)->next;
692 			if (xtables_fully_register_pending_match(ptr, prev)) {
693 				prev = ptr;
694 				continue;
695 			} else if (prev) {
696 				continue;
697 			}
698 			*dptr = ptr;
699 		}
700 		dptr = &((*dptr)->next);
701 	}
702 
703 	for (ptr = xtables_matches; ptr; ptr = ptr->next) {
704 		if (extension_cmp(name, ptr->name, ptr->family)) {
705 			struct xtables_match *clone;
706 
707 			/* First match of this type: */
708 			if (ptr->m == NULL)
709 				break;
710 
711 			/* Second and subsequent clones */
712 			clone = xtables_malloc(sizeof(struct xtables_match));
713 			memcpy(clone, ptr, sizeof(struct xtables_match));
714 			clone->udata = NULL;
715 			clone->mflags = 0;
716 			/* This is a clone: */
717 			clone->next = clone;
718 
719 			ptr = clone;
720 			break;
721 		}
722 	}
723 
724 #ifndef NO_SHARED_LIBS
725 	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
726 		ptr = load_extension(xtables_libdir, afinfo->libprefix,
727 		      name, false);
728 
729 		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
730 			xt_params->exit_err(PARAMETER_PROBLEM,
731 				   "Couldn't load match `%s':%s\n",
732 				   name, strerror(errno));
733 	}
734 #else
735 	if (ptr && !ptr->loaded) {
736 		if (tryload != XTF_DONT_LOAD)
737 			ptr->loaded = 1;
738 		else
739 			ptr = NULL;
740 	}
741 	if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) {
742 		xt_params->exit_err(PARAMETER_PROBLEM,
743 			   "Couldn't find match `%s'\n", name);
744 	}
745 #endif
746 
747 	if (ptr && matches) {
748 		struct xtables_rule_match **i;
749 		struct xtables_rule_match *newentry;
750 
751 		newentry = xtables_malloc(sizeof(struct xtables_rule_match));
752 
753 		for (i = matches; *i; i = &(*i)->next) {
754 			if (extension_cmp(name, (*i)->match->name,
755 					  (*i)->match->family))
756 				(*i)->completed = true;
757 		}
758 		newentry->match = ptr;
759 		newentry->completed = false;
760 		newentry->next = NULL;
761 		*i = newentry;
762 	}
763 
764 	return ptr;
765 }
766 
767 struct xtables_match *
xtables_find_match_revision(const char * name,enum xtables_tryload tryload,struct xtables_match * match,int revision)768 xtables_find_match_revision(const char *name, enum xtables_tryload tryload,
769 			    struct xtables_match *match, int revision)
770 {
771 	if (!match) {
772 		match = xtables_find_match(name, tryload, NULL);
773 		if (!match)
774 			return NULL;
775 	}
776 
777 	while (1) {
778 		if (match->revision == revision)
779 			return match;
780 		match = match->next;
781 		if (!match)
782 			return NULL;
783 		if (!extension_cmp(name, match->name, match->family))
784 			return NULL;
785 	}
786 }
787 
788 struct xtables_target *
xtables_find_target(const char * name,enum xtables_tryload tryload)789 xtables_find_target(const char *name, enum xtables_tryload tryload)
790 {
791 	struct xtables_target *prev = NULL;
792 	struct xtables_target **dptr;
793 	struct xtables_target *ptr;
794 
795 	/* Standard target? */
796 	if (strcmp(name, "") == 0
797 	    || strcmp(name, XTC_LABEL_ACCEPT) == 0
798 	    || strcmp(name, XTC_LABEL_DROP) == 0
799 	    || strcmp(name, XTC_LABEL_QUEUE) == 0
800 	    || strcmp(name, XTC_LABEL_RETURN) == 0)
801 		name = "standard";
802 
803 	/* Trigger delayed initialization */
804 	for (dptr = &xtables_pending_targets; *dptr; ) {
805 		if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) {
806 			ptr = *dptr;
807 			*dptr = (*dptr)->next;
808 			if (xtables_fully_register_pending_target(ptr, prev)) {
809 				prev = ptr;
810 				continue;
811 			} else if (prev) {
812 				continue;
813 			}
814 			*dptr = ptr;
815 		}
816 		dptr = &((*dptr)->next);
817 	}
818 
819 	for (ptr = xtables_targets; ptr; ptr = ptr->next) {
820 		if (extension_cmp(name, ptr->name, ptr->family)) {
821 #if 0			/* Code block below causes memory leak.  (Bugs 162925719 and 168688680) */
822 			struct xtables_target *clone;
823 
824 			/* First target of this type: */
825 			if (ptr->t == NULL)
826 				break;
827 
828 			/* Second and subsequent clones */
829 			clone = xtables_malloc(sizeof(struct xtables_target));
830 			memcpy(clone, ptr, sizeof(struct xtables_target));
831 			clone->udata = NULL;
832 			clone->tflags = 0;
833 			/* This is a clone: */
834 			clone->next = clone;
835 
836 			ptr = clone;
837 #endif
838 			break;
839 		}
840 	}
841 
842 #ifndef NO_SHARED_LIBS
843 	if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) {
844 		ptr = load_extension(xtables_libdir, afinfo->libprefix,
845 		      name, true);
846 
847 		if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED)
848 			xt_params->exit_err(PARAMETER_PROBLEM,
849 				   "Couldn't load target `%s':%s\n",
850 				   name, strerror(errno));
851 	}
852 #else
853 	if (ptr && !ptr->loaded) {
854 		if (tryload != XTF_DONT_LOAD)
855 			ptr->loaded = 1;
856 		else
857 			ptr = NULL;
858 	}
859 	if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) {
860 		xt_params->exit_err(PARAMETER_PROBLEM,
861 			   "Couldn't find target `%s'\n", name);
862 	}
863 #endif
864 
865 	if (ptr)
866 		ptr->used = 1;
867 
868 	return ptr;
869 }
870 
871 struct xtables_target *
xtables_find_target_revision(const char * name,enum xtables_tryload tryload,struct xtables_target * target,int revision)872 xtables_find_target_revision(const char *name, enum xtables_tryload tryload,
873 			     struct xtables_target *target, int revision)
874 {
875 	if (!target) {
876 		target = xtables_find_target(name, tryload);
877 		if (!target)
878 			return NULL;
879 	}
880 
881 	while (1) {
882 		if (target->revision == revision)
883 			return target;
884 		target = target->next;
885 		if (!target)
886 			return NULL;
887 		if (!extension_cmp(name, target->name, target->family))
888 			return NULL;
889 	}
890 }
891 
xtables_compatible_revision(const char * name,uint8_t revision,int opt)892 int xtables_compatible_revision(const char *name, uint8_t revision, int opt)
893 {
894 	struct xt_get_revision rev;
895 	socklen_t s = sizeof(rev);
896 	int max_rev, sockfd;
897 
898 	sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);
899 	if (sockfd < 0) {
900 		if (errno == EPERM) {
901 			/* revision 0 is always supported. */
902 			if (revision != 0)
903 				fprintf(stderr, "%s: Could not determine whether "
904 						"revision %u is supported, "
905 						"assuming it is.\n",
906 					name, revision);
907 			return 1;
908 		}
909 		fprintf(stderr, "Could not open socket to kernel: %s\n",
910 			strerror(errno));
911 		exit(1);
912 	}
913 
914 	if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) {
915 		fprintf(stderr, "Could not set close on exec: %s\n",
916 			strerror(errno));
917 		exit(1);
918 	}
919 
920 	xtables_load_ko(xtables_modprobe_program, true);
921 
922 	strncpy(rev.name, name, XT_EXTENSION_MAXNAMELEN - 1);
923 	rev.name[XT_EXTENSION_MAXNAMELEN - 1] = '\0';
924 	rev.revision = revision;
925 
926 	max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s);
927 	if (max_rev < 0) {
928 		/* Definitely don't support this? */
929 		if (errno == ENOENT || errno == EPROTONOSUPPORT) {
930 			close(sockfd);
931 			return 0;
932 		} else if (errno == ENOPROTOOPT) {
933 			close(sockfd);
934 			/* Assume only revision 0 support (old kernel) */
935 			return (revision == 0);
936 		} else {
937 			fprintf(stderr, "getsockopt failed strangely: %s\n",
938 				strerror(errno));
939 			exit(1);
940 		}
941 	}
942 	close(sockfd);
943 	return 1;
944 }
945 
946 
compatible_match_revision(const char * name,uint8_t revision)947 static int compatible_match_revision(const char *name, uint8_t revision)
948 {
949 	return xt_params->compat_rev(name, revision, afinfo->so_rev_match);
950 }
951 
compatible_target_revision(const char * name,uint8_t revision)952 static int compatible_target_revision(const char *name, uint8_t revision)
953 {
954 	return xt_params->compat_rev(name, revision, afinfo->so_rev_target);
955 }
956 
xtables_check_options(const char * name,const struct option * opt)957 static void xtables_check_options(const char *name, const struct option *opt)
958 {
959 	for (; opt->name != NULL; ++opt)
960 		if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) {
961 			fprintf(stderr, "%s: Extension %s uses invalid "
962 			        "option value %d\n",xt_params->program_name,
963 			        name, opt->val);
964 			exit(1);
965 		}
966 }
967 
968 static int xtables_match_prefer(const struct xtables_match *a,
969 				const struct xtables_match *b);
970 
xtables_register_match(struct xtables_match * me)971 void xtables_register_match(struct xtables_match *me)
972 {
973 	struct xtables_match **pos;
974 	bool seen_myself = false;
975 
976 	if (me->next) {
977 		fprintf(stderr, "%s: match \"%s\" already registered\n",
978 			xt_params->program_name, me->name);
979 		exit(1);
980 	}
981 
982 	if (me->version == NULL) {
983 		fprintf(stderr, "%s: match %s<%u> is missing a version\n",
984 		        xt_params->program_name, me->name, me->revision);
985 		exit(1);
986 	}
987 
988 	if (me->size != XT_ALIGN(me->size)) {
989 		fprintf(stderr, "%s: match \"%s\" has invalid size %u.\n",
990 		        xt_params->program_name, me->name,
991 		        (unsigned int)me->size);
992 		exit(1);
993 	}
994 
995 	if (strcmp(me->version, XTABLES_VERSION) != 0) {
996 		fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
997 		        "but \"%s\" is required.\n",
998 			xt_params->program_name, me->name,
999 			me->version, XTABLES_VERSION);
1000 		exit(1);
1001 	}
1002 
1003 	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
1004 		fprintf(stderr, "%s: match `%s' has invalid name\n",
1005 			xt_params->program_name, me->name);
1006 		exit(1);
1007 	}
1008 
1009 	if (me->real_name && strlen(me->real_name) >= XT_EXTENSION_MAXNAMELEN) {
1010 		fprintf(stderr, "%s: match `%s' has invalid real name\n",
1011 			xt_params->program_name, me->real_name);
1012 		exit(1);
1013 	}
1014 
1015 	if (me->family >= NPROTO) {
1016 		fprintf(stderr,
1017 			"%s: BUG: match %s has invalid protocol family\n",
1018 			xt_params->program_name, me->name);
1019 		exit(1);
1020 	}
1021 
1022 	if (me->x6_options != NULL)
1023 		xtables_option_metavalidate(me->name, me->x6_options);
1024 	if (me->extra_opts != NULL)
1025 		xtables_check_options(me->name, me->extra_opts);
1026 
1027 	/* order into linked list of matches pending full registration */
1028 	for (pos = &xtables_pending_matches; *pos; pos = &(*pos)->next) {
1029 		/* group by name and family */
1030 		if (strcmp(me->name, (*pos)->name) ||
1031 		    me->family != (*pos)->family) {
1032 			if (seen_myself)
1033 				break; /* end of own group, append to it */
1034 			continue;
1035 		}
1036 		/* found own group */
1037 		seen_myself = true;
1038 		if (xtables_match_prefer(me, *pos) >= 0)
1039 			break; /* put preferred items first in group */
1040 	}
1041 	/* if own group was not found, prepend item */
1042 	if (!*pos && !seen_myself)
1043 		pos = &xtables_pending_matches;
1044 
1045 	me->next = *pos;
1046 	*pos = me;
1047 #ifdef DEBUG
1048 	printf("%s: inserted match %s (family %d, revision %d):\n",
1049 			__func__, me->name, me->family, me->revision);
1050 	for (pos = &xtables_pending_matches; *pos; pos = &(*pos)->next) {
1051 		printf("%s:\tmatch %s (family %d, revision %d)\n", __func__,
1052 		       (*pos)->name, (*pos)->family, (*pos)->revision);
1053 	}
1054 #endif
1055 }
1056 
1057 /**
1058  * Compare two actions for their preference
1059  * @a:	one action
1060  * @b: 	another
1061  *
1062  * Like strcmp, returns a negative number if @a is less preferred than @b,
1063  * positive number if @a is more preferred than @b, or zero if equally
1064  * preferred.
1065  */
1066 static int
xtables_mt_prefer(bool a_alias,unsigned int a_rev,unsigned int a_fam,bool b_alias,unsigned int b_rev,unsigned int b_fam)1067 xtables_mt_prefer(bool a_alias, unsigned int a_rev, unsigned int a_fam,
1068 		  bool b_alias, unsigned int b_rev, unsigned int b_fam)
1069 {
1070 	/*
1071 	 * Alias ranks higher than no alias.
1072 	 * (We want the new action to be used whenever possible.)
1073 	 */
1074 	if (!a_alias && b_alias)
1075 		return -1;
1076 	if (a_alias && !b_alias)
1077 		return 1;
1078 
1079 	/* Higher revision ranks higher. */
1080 	if (a_rev < b_rev)
1081 		return -1;
1082 	if (a_rev > b_rev)
1083 		return 1;
1084 
1085 	/* NFPROTO_<specific> ranks higher than NFPROTO_UNSPEC. */
1086 	if (a_fam == NFPROTO_UNSPEC && b_fam != NFPROTO_UNSPEC)
1087 		return -1;
1088 	if (a_fam != NFPROTO_UNSPEC && b_fam == NFPROTO_UNSPEC)
1089 		return 1;
1090 
1091 	/* Must be the same thing. */
1092 	return 0;
1093 }
1094 
xtables_match_prefer(const struct xtables_match * a,const struct xtables_match * b)1095 static int xtables_match_prefer(const struct xtables_match *a,
1096 				const struct xtables_match *b)
1097 {
1098 	return xtables_mt_prefer(a->real_name != NULL,
1099 				 a->revision, a->family,
1100 				 b->real_name != NULL,
1101 				 b->revision, b->family);
1102 }
1103 
xtables_target_prefer(const struct xtables_target * a,const struct xtables_target * b)1104 static int xtables_target_prefer(const struct xtables_target *a,
1105 				 const struct xtables_target *b)
1106 {
1107 	/*
1108 	 * Note that if x->real_name==NULL, it will be set to x->name in
1109 	 * xtables_register_*; the direct pointer comparison here is therefore
1110 	 * legitimate to detect an alias.
1111 	 */
1112 	return xtables_mt_prefer(a->real_name != NULL,
1113 				 a->revision, a->family,
1114 				 b->real_name != NULL,
1115 				 b->revision, b->family);
1116 }
1117 
xtables_fully_register_pending_match(struct xtables_match * me,struct xtables_match * prev)1118 static bool xtables_fully_register_pending_match(struct xtables_match *me,
1119 						 struct xtables_match *prev)
1120 {
1121 	struct xtables_match **i;
1122 	const char *rn;
1123 
1124 	/* See if new match can be used. */
1125 	rn = (me->real_name != NULL) ? me->real_name : me->name;
1126 	if (!compatible_match_revision(rn, me->revision))
1127 		return false;
1128 
1129 	if (!prev) {
1130 		/* Append to list. */
1131 		for (i = &xtables_matches; *i; i = &(*i)->next);
1132 	} else {
1133 		/* Append it */
1134 		i = &prev->next;
1135 		prev = prev->next;
1136 	}
1137 
1138 	me->next = prev;
1139 	*i = me;
1140 
1141 	me->m = NULL;
1142 	me->mflags = 0;
1143 
1144 	return true;
1145 }
1146 
xtables_register_matches(struct xtables_match * match,unsigned int n)1147 void xtables_register_matches(struct xtables_match *match, unsigned int n)
1148 {
1149 	int i;
1150 
1151 	for (i = 0; i < n; i++)
1152 		xtables_register_match(&match[i]);
1153 }
1154 
xtables_register_target(struct xtables_target * me)1155 void xtables_register_target(struct xtables_target *me)
1156 {
1157 	struct xtables_target **pos;
1158 	bool seen_myself = false;
1159 
1160 	if (me->next) {
1161 		fprintf(stderr, "%s: target \"%s\" already registered\n",
1162 			xt_params->program_name, me->name);
1163 		exit(1);
1164 	}
1165 
1166 	if (me->version == NULL) {
1167 		fprintf(stderr, "%s: target %s<%u> is missing a version\n",
1168 		        xt_params->program_name, me->name, me->revision);
1169 		exit(1);
1170 	}
1171 
1172 	if (me->size != XT_ALIGN(me->size)) {
1173 		fprintf(stderr, "%s: target \"%s\" has invalid size %u.\n",
1174 		        xt_params->program_name, me->name,
1175 		        (unsigned int)me->size);
1176 		exit(1);
1177 	}
1178 
1179 	if (strcmp(me->version, XTABLES_VERSION) != 0) {
1180 		fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
1181 		        "but \"%s\" is required.\n",
1182 			xt_params->program_name, me->name,
1183 			me->version, XTABLES_VERSION);
1184 		exit(1);
1185 	}
1186 
1187 	if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) {
1188 		fprintf(stderr, "%s: target `%s' has invalid name\n",
1189 			xt_params->program_name, me->name);
1190 		exit(1);
1191 	}
1192 
1193 	if (me->real_name && strlen(me->real_name) >= XT_EXTENSION_MAXNAMELEN) {
1194 		fprintf(stderr, "%s: target `%s' has invalid real name\n",
1195 			xt_params->program_name, me->real_name);
1196 		exit(1);
1197 	}
1198 
1199 	if (me->family >= NPROTO) {
1200 		fprintf(stderr,
1201 			"%s: BUG: target %s has invalid protocol family\n",
1202 			xt_params->program_name, me->name);
1203 		exit(1);
1204 	}
1205 
1206 	if (me->x6_options != NULL)
1207 		xtables_option_metavalidate(me->name, me->x6_options);
1208 	if (me->extra_opts != NULL)
1209 		xtables_check_options(me->name, me->extra_opts);
1210 
1211 	/* ignore not interested target */
1212 	if (me->family != afinfo->family && me->family != AF_UNSPEC)
1213 		return;
1214 
1215 	/* order into linked list of targets pending full registration */
1216 	for (pos = &xtables_pending_targets; *pos; pos = &(*pos)->next) {
1217 		/* group by name */
1218 		if (!extension_cmp(me->name, (*pos)->name, (*pos)->family)) {
1219 			if (seen_myself)
1220 				break; /* end of own group, append to it */
1221 			continue;
1222 		}
1223 		/* found own group */
1224 		seen_myself = true;
1225 		if (xtables_target_prefer(me, *pos) >= 0)
1226 			break; /* put preferred items first in group */
1227 	}
1228 	/* if own group was not found, prepend item */
1229 	if (!*pos && !seen_myself)
1230 		pos = &xtables_pending_targets;
1231 
1232 	me->next = *pos;
1233 	*pos = me;
1234 #ifdef DEBUG
1235 	printf("%s: inserted target %s (family %d, revision %d):\n",
1236 			__func__, me->name, me->family, me->revision);
1237 	for (pos = &xtables_pending_targets; *pos; pos = &(*pos)->next) {
1238 		printf("%s:\ttarget %s (family %d, revision %d)\n", __func__,
1239 		       (*pos)->name, (*pos)->family, (*pos)->revision);
1240 	}
1241 #endif
1242 }
1243 
xtables_fully_register_pending_target(struct xtables_target * me,struct xtables_target * prev)1244 static bool xtables_fully_register_pending_target(struct xtables_target *me,
1245 						  struct xtables_target *prev)
1246 {
1247 	struct xtables_target **i;
1248 	const char *rn;
1249 
1250 	if (strcmp(me->name, "standard") != 0) {
1251 		/* See if new target can be used. */
1252 		rn = (me->real_name != NULL) ? me->real_name : me->name;
1253 		if (!compatible_target_revision(rn, me->revision))
1254 			return false;
1255 	}
1256 
1257 	if (!prev) {
1258 		/* Prepend to list. */
1259 		i = &xtables_targets;
1260 		prev = xtables_targets;
1261 	} else {
1262 		/* Append it */
1263 		i = &prev->next;
1264 		prev = prev->next;
1265 	}
1266 
1267 	me->next = prev;
1268 	*i = me;
1269 
1270 	me->t = NULL;
1271 	me->tflags = 0;
1272 
1273 	return true;
1274 }
1275 
xtables_register_targets(struct xtables_target * target,unsigned int n)1276 void xtables_register_targets(struct xtables_target *target, unsigned int n)
1277 {
1278 	int i;
1279 
1280 	for (i = 0; i < n; i++)
1281 		xtables_register_target(&target[i]);
1282 }
1283 
1284 /* receives a list of xtables_rule_match, release them */
xtables_rule_matches_free(struct xtables_rule_match ** matches)1285 void xtables_rule_matches_free(struct xtables_rule_match **matches)
1286 {
1287 	struct xtables_rule_match *matchp, *tmp;
1288 
1289 	for (matchp = *matches; matchp;) {
1290 		tmp = matchp->next;
1291 		if (matchp->match->m) {
1292 			free(matchp->match->m);
1293 			matchp->match->m = NULL;
1294 		}
1295 		if (matchp->match == matchp->match->next) {
1296 			free(matchp->match);
1297 			matchp->match = NULL;
1298 		}
1299 		free(matchp);
1300 		matchp = tmp;
1301 	}
1302 
1303 	*matches = NULL;
1304 }
1305 
1306 /**
1307  * xtables_param_act - act on condition
1308  * @status:	a constant from enum xtables_exittype
1309  *
1310  * %XTF_ONLY_ONCE: print error message that option may only be used once.
1311  * @p1:		module name (e.g. "mark")
1312  * @p2(...):	option in conflict (e.g. "--mark")
1313  * @p3(...):	condition to match on (see extensions/ for examples)
1314  *
1315  * %XTF_NO_INVERT: option does not support inversion
1316  * @p1:		module name
1317  * @p2:		option in conflict
1318  * @p3:		condition to match on
1319  *
1320  * %XTF_BAD_VALUE: bad value for option
1321  * @p1:		module name
1322  * @p2:		option with which the problem occurred (e.g. "--mark")
1323  * @p3:		string the user passed in (e.g. "99999999999999")
1324  *
1325  * %XTF_ONE_ACTION: two mutually exclusive actions have been specified
1326  * @p1:		module name
1327  *
1328  * Displays an error message and exits the program.
1329  */
xtables_param_act(unsigned int status,const char * p1,...)1330 void xtables_param_act(unsigned int status, const char *p1, ...)
1331 {
1332 	const char *p2, *p3;
1333 	va_list args;
1334 	bool b;
1335 
1336 	va_start(args, p1);
1337 
1338 	switch (status) {
1339 	case XTF_ONLY_ONCE:
1340 		p2 = va_arg(args, const char *);
1341 		b  = va_arg(args, unsigned int);
1342 		if (!b) {
1343 			va_end(args);
1344 			return;
1345 		}
1346 		xt_params->exit_err(PARAMETER_PROBLEM,
1347 		           "%s: \"%s\" option may only be specified once",
1348 		           p1, p2);
1349 		break;
1350 	case XTF_NO_INVERT:
1351 		p2 = va_arg(args, const char *);
1352 		b  = va_arg(args, unsigned int);
1353 		if (!b) {
1354 			va_end(args);
1355 			return;
1356 		}
1357 		xt_params->exit_err(PARAMETER_PROBLEM,
1358 		           "%s: \"%s\" option cannot be inverted", p1, p2);
1359 		break;
1360 	case XTF_BAD_VALUE:
1361 		p2 = va_arg(args, const char *);
1362 		p3 = va_arg(args, const char *);
1363 		xt_params->exit_err(PARAMETER_PROBLEM,
1364 		           "%s: Bad value for \"%s\" option: \"%s\"",
1365 		           p1, p2, p3);
1366 		break;
1367 	case XTF_ONE_ACTION:
1368 		b = va_arg(args, unsigned int);
1369 		if (!b) {
1370 			va_end(args);
1371 			return;
1372 		}
1373 		xt_params->exit_err(PARAMETER_PROBLEM,
1374 		           "%s: At most one action is possible", p1);
1375 		break;
1376 	default:
1377 		xt_params->exit_err(status, p1, args);
1378 		break;
1379 	}
1380 
1381 	va_end(args);
1382 }
1383 
xtables_ipaddr_to_numeric(const struct in_addr * addrp)1384 const char *xtables_ipaddr_to_numeric(const struct in_addr *addrp)
1385 {
1386 	static char buf[20];
1387 	const unsigned char *bytep = (const void *)&addrp->s_addr;
1388 
1389 	sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]);
1390 	return buf;
1391 }
1392 
ipaddr_to_host(const struct in_addr * addr)1393 static const char *ipaddr_to_host(const struct in_addr *addr)
1394 {
1395 	static char hostname[NI_MAXHOST];
1396 	struct sockaddr_in saddr = {
1397 		.sin_family = AF_INET,
1398 		.sin_addr = *addr,
1399 	};
1400 	int err;
1401 
1402 
1403 	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in),
1404 		       hostname, sizeof(hostname) - 1, NULL, 0, 0);
1405 	if (err != 0)
1406 		return NULL;
1407 
1408 	return hostname;
1409 }
1410 
ipaddr_to_network(const struct in_addr * addr)1411 static const char *ipaddr_to_network(const struct in_addr *addr)
1412 {
1413 	struct netent *net;
1414 
1415 	if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL)
1416 		return net->n_name;
1417 
1418 	return NULL;
1419 }
1420 
xtables_ipaddr_to_anyname(const struct in_addr * addr)1421 const char *xtables_ipaddr_to_anyname(const struct in_addr *addr)
1422 {
1423 	const char *name;
1424 
1425 	if ((name = ipaddr_to_host(addr)) != NULL ||
1426 	    (name = ipaddr_to_network(addr)) != NULL)
1427 		return name;
1428 
1429 	return xtables_ipaddr_to_numeric(addr);
1430 }
1431 
xtables_ipmask_to_cidr(const struct in_addr * mask)1432 int xtables_ipmask_to_cidr(const struct in_addr *mask)
1433 {
1434 	uint32_t maskaddr, bits;
1435 	int i;
1436 
1437 	maskaddr = ntohl(mask->s_addr);
1438 	/* shortcut for /32 networks */
1439 	if (maskaddr == 0xFFFFFFFFL)
1440 		return 32;
1441 
1442 	i = 32;
1443 	bits = 0xFFFFFFFEL;
1444 	while (--i >= 0 && maskaddr != bits)
1445 		bits <<= 1;
1446 	if (i >= 0)
1447 		return i;
1448 
1449 	/* this mask cannot be converted to CIDR notation */
1450 	return -1;
1451 }
1452 
xtables_ipmask_to_numeric(const struct in_addr * mask)1453 const char *xtables_ipmask_to_numeric(const struct in_addr *mask)
1454 {
1455 	static char buf[20];
1456 	uint32_t cidr;
1457 
1458 	cidr = xtables_ipmask_to_cidr(mask);
1459 	if (cidr == (unsigned int)-1) {
1460 		/* mask was not a decent combination of 1's and 0's */
1461 		sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask));
1462 		return buf;
1463 	} else if (cidr == 32) {
1464 		/* we don't want to see "/32" */
1465 		return "";
1466 	}
1467 
1468 	sprintf(buf, "/%d", cidr);
1469 	return buf;
1470 }
1471 
__numeric_to_ipaddr(const char * dotted,bool is_mask)1472 static struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask)
1473 {
1474 	static struct in_addr addr;
1475 	unsigned char *addrp;
1476 	unsigned int onebyte;
1477 	char buf[20], *p, *q;
1478 	int i;
1479 
1480 	/* copy dotted string, because we need to modify it */
1481 	strncpy(buf, dotted, sizeof(buf) - 1);
1482 	buf[sizeof(buf) - 1] = '\0';
1483 	addrp = (void *)&addr.s_addr;
1484 
1485 	p = buf;
1486 	for (i = 0; i < 3; ++i) {
1487 		if ((q = strchr(p, '.')) == NULL) {
1488 			if (is_mask)
1489 				return NULL;
1490 
1491 			/* autocomplete, this is a network address */
1492 			if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1493 				return NULL;
1494 
1495 			addrp[i] = onebyte;
1496 			while (i < 3)
1497 				addrp[++i] = 0;
1498 
1499 			return &addr;
1500 		}
1501 
1502 		*q = '\0';
1503 		if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1504 			return NULL;
1505 
1506 		addrp[i] = onebyte;
1507 		p = q + 1;
1508 	}
1509 
1510 	/* we have checked 3 bytes, now we check the last one */
1511 	if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX))
1512 		return NULL;
1513 
1514 	addrp[3] = onebyte;
1515 	return &addr;
1516 }
1517 
xtables_numeric_to_ipaddr(const char * dotted)1518 struct in_addr *xtables_numeric_to_ipaddr(const char *dotted)
1519 {
1520 	return __numeric_to_ipaddr(dotted, false);
1521 }
1522 
xtables_numeric_to_ipmask(const char * dotted)1523 struct in_addr *xtables_numeric_to_ipmask(const char *dotted)
1524 {
1525 	return __numeric_to_ipaddr(dotted, true);
1526 }
1527 
network_to_ipaddr(const char * name)1528 static struct in_addr *network_to_ipaddr(const char *name)
1529 {
1530 	static struct in_addr addr;
1531 	struct netent *net;
1532 
1533 	if ((net = getnetbyname(name)) != NULL) {
1534 		if (net->n_addrtype != AF_INET)
1535 			return NULL;
1536 		addr.s_addr = htonl(net->n_net);
1537 		return &addr;
1538 	}
1539 
1540 	return NULL;
1541 }
1542 
host_to_ipaddr(const char * name,unsigned int * naddr)1543 static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
1544 {
1545 	struct in_addr *addr;
1546 	struct addrinfo hints;
1547 	struct addrinfo *res, *p;
1548 	int err;
1549 	unsigned int i;
1550 
1551 	memset(&hints, 0, sizeof(hints));
1552 	hints.ai_family   = AF_INET;
1553 	hints.ai_socktype = SOCK_RAW;
1554 
1555 	*naddr = 0;
1556 	err = getaddrinfo(name, NULL, &hints, &res);
1557 	if (err != 0)
1558 		return NULL;
1559 	for (p = res; p != NULL; p = p->ai_next)
1560 		++*naddr;
1561 	addr = xtables_calloc(*naddr, sizeof(struct in_addr));
1562 	for (i = 0, p = res; p != NULL; p = p->ai_next)
1563 		memcpy(&addr[i++],
1564 		       &((const struct sockaddr_in *)p->ai_addr)->sin_addr,
1565 		       sizeof(struct in_addr));
1566 	freeaddrinfo(res);
1567 	return addr;
1568 }
1569 
1570 static struct in_addr *
ipparse_hostnetwork(const char * name,unsigned int * naddrs)1571 ipparse_hostnetwork(const char *name, unsigned int *naddrs)
1572 {
1573 	struct in_addr *addrptmp, *addrp;
1574 
1575 	if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL ||
1576 	    (addrptmp = network_to_ipaddr(name)) != NULL) {
1577 		addrp = xtables_malloc(sizeof(struct in_addr));
1578 		memcpy(addrp, addrptmp, sizeof(*addrp));
1579 		*naddrs = 1;
1580 		return addrp;
1581 	}
1582 	if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL)
1583 		return addrptmp;
1584 
1585 	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1586 }
1587 
parse_ipmask(const char * mask)1588 static struct in_addr *parse_ipmask(const char *mask)
1589 {
1590 	static struct in_addr maskaddr;
1591 	struct in_addr *addrp;
1592 	unsigned int bits;
1593 
1594 	if (mask == NULL) {
1595 		/* no mask at all defaults to 32 bits */
1596 		maskaddr.s_addr = 0xFFFFFFFF;
1597 		return &maskaddr;
1598 	}
1599 	if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL)
1600 		/* dotted_to_addr already returns a network byte order addr */
1601 		return addrp;
1602 	if (!xtables_strtoui(mask, NULL, &bits, 0, 32))
1603 		xt_params->exit_err(PARAMETER_PROBLEM,
1604 			   "invalid mask `%s' specified", mask);
1605 	if (bits != 0) {
1606 		maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
1607 		return &maskaddr;
1608 	}
1609 
1610 	maskaddr.s_addr = 0U;
1611 	return &maskaddr;
1612 }
1613 
xtables_ipparse_multiple(const char * name,struct in_addr ** addrpp,struct in_addr ** maskpp,unsigned int * naddrs)1614 void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp,
1615                               struct in_addr **maskpp, unsigned int *naddrs)
1616 {
1617 	struct in_addr *addrp;
1618 	char buf[256], *p, *next;
1619 	unsigned int len, i, j, n, count = 1;
1620 	const char *loop = name;
1621 
1622 	while ((loop = strchr(loop, ',')) != NULL) {
1623 		++count;
1624 		++loop; /* skip ',' */
1625 	}
1626 
1627 	*addrpp = xtables_malloc(sizeof(struct in_addr) * count);
1628 	*maskpp = xtables_malloc(sizeof(struct in_addr) * count);
1629 
1630 	loop = name;
1631 
1632 	for (i = 0; i < count; ++i) {
1633 		while (isspace(*loop))
1634 			++loop;
1635 		next = strchr(loop, ',');
1636 		if (next != NULL)
1637 			len = next - loop;
1638 		else
1639 			len = strlen(loop);
1640 		if (len > sizeof(buf) - 1)
1641 			xt_params->exit_err(PARAMETER_PROBLEM,
1642 				"Hostname too long");
1643 
1644 		strncpy(buf, loop, len);
1645 		buf[len] = '\0';
1646 		if ((p = strrchr(buf, '/')) != NULL) {
1647 			*p = '\0';
1648 			addrp = parse_ipmask(p + 1);
1649 		} else {
1650 			addrp = parse_ipmask(NULL);
1651 		}
1652 		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1653 
1654 		/* if a null mask is given, the name is ignored, like in "any/0" */
1655 		if ((*maskpp + i)->s_addr == 0)
1656 			/*
1657 			 * A bit pointless to process multiple addresses
1658 			 * in this case...
1659 			 */
1660 			strcpy(buf, "0.0.0.0");
1661 
1662 		addrp = ipparse_hostnetwork(buf, &n);
1663 		if (n > 1) {
1664 			count += n - 1;
1665 			*addrpp = xtables_realloc(*addrpp,
1666 			          sizeof(struct in_addr) * count);
1667 			*maskpp = xtables_realloc(*maskpp,
1668 			          sizeof(struct in_addr) * count);
1669 			for (j = 0; j < n; ++j)
1670 				/* for each new addr */
1671 				memcpy(*addrpp + i + j, addrp + j,
1672 				       sizeof(*addrp));
1673 			for (j = 1; j < n; ++j)
1674 				/* for each new mask */
1675 				memcpy(*maskpp + i + j, *maskpp + i,
1676 				       sizeof(*addrp));
1677 			i += n - 1;
1678 		} else {
1679 			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1680 		}
1681 		/* free what ipparse_hostnetwork had allocated: */
1682 		free(addrp);
1683 		if (next == NULL)
1684 			break;
1685 		loop = next + 1;
1686 	}
1687 	*naddrs = count;
1688 	for (i = 0; i < count; ++i)
1689 		(*addrpp+i)->s_addr &= (*maskpp+i)->s_addr;
1690 }
1691 
1692 
1693 /**
1694  * xtables_ipparse_any - transform arbitrary name to in_addr
1695  *
1696  * Possible inputs (pseudo regex):
1697  * 	m{^($hostname|$networkname|$ipaddr)(/$mask)?}
1698  * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname"
1699  */
xtables_ipparse_any(const char * name,struct in_addr ** addrpp,struct in_addr * maskp,unsigned int * naddrs)1700 void xtables_ipparse_any(const char *name, struct in_addr **addrpp,
1701                          struct in_addr *maskp, unsigned int *naddrs)
1702 {
1703 	unsigned int i, j, k, n;
1704 	struct in_addr *addrp;
1705 	char buf[256], *p;
1706 
1707 	strncpy(buf, name, sizeof(buf) - 1);
1708 	buf[sizeof(buf) - 1] = '\0';
1709 	if ((p = strrchr(buf, '/')) != NULL) {
1710 		*p = '\0';
1711 		addrp = parse_ipmask(p + 1);
1712 	} else {
1713 		addrp = parse_ipmask(NULL);
1714 	}
1715 	memcpy(maskp, addrp, sizeof(*maskp));
1716 
1717 	/* if a null mask is given, the name is ignored, like in "any/0" */
1718 	if (maskp->s_addr == 0U)
1719 		strcpy(buf, "0.0.0.0");
1720 
1721 	addrp = *addrpp = ipparse_hostnetwork(buf, naddrs);
1722 	n = *naddrs;
1723 	for (i = 0, j = 0; i < n; ++i) {
1724 		addrp[j++].s_addr &= maskp->s_addr;
1725 		for (k = 0; k < j - 1; ++k)
1726 			if (addrp[k].s_addr == addrp[j-1].s_addr) {
1727 				/*
1728 				 * Nuke the dup by copying an address from the
1729 				 * tail here, and check the current position
1730 				 * again (--j).
1731 				 */
1732 				memcpy(&addrp[--j], &addrp[--*naddrs],
1733 				       sizeof(struct in_addr));
1734 				break;
1735 			}
1736 	}
1737 }
1738 
xtables_ip6addr_to_numeric(const struct in6_addr * addrp)1739 const char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp)
1740 {
1741 	/* 0000:0000:0000:0000:0000:0000:000.000.000.000
1742 	 * 0000:0000:0000:0000:0000:0000:0000:0000 */
1743 	static char buf[50+1];
1744 	return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
1745 }
1746 
ip6addr_to_host(const struct in6_addr * addr)1747 static const char *ip6addr_to_host(const struct in6_addr *addr)
1748 {
1749 	static char hostname[NI_MAXHOST];
1750 	struct sockaddr_in6 saddr;
1751 	int err;
1752 
1753 	memset(&saddr, 0, sizeof(struct sockaddr_in6));
1754 	memcpy(&saddr.sin6_addr, addr, sizeof(*addr));
1755 	saddr.sin6_family = AF_INET6;
1756 
1757 	err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6),
1758 			hostname, sizeof(hostname) - 1, NULL, 0, 0);
1759 	if (err != 0)
1760 		return NULL;
1761 
1762 	return hostname;
1763 }
1764 
xtables_ip6addr_to_anyname(const struct in6_addr * addr)1765 const char *xtables_ip6addr_to_anyname(const struct in6_addr *addr)
1766 {
1767 	const char *name;
1768 
1769 	if ((name = ip6addr_to_host(addr)) != NULL)
1770 		return name;
1771 
1772 	return xtables_ip6addr_to_numeric(addr);
1773 }
1774 
xtables_ip6mask_to_cidr(const struct in6_addr * k)1775 int xtables_ip6mask_to_cidr(const struct in6_addr *k)
1776 {
1777 	unsigned int bits = 0;
1778 	uint32_t a, b, c, d;
1779 
1780 	a = ntohl(k->s6_addr32[0]);
1781 	b = ntohl(k->s6_addr32[1]);
1782 	c = ntohl(k->s6_addr32[2]);
1783 	d = ntohl(k->s6_addr32[3]);
1784 	while (a & 0x80000000U) {
1785 		++bits;
1786 		a <<= 1;
1787 		a  |= (b >> 31) & 1;
1788 		b <<= 1;
1789 		b  |= (c >> 31) & 1;
1790 		c <<= 1;
1791 		c  |= (d >> 31) & 1;
1792 		d <<= 1;
1793 	}
1794 	if (a != 0 || b != 0 || c != 0 || d != 0)
1795 		return -1;
1796 	return bits;
1797 }
1798 
xtables_ip6mask_to_numeric(const struct in6_addr * addrp)1799 const char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp)
1800 {
1801 	static char buf[50+2];
1802 	int l = xtables_ip6mask_to_cidr(addrp);
1803 
1804 	if (l == -1) {
1805 		strcpy(buf, "/");
1806 		strcat(buf, xtables_ip6addr_to_numeric(addrp));
1807 		return buf;
1808 	}
1809 	/* we don't want to see "/128" */
1810 	if (l == 128)
1811 		return "";
1812 	else
1813 		sprintf(buf, "/%d", l);
1814 	return buf;
1815 }
1816 
xtables_numeric_to_ip6addr(const char * num)1817 struct in6_addr *xtables_numeric_to_ip6addr(const char *num)
1818 {
1819 	static struct in6_addr ap;
1820 	int err;
1821 
1822 	if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
1823 		return &ap;
1824 
1825 	return NULL;
1826 }
1827 
1828 static struct in6_addr *
host_to_ip6addr(const char * name,unsigned int * naddr)1829 host_to_ip6addr(const char *name, unsigned int *naddr)
1830 {
1831 	struct in6_addr *addr;
1832 	struct addrinfo hints;
1833 	struct addrinfo *res, *p;
1834 	int err;
1835 	unsigned int i;
1836 
1837 	memset(&hints, 0, sizeof(hints));
1838 	hints.ai_family   = AF_INET6;
1839 	hints.ai_socktype = SOCK_RAW;
1840 
1841 	*naddr = 0;
1842 	err = getaddrinfo(name, NULL, &hints, &res);
1843 	if (err != 0)
1844 		return NULL;
1845 	/* Find length of address chain */
1846 	for (p = res; p != NULL; p = p->ai_next)
1847 		++*naddr;
1848 	/* Copy each element of the address chain */
1849 	addr = xtables_calloc(*naddr, sizeof(struct in6_addr));
1850 	for (i = 0, p = res; p != NULL; p = p->ai_next)
1851 		memcpy(&addr[i++],
1852 		       &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr,
1853 		       sizeof(struct in6_addr));
1854 	freeaddrinfo(res);
1855 	return addr;
1856 }
1857 
network_to_ip6addr(const char * name)1858 static struct in6_addr *network_to_ip6addr(const char *name)
1859 {
1860 	/*	abort();*/
1861 	/* TODO: not implemented yet, but the exception breaks the
1862 	 *       name resolvation */
1863 	return NULL;
1864 }
1865 
1866 static struct in6_addr *
ip6parse_hostnetwork(const char * name,unsigned int * naddrs)1867 ip6parse_hostnetwork(const char *name, unsigned int *naddrs)
1868 {
1869 	struct in6_addr *addrp, *addrptmp;
1870 
1871 	if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL ||
1872 	    (addrptmp = network_to_ip6addr(name)) != NULL) {
1873 		addrp = xtables_malloc(sizeof(struct in6_addr));
1874 		memcpy(addrp, addrptmp, sizeof(*addrp));
1875 		*naddrs = 1;
1876 		return addrp;
1877 	}
1878 	if ((addrp = host_to_ip6addr(name, naddrs)) != NULL)
1879 		return addrp;
1880 
1881 	xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name);
1882 }
1883 
parse_ip6mask(char * mask)1884 static struct in6_addr *parse_ip6mask(char *mask)
1885 {
1886 	static struct in6_addr maskaddr;
1887 	struct in6_addr *addrp;
1888 	unsigned int bits;
1889 
1890 	if (mask == NULL) {
1891 		/* no mask at all defaults to 128 bits */
1892 		memset(&maskaddr, 0xff, sizeof maskaddr);
1893 		return &maskaddr;
1894 	}
1895 	if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL)
1896 		return addrp;
1897 	if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
1898 		xt_params->exit_err(PARAMETER_PROBLEM,
1899 			   "invalid mask `%s' specified", mask);
1900 	if (bits != 0) {
1901 		char *p = (void *)&maskaddr;
1902 		memset(p, 0xff, bits / 8);
1903 		memset(p + ((bits + 7) / 8), 0, (128 - bits) / 8);
1904 		if (bits < 128)
1905 			p[bits/8] = 0xff << (8 - (bits & 7));
1906 		return &maskaddr;
1907 	}
1908 
1909 	memset(&maskaddr, 0, sizeof(maskaddr));
1910 	return &maskaddr;
1911 }
1912 
1913 void
xtables_ip6parse_multiple(const char * name,struct in6_addr ** addrpp,struct in6_addr ** maskpp,unsigned int * naddrs)1914 xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp,
1915 		      struct in6_addr **maskpp, unsigned int *naddrs)
1916 {
1917 	static const struct in6_addr zero_addr;
1918 	struct in6_addr *addrp;
1919 	char buf[256], *p, *next;
1920 	unsigned int len, i, j, n, count = 1;
1921 	const char *loop = name;
1922 
1923 	while ((loop = strchr(loop, ',')) != NULL) {
1924 		++count;
1925 		++loop; /* skip ',' */
1926 	}
1927 
1928 	*addrpp = xtables_malloc(sizeof(struct in6_addr) * count);
1929 	*maskpp = xtables_malloc(sizeof(struct in6_addr) * count);
1930 
1931 	loop = name;
1932 
1933 	for (i = 0; i < count /*NB: count can grow*/; ++i) {
1934 		while (isspace(*loop))
1935 			++loop;
1936 		next = strchr(loop, ',');
1937 		if (next != NULL)
1938 			len = next - loop;
1939 		else
1940 			len = strlen(loop);
1941 		if (len > sizeof(buf) - 1)
1942 			xt_params->exit_err(PARAMETER_PROBLEM,
1943 				"Hostname too long");
1944 
1945 		strncpy(buf, loop, len);
1946 		buf[len] = '\0';
1947 		if ((p = strrchr(buf, '/')) != NULL) {
1948 			*p = '\0';
1949 			addrp = parse_ip6mask(p + 1);
1950 		} else {
1951 			addrp = parse_ip6mask(NULL);
1952 		}
1953 		memcpy(*maskpp + i, addrp, sizeof(*addrp));
1954 
1955 		/* if a null mask is given, the name is ignored, like in "any/0" */
1956 		if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0)
1957 			strcpy(buf, "::");
1958 
1959 		addrp = ip6parse_hostnetwork(buf, &n);
1960 		if (n > 1) {
1961 			count += n - 1;
1962 			*addrpp = xtables_realloc(*addrpp,
1963 			          sizeof(struct in6_addr) * count);
1964 			*maskpp = xtables_realloc(*maskpp,
1965 			          sizeof(struct in6_addr) * count);
1966 			for (j = 0; j < n; ++j)
1967 				/* for each new addr */
1968 				memcpy(*addrpp + i + j, addrp + j,
1969 				       sizeof(*addrp));
1970 			for (j = 1; j < n; ++j)
1971 				/* for each new mask */
1972 				memcpy(*maskpp + i + j, *maskpp + i,
1973 				       sizeof(*addrp));
1974 			i += n - 1;
1975 		} else {
1976 			memcpy(*addrpp + i, addrp, sizeof(*addrp));
1977 		}
1978 		/* free what ip6parse_hostnetwork had allocated: */
1979 		free(addrp);
1980 		if (next == NULL)
1981 			break;
1982 		loop = next + 1;
1983 	}
1984 	*naddrs = count;
1985 	for (i = 0; i < count; ++i)
1986 		for (j = 0; j < 4; ++j)
1987 			(*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j];
1988 }
1989 
xtables_ip6parse_any(const char * name,struct in6_addr ** addrpp,struct in6_addr * maskp,unsigned int * naddrs)1990 void xtables_ip6parse_any(const char *name, struct in6_addr **addrpp,
1991                           struct in6_addr *maskp, unsigned int *naddrs)
1992 {
1993 	static const struct in6_addr zero_addr;
1994 	struct in6_addr *addrp;
1995 	unsigned int i, j, k, n;
1996 	char buf[256], *p;
1997 
1998 	strncpy(buf, name, sizeof(buf) - 1);
1999 	buf[sizeof(buf)-1] = '\0';
2000 	if ((p = strrchr(buf, '/')) != NULL) {
2001 		*p = '\0';
2002 		addrp = parse_ip6mask(p + 1);
2003 	} else {
2004 		addrp = parse_ip6mask(NULL);
2005 	}
2006 	memcpy(maskp, addrp, sizeof(*maskp));
2007 
2008 	/* if a null mask is given, the name is ignored, like in "any/0" */
2009 	if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0)
2010 		strcpy(buf, "::");
2011 
2012 	addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs);
2013 	n = *naddrs;
2014 	for (i = 0, j = 0; i < n; ++i) {
2015 		for (k = 0; k < 4; ++k)
2016 			addrp[j].s6_addr32[k] &= maskp->s6_addr32[k];
2017 		++j;
2018 		for (k = 0; k < j - 1; ++k)
2019 			if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) {
2020 				/*
2021 				 * Nuke the dup by copying an address from the
2022 				 * tail here, and check the current position
2023 				 * again (--j).
2024 				 */
2025 				memcpy(&addrp[--j], &addrp[--*naddrs],
2026 				       sizeof(struct in_addr));
2027 				break;
2028 			}
2029 	}
2030 }
2031 
xtables_save_string(const char * value)2032 void xtables_save_string(const char *value)
2033 {
2034 	static const char no_quote_chars[] = "_-0123456789"
2035 		"abcdefghijklmnopqrstuvwxyz"
2036 		"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
2037 	static const char escape_chars[] = "\"\\'";
2038 	size_t length;
2039 	const char *p;
2040 
2041 	length = strspn(value, no_quote_chars);
2042 	if (length > 0 && value[length] == 0) {
2043 		/* no quoting required */
2044 		putchar(' ');
2045 		fputs(value, stdout);
2046 	} else {
2047 		/* there is at least one dangerous character in the
2048 		   value, which we have to quote.  Write double quotes
2049 		   around the value and escape special characters with
2050 		   a backslash */
2051 		printf(" \"");
2052 
2053 		for (p = strpbrk(value, escape_chars); p != NULL;
2054 		     p = strpbrk(value, escape_chars)) {
2055 			if (p > value)
2056 				fwrite(value, 1, p - value, stdout);
2057 			putchar('\\');
2058 			putchar(*p);
2059 			value = p + 1;
2060 		}
2061 
2062 		/* print the rest and finish the double quoted
2063 		   string */
2064 		fputs(value, stdout);
2065 		putchar('\"');
2066 	}
2067 }
2068 
2069 const struct xtables_pprot xtables_chain_protos[] = {
2070 	{"tcp",       IPPROTO_TCP},
2071 	{"sctp",      IPPROTO_SCTP},
2072 	{"udp",       IPPROTO_UDP},
2073 	{"udplite",   IPPROTO_UDPLITE},
2074 	{"icmp",      IPPROTO_ICMP},
2075 	{"icmpv6",    IPPROTO_ICMPV6},
2076 	{"ipv6-icmp", IPPROTO_ICMPV6},
2077 	{"esp",       IPPROTO_ESP},
2078 	{"ah",        IPPROTO_AH},
2079 	{"ipv6-mh",   IPPROTO_MH},
2080 	{"mh",        IPPROTO_MH},
2081 	{"all",       0},
2082 	{NULL},
2083 };
2084 
2085 uint16_t
xtables_parse_protocol(const char * s)2086 xtables_parse_protocol(const char *s)
2087 {
2088 	const struct protoent *pent;
2089 	unsigned int proto, i;
2090 
2091 	if (xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX))
2092 		return proto;
2093 
2094 	/* first deal with the special case of 'all' to prevent
2095 	 * people from being able to redefine 'all' in nsswitch
2096 	 * and/or provoke expensive [not working] ldap/nis/...
2097 	 * lookups */
2098 	if (strcmp(s, "all") == 0)
2099 		return 0;
2100 
2101 	pent = getprotobyname(s);
2102 	if (pent != NULL)
2103 		return pent->p_proto;
2104 
2105 	for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
2106 		if (xtables_chain_protos[i].name == NULL)
2107 			continue;
2108 		if (strcmp(s, xtables_chain_protos[i].name) == 0)
2109 			return xtables_chain_protos[i].num;
2110 	}
2111 	xt_params->exit_err(PARAMETER_PROBLEM,
2112 		"unknown protocol \"%s\" specified", s);
2113 	return -1;
2114 }
2115 
xtables_print_num(uint64_t number,unsigned int format)2116 void xtables_print_num(uint64_t number, unsigned int format)
2117 {
2118 	if (!(format & FMT_KILOMEGAGIGA)) {
2119 		printf(FMT("%8llu ","%llu "), (unsigned long long)number);
2120 		return;
2121 	}
2122 	if (number <= 99999) {
2123 		printf(FMT("%5llu ","%llu "), (unsigned long long)number);
2124 		return;
2125 	}
2126 	number = (number + 500) / 1000;
2127 	if (number <= 9999) {
2128 		printf(FMT("%4lluK ","%lluK "), (unsigned long long)number);
2129 		return;
2130 	}
2131 	number = (number + 500) / 1000;
2132 	if (number <= 9999) {
2133 		printf(FMT("%4lluM ","%lluM "), (unsigned long long)number);
2134 		return;
2135 	}
2136 	number = (number + 500) / 1000;
2137 	if (number <= 9999) {
2138 		printf(FMT("%4lluG ","%lluG "), (unsigned long long)number);
2139 		return;
2140 	}
2141 	number = (number + 500) / 1000;
2142 	printf(FMT("%4lluT ","%lluT "), (unsigned long long)number);
2143 }
2144 
2145 #include <netinet/ether.h>
2146 
2147 static const unsigned char mac_type_unicast[ETH_ALEN] =   {};
2148 static const unsigned char msk_type_unicast[ETH_ALEN] =   {1};
2149 static const unsigned char mac_type_multicast[ETH_ALEN] = {1};
2150 static const unsigned char msk_type_multicast[ETH_ALEN] = {1};
2151 #define ALL_ONE_MAC {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
2152 static const unsigned char mac_type_broadcast[ETH_ALEN] = ALL_ONE_MAC;
2153 static const unsigned char msk_type_broadcast[ETH_ALEN] = ALL_ONE_MAC;
2154 static const unsigned char mac_type_bridge_group[ETH_ALEN] = {0x01, 0x80, 0xc2};
2155 static const unsigned char msk_type_bridge_group[ETH_ALEN] = ALL_ONE_MAC;
2156 #undef ALL_ONE_MAC
2157 
xtables_parse_mac_and_mask(const char * from,void * to,void * mask)2158 int xtables_parse_mac_and_mask(const char *from, void *to, void *mask)
2159 {
2160 	char *p;
2161 	int i;
2162 	struct ether_addr *addr = NULL;
2163 
2164 	if (strcasecmp(from, "Unicast") == 0) {
2165 		memcpy(to, mac_type_unicast, ETH_ALEN);
2166 		memcpy(mask, msk_type_unicast, ETH_ALEN);
2167 		return 0;
2168 	}
2169 	if (strcasecmp(from, "Multicast") == 0) {
2170 		memcpy(to, mac_type_multicast, ETH_ALEN);
2171 		memcpy(mask, msk_type_multicast, ETH_ALEN);
2172 		return 0;
2173 	}
2174 	if (strcasecmp(from, "Broadcast") == 0) {
2175 		memcpy(to, mac_type_broadcast, ETH_ALEN);
2176 		memcpy(mask, msk_type_broadcast, ETH_ALEN);
2177 		return 0;
2178 	}
2179 	if (strcasecmp(from, "BGA") == 0) {
2180 		memcpy(to, mac_type_bridge_group, ETH_ALEN);
2181 		memcpy(mask, msk_type_bridge_group, ETH_ALEN);
2182 		return 0;
2183 	}
2184 	if ( (p = strrchr(from, '/')) != NULL) {
2185 		*p = '\0';
2186 		if (!(addr = ether_aton(p + 1)))
2187 			return -1;
2188 		memcpy(mask, addr, ETH_ALEN);
2189 	} else
2190 		memset(mask, 0xff, ETH_ALEN);
2191 	if (!(addr = ether_aton(from)))
2192 		return -1;
2193 	memcpy(to, addr, ETH_ALEN);
2194 	for (i = 0; i < ETH_ALEN; i++)
2195 		((char *)to)[i] &= ((char *)mask)[i];
2196 	return 0;
2197 }
2198 
xtables_print_well_known_mac_and_mask(const void * mac,const void * mask)2199 int xtables_print_well_known_mac_and_mask(const void *mac, const void *mask)
2200 {
2201 	if (!memcmp(mac, mac_type_unicast, ETH_ALEN) &&
2202 	    !memcmp(mask, msk_type_unicast, ETH_ALEN))
2203 		printf("Unicast");
2204 	else if (!memcmp(mac, mac_type_multicast, ETH_ALEN) &&
2205 	         !memcmp(mask, msk_type_multicast, ETH_ALEN))
2206 		printf("Multicast");
2207 	else if (!memcmp(mac, mac_type_broadcast, ETH_ALEN) &&
2208 	         !memcmp(mask, msk_type_broadcast, ETH_ALEN))
2209 		printf("Broadcast");
2210 	else if (!memcmp(mac, mac_type_bridge_group, ETH_ALEN) &&
2211 	         !memcmp(mask, msk_type_bridge_group, ETH_ALEN))
2212 		printf("BGA");
2213 	else
2214 		return -1;
2215 	return 0;
2216 }
2217 
xtables_print_mac(const unsigned char * macaddress)2218 void xtables_print_mac(const unsigned char *macaddress)
2219 {
2220 	unsigned int i;
2221 
2222 	printf("%02x", macaddress[0]);
2223 	for (i = 1; i < 6; ++i)
2224 		printf(":%02x", macaddress[i]);
2225 }
2226 
xtables_print_mac_and_mask(const unsigned char * mac,const unsigned char * mask)2227 void xtables_print_mac_and_mask(const unsigned char *mac, const unsigned char *mask)
2228 {
2229 	static const char hlpmsk[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2230 
2231 	xtables_print_mac(mac);
2232 
2233 	if (memcmp(mask, hlpmsk, 6) == 0)
2234 		return;
2235 
2236 	printf("/");
2237 	xtables_print_mac(mask);
2238 }
2239 
xtables_parse_val_mask(struct xt_option_call * cb,unsigned int * val,unsigned int * mask,const struct xtables_lmap * lmap)2240 void xtables_parse_val_mask(struct xt_option_call *cb,
2241 			    unsigned int *val, unsigned int *mask,
2242 			    const struct xtables_lmap *lmap)
2243 {
2244 	char *end;
2245 
2246 	*mask = ~0U;
2247 
2248 	if (!xtables_strtoui(cb->arg, &end, val, 0, UINT32_MAX)) {
2249 		if (lmap)
2250 			goto name2val;
2251 		else
2252 			goto bad_val;
2253 	}
2254 
2255 	if (*end == '\0')
2256 		return;
2257 
2258 	if (*end != '/') {
2259 		if (lmap)
2260 			goto name2val;
2261 		else
2262 			goto garbage;
2263 	}
2264 
2265 	if (!xtables_strtoui(end + 1, &end, mask, 0, UINT32_MAX))
2266 		goto bad_val;
2267 
2268 	if (*end == '\0')
2269 		return;
2270 
2271 garbage:
2272 	xt_params->exit_err(PARAMETER_PROBLEM,
2273 			"%s: trailing garbage after value "
2274 			"for option \"--%s\".\n",
2275 			cb->ext_name, cb->entry->name);
2276 
2277 bad_val:
2278 	xt_params->exit_err(PARAMETER_PROBLEM,
2279 			"%s: bad integer value for option \"--%s\", "
2280 			"or out of range.\n",
2281 			cb->ext_name, cb->entry->name);
2282 
2283 name2val:
2284 	*val = xtables_lmap_name2id(lmap, cb->arg);
2285 	if ((int)*val == -1)
2286 		xt_params->exit_err(PARAMETER_PROBLEM,
2287 			"%s: could not map name %s to an integer value "
2288 			"for option \"--%s\".\n",
2289 			cb->ext_name, cb->arg, cb->entry->name);
2290 }
2291 
xtables_print_val_mask(unsigned int val,unsigned int mask,const struct xtables_lmap * lmap)2292 void xtables_print_val_mask(unsigned int val, unsigned int mask,
2293 			    const struct xtables_lmap *lmap)
2294 {
2295 	if (mask != ~0U) {
2296 		printf(" 0x%x/0x%x", val, mask);
2297 		return;
2298 	}
2299 
2300 	if (lmap) {
2301 		const char *name = xtables_lmap_id2name(lmap, val);
2302 
2303 		if (name) {
2304 			printf(" %s", name);
2305 			return;
2306 		}
2307 	}
2308 
2309 	printf(" 0x%x", val);
2310 }
2311 
2312 int kernel_version;
2313 
get_kernel_version(void)2314 void get_kernel_version(void)
2315 {
2316 	static struct utsname uts;
2317 	int x = 0, y = 0, z = 0;
2318 
2319 	if (uname(&uts) == -1) {
2320 		fprintf(stderr, "Unable to retrieve kernel version.\n");
2321 		xtables_free_opts(1);
2322 		exit(1);
2323 	}
2324 
2325 	sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
2326 	kernel_version = LINUX_VERSION(x, y, z);
2327 }
2328 
2329 #include <linux/netfilter/nf_tables.h>
2330 
2331 struct xt_xlate {
2332 	struct {
2333 		char	*data;
2334 		int	size;
2335 		int	rem;
2336 		int	off;
2337 	} buf;
2338 	char comment[NFT_USERDATA_MAXLEN];
2339 };
2340 
xt_xlate_alloc(int size)2341 struct xt_xlate *xt_xlate_alloc(int size)
2342 {
2343 	struct xt_xlate *xl;
2344 
2345 	xl = malloc(sizeof(struct xt_xlate));
2346 	if (xl == NULL)
2347 		xtables_error(RESOURCE_PROBLEM, "OOM");
2348 
2349 	xl->buf.data = malloc(size);
2350 	if (xl->buf.data == NULL)
2351 		xtables_error(RESOURCE_PROBLEM, "OOM");
2352 
2353 	xl->buf.data[0] = '\0';
2354 	xl->buf.size = size;
2355 	xl->buf.rem = size;
2356 	xl->buf.off = 0;
2357 	xl->comment[0] = '\0';
2358 
2359 	return xl;
2360 }
2361 
xt_xlate_free(struct xt_xlate * xl)2362 void xt_xlate_free(struct xt_xlate *xl)
2363 {
2364 	free(xl->buf.data);
2365 	free(xl);
2366 }
2367 
xt_xlate_add(struct xt_xlate * xl,const char * fmt,...)2368 void xt_xlate_add(struct xt_xlate *xl, const char *fmt, ...)
2369 {
2370 	va_list ap;
2371 	int len;
2372 
2373 	va_start(ap, fmt);
2374 	len = vsnprintf(xl->buf.data + xl->buf.off, xl->buf.rem, fmt, ap);
2375 	if (len < 0 || len >= xl->buf.rem)
2376 		xtables_error(RESOURCE_PROBLEM, "OOM");
2377 
2378 	va_end(ap);
2379 	xl->buf.rem -= len;
2380 	xl->buf.off += len;
2381 }
2382 
xt_xlate_add_comment(struct xt_xlate * xl,const char * comment)2383 void xt_xlate_add_comment(struct xt_xlate *xl, const char *comment)
2384 {
2385 	strncpy(xl->comment, comment, NFT_USERDATA_MAXLEN - 1);
2386 	xl->comment[NFT_USERDATA_MAXLEN - 1] = '\0';
2387 }
2388 
xt_xlate_get_comment(struct xt_xlate * xl)2389 const char *xt_xlate_get_comment(struct xt_xlate *xl)
2390 {
2391 	return xl->comment[0] ? xl->comment : NULL;
2392 }
2393 
xt_xlate_get(struct xt_xlate * xl)2394 const char *xt_xlate_get(struct xt_xlate *xl)
2395 {
2396 	return xl->buf.data;
2397 }
2398