xtoptions.c revision 57e2e37ebe5319cf84381bdb319ea94143b1bf97
1/*
2 *	Argument parser
3 *	Copyright © Jan Engelhardt, 2011
4 *
5 *	This program is free software; you can redistribute it and/or
6 *	modify it under the terms of the GNU General Public License as
7 *	published by the Free Software Foundation; either version 2 of
8 *	the License, or (at your option) any later version.
9 */
10#include <ctype.h>
11#include <errno.h>
12#include <getopt.h>
13#include <limits.h>
14#include <netdb.h>
15#include <stdbool.h>
16#include <stdint.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <syslog.h>
21#include <arpa/inet.h>
22#include <netinet/ip.h>
23#include "xtables.h"
24#include "xshared.h"
25#ifndef IPTOS_NORMALSVC
26#	define IPTOS_NORMALSVC 0
27#endif
28
29#define XTOPT_MKPTR(cb) \
30	((void *)((char *)(cb)->data + (cb)->entry->ptroff))
31
32/**
33 * Simple key-value pairs for syslog levels
34 */
35struct syslog_level {
36	char name[8];
37	uint8_t level;
38};
39
40struct tos_value_mask {
41	uint8_t value, mask;
42};
43
44/**
45 * Creates getopt options from the x6-style option map, and assigns each a
46 * getopt id.
47 */
48struct option *
49xtables_options_xfrm(struct option *orig_opts, struct option *oldopts,
50		     const struct xt_option_entry *entry, unsigned int *offset)
51{
52	unsigned int num_orig, num_old = 0, num_new, i;
53	struct option *merge, *mp;
54
55	if (entry == NULL)
56		return oldopts;
57	for (num_orig = 0; orig_opts[num_orig].name != NULL; ++num_orig)
58		;
59	if (oldopts != NULL)
60		for (num_old = 0; oldopts[num_old].name != NULL; ++num_old)
61			;
62	for (num_new = 0; entry[num_new].name != NULL; ++num_new)
63		;
64
65	/*
66	 * Since @oldopts also has @orig_opts already (and does so at the
67	 * start), skip these entries.
68	 */
69	oldopts += num_orig;
70	num_old -= num_orig;
71
72	merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1));
73	if (merge == NULL)
74		return NULL;
75
76	/* Let the base options -[ADI...] have precedence over everything */
77	memcpy(merge, orig_opts, sizeof(*mp) * num_orig);
78	mp = merge + num_orig;
79
80	/* Second, the new options */
81	xt_params->option_offset += XT_OPTION_OFFSET_SCALE;
82	*offset = xt_params->option_offset;
83
84	for (i = 0; i < num_new; ++i, ++mp, ++entry) {
85		mp->name         = entry->name;
86		mp->has_arg      = entry->type != XTTYPE_NONE;
87		mp->flag         = NULL;
88		mp->val          = entry->id + *offset;
89	}
90
91	/* Third, the old options */
92	memcpy(mp, oldopts, sizeof(*mp) * num_old);
93	mp += num_old;
94	xtables_free_opts(0);
95
96	/* Clear trailing entry */
97	memset(mp, 0, sizeof(*mp));
98	return merge;
99}
100
101static uintmax_t xtopt_max_by_type(enum xt_option_type type)
102{
103	switch (type) {
104	case XTTYPE_UINT8:
105	case XTTYPE_UINT8RC:
106		return UINT8_MAX;
107	case XTTYPE_UINT16:
108	case XTTYPE_UINT16RC:
109		return UINT16_MAX;
110	case XTTYPE_UINT32:
111	case XTTYPE_UINT32RC:
112		return UINT32_MAX;
113	case XTTYPE_UINT64:
114	case XTTYPE_UINT64RC:
115		return UINT64_MAX;
116	default:
117		return 0;
118	}
119}
120
121/**
122 * Require a simple integer.
123 */
124static void xtopt_parse_int(struct xt_option_call *cb)
125{
126	const struct xt_option_entry *entry = cb->entry;
127	uintmax_t lmin = 0, lmax = xtopt_max_by_type(entry->type);
128	uintmax_t value;
129
130	if (cb->entry->min != 0)
131		lmin = cb->entry->min;
132	if (cb->entry->max != 0)
133		lmax = cb->entry->max;
134
135	if (!xtables_strtoul(cb->arg, NULL, &value, lmin, lmax))
136		xt_params->exit_err(PARAMETER_PROBLEM,
137			"%s: bad value for option \"--%s\", "
138			"or out of range (%ju-%ju).\n",
139			cb->ext_name, entry->name, lmin, lmax);
140
141	if (entry->type == XTTYPE_UINT8) {
142		cb->val.u8 = value;
143		if (entry->flags & XTOPT_PUT)
144			*(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8;
145	} else if (entry->type == XTTYPE_UINT16) {
146		cb->val.u16 = value;
147		if (entry->flags & XTOPT_PUT)
148			*(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16;
149	} else if (entry->type == XTTYPE_UINT32) {
150		cb->val.u32 = value;
151		if (entry->flags & XTOPT_PUT)
152			*(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32;
153	} else if (entry->type == XTTYPE_UINT64) {
154		cb->val.u64 = value;
155		if (entry->flags & XTOPT_PUT)
156			*(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64;
157	}
158}
159
160/**
161 * Require a simple floating point number.
162 */
163static void xtopt_parse_float(struct xt_option_call *cb)
164{
165	const struct xt_option_entry *entry = cb->entry;
166	double value;
167	char *end;
168
169	value = strtod(cb->arg, &end);
170	if (end == cb->arg || *end != '\0' ||
171	    (entry->min != entry->max &&
172	    (value < entry->min || value > entry->max)))
173		xt_params->exit_err(PARAMETER_PROBLEM,
174			"%s: bad value for option \"--%s\", "
175			"or out of range (%u-%u).\n",
176			cb->ext_name, entry->name, entry->min, entry->max);
177
178	cb->val.dbl = value;
179	if (entry->flags & XTOPT_PUT)
180		*(double *)XTOPT_MKPTR(cb) = cb->val.dbl;
181}
182
183/**
184 * Multiple integer parse routine.
185 *
186 * This function is capable of parsing any number of fields. Only the first
187 * two values from the string will be put into @cb however (and as such,
188 * @cb->val.uXX_range is just that large) to cater for the few extensions that
189 * do not have a range[2] field, but {min, max}, and which cannot use
190 * XTOPT_POINTER.
191 */
192static void xtopt_parse_mint(struct xt_option_call *cb)
193{
194	const struct xt_option_entry *entry = cb->entry;
195	const char *arg = cb->arg;
196	size_t esize = sizeof(uint32_t);
197	uintmax_t lmax = xtopt_max_by_type(entry->type);
198	char *put = XTOPT_MKPTR(cb);
199	unsigned int maxiter;
200	uintmax_t value;
201	char *end = "";
202	char sep = ':';
203
204	if (entry->type == XTTYPE_UINT8RC)
205		esize = sizeof(uint8_t);
206	else if (entry->type == XTTYPE_UINT16RC)
207		esize = sizeof(uint16_t);
208	else if (entry->type == XTTYPE_UINT64RC)
209		esize = sizeof(uint64_t);
210	maxiter = entry->size / esize;
211	if (maxiter == 0)
212		maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */
213	if (entry->size % esize != 0)
214		xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does "
215			"not have proper size\n", __func__);
216
217	cb->nvals = 0;
218	for (arg = cb->arg; ; arg = end + 1) {
219		if (cb->nvals == maxiter)
220			xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many "
221				"components for option \"--%s\" (max: %u)\n",
222				cb->ext_name, entry->name, maxiter);
223		if (!xtables_strtoul(arg, &end, &value, 0, lmax))
224			xt_params->exit_err(PARAMETER_PROBLEM,
225				"%s: bad value for option \"--%s\" near "
226				"\"%s\", or out of range (0-%ju).\n",
227				cb->ext_name, entry->name, arg, lmax);
228		if (*end != '\0' && *end != sep)
229			xt_params->exit_err(PARAMETER_PROBLEM,
230				"%s: Argument to \"--%s\" has unexpected "
231				"characters near \"%s\".\n",
232				cb->ext_name, entry->name, end);
233		if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) {
234			if (entry->type == XTTYPE_UINT8RC)
235				cb->val.u8_range[cb->nvals] = value;
236			else if (entry->type == XTTYPE_UINT16RC)
237				cb->val.u16_range[cb->nvals] = value;
238			else if (entry->type == XTTYPE_UINT32RC)
239				cb->val.u32_range[cb->nvals] = value;
240			else if (entry->type == XTTYPE_UINT64RC)
241				cb->val.u64_range[cb->nvals] = value;
242		}
243		++cb->nvals;
244		if (entry->flags & XTOPT_PUT) {
245			if (entry->type == XTTYPE_UINT8RC)
246				*(uint8_t *)put = value;
247			else if (entry->type == XTTYPE_UINT16RC)
248				*(uint16_t *)put = value;
249			else if (entry->type == XTTYPE_UINT32RC)
250				*(uint32_t *)put = value;
251			else if (entry->type == XTTYPE_UINT64RC)
252				*(uint64_t *)put = value;
253			put += esize;
254		}
255		if (*end == '\0')
256			break;
257	}
258}
259
260static void xtopt_parse_string(struct xt_option_call *cb)
261{
262	const struct xt_option_entry *entry = cb->entry;
263	size_t z = strlen(cb->arg);
264	char *p;
265
266	if (entry->min != 0 && z < entry->min)
267		xt_params->exit_err(PARAMETER_PROBLEM,
268			"Argument must have a minimum length of "
269			"%u characters\n", entry->min);
270	if (entry->max != 0 && z > entry->max)
271		xt_params->exit_err(PARAMETER_PROBLEM,
272			"Argument must have a maximum length of "
273			"%u characters\n", entry->max);
274	if (!(entry->flags & XTOPT_PUT))
275		return;
276	if (z >= entry->size)
277		z = entry->size - 1;
278	p = XTOPT_MKPTR(cb);
279	strncpy(p, cb->arg, z);
280	p[z] = '\0';
281}
282
283static const struct tos_symbol_info {
284	unsigned char value;
285	const char *name;
286} tos_symbol_names[] = {
287	{IPTOS_LOWDELAY,    "Minimize-Delay"},
288	{IPTOS_THROUGHPUT,  "Maximize-Throughput"},
289	{IPTOS_RELIABILITY, "Maximize-Reliability"},
290	{IPTOS_MINCOST,     "Minimize-Cost"},
291	{IPTOS_NORMALSVC,   "Normal-Service"},
292	{},
293};
294
295/*
296 * tos_parse_numeric - parse a string like "15/255"
297 *
298 * @str:	input string
299 * @tvm:	(value/mask) tuple
300 * @max:	maximum allowed value (must be pow(2,some_int)-1)
301 */
302static bool tos_parse_numeric(const char *str, struct xt_option_call *cb,
303                              unsigned int max)
304{
305	unsigned int value;
306	char *end;
307
308	xtables_strtoui(str, &end, &value, 0, max);
309	cb->val.tos_value = value;
310	cb->val.tos_mask  = max;
311
312	if (*end == '/') {
313		const char *p = end + 1;
314
315		if (!xtables_strtoui(p, &end, &value, 0, max))
316			xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"",
317			           str);
318		cb->val.tos_mask = value;
319	}
320
321	if (*end != '\0')
322		xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str);
323	return true;
324}
325
326/**
327 * @str:	input string
328 * @tvm:	(value/mask) tuple
329 * @def_mask:	mask to force when a symbolic name is used
330 */
331static void xtopt_parse_tosmask(struct xt_option_call *cb)
332{
333	const struct tos_symbol_info *symbol;
334	char *tmp;
335
336	if (xtables_strtoui(cb->arg, &tmp, NULL, 0, UINT8_MAX)) {
337		tos_parse_numeric(cb->arg, cb, UINT8_MAX);
338		return;
339	}
340	/*
341	 * This is our way we deal with different defaults
342	 * for different revisions.
343	 */
344	cb->val.tos_mask = cb->entry->max;
345	for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
346		if (strcasecmp(cb->arg, symbol->name) == 0) {
347			cb->val.tos_value = symbol->value;
348			return;
349		}
350
351	xtables_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown",
352		      cb->arg);
353}
354
355/**
356 * Validate the input for being conformant to "mark[/mask]".
357 */
358static void xtopt_parse_markmask(struct xt_option_call *cb)
359{
360	unsigned int mark = 0, mask = ~0U;
361	char *end;
362
363	if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX))
364		xt_params->exit_err(PARAMETER_PROBLEM,
365			"%s: bad mark value for option \"--%s\", "
366			"or out of range.\n",
367			cb->ext_name, cb->entry->name);
368	if (*end == '/' &&
369	    !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
370		xt_params->exit_err(PARAMETER_PROBLEM,
371			"%s: bad mask value for option \"--%s\", "
372			"or out of range.\n",
373			cb->ext_name, cb->entry->name);
374	if (*end != '\0')
375		xt_params->exit_err(PARAMETER_PROBLEM,
376			"%s: trailing garbage after value "
377			"for option \"--%s\".\n",
378			cb->ext_name, cb->entry->name);
379	cb->val.mark = mark;
380	cb->val.mask = mask;
381}
382
383static int xtopt_sysloglvl_compare(const void *a, const void *b)
384{
385	const char *name = a;
386	const struct syslog_level *entry = b;
387
388	return strcmp(name, entry->name);
389}
390
391static void xtopt_parse_sysloglevel(struct xt_option_call *cb)
392{
393	static const struct syslog_level log_names[] = { /* must be sorted */
394		{"alert",   LOG_ALERT},
395		{"crit",    LOG_CRIT},
396		{"debug",   LOG_DEBUG},
397		{"emerg",   LOG_EMERG},
398		{"error",   LOG_ERR}, /* deprecated */
399		{"info",    LOG_INFO},
400		{"notice",  LOG_NOTICE},
401		{"panic",   LOG_EMERG}, /* deprecated */
402		{"warning", LOG_WARNING},
403	};
404	const struct syslog_level *e;
405	unsigned int num = 0;
406
407	if (!xtables_strtoui(cb->arg, NULL, &num, 0, 7)) {
408		e = bsearch(cb->arg, log_names, ARRAY_SIZE(log_names),
409			    sizeof(*log_names), xtopt_sysloglvl_compare);
410		if (e == NULL)
411			xt_params->exit_err(PARAMETER_PROBLEM,
412				"log level \"%s\" unknown\n", cb->arg);
413		num = e->level;
414	}
415	cb->val.syslog_level = num;
416	if (cb->entry->flags & XTOPT_PUT)
417		*(uint8_t *)XTOPT_MKPTR(cb) = num;
418}
419
420static void *xtables_sa_host(const void *sa, unsigned int afproto)
421{
422	if (afproto == AF_INET6)
423		return &((struct sockaddr_in6 *)sa)->sin6_addr;
424	else if (afproto == AF_INET)
425		return &((struct sockaddr_in *)sa)->sin_addr;
426	return (void *)sa;
427}
428
429static socklen_t xtables_sa_hostlen(unsigned int afproto)
430{
431	if (afproto == AF_INET6)
432		return sizeof(struct in6_addr);
433	else if (afproto == AF_INET)
434		return sizeof(struct in_addr);
435	return 0;
436}
437
438/**
439 * Accepts: a hostname (DNS), or a single inetaddr - without any mask. The
440 * result is stored in @cb->val.haddr. Additionally, @cb->val.hmask and
441 * @cb->val.hlen are set for completeness to the appropriate values.
442 */
443static void xtopt_parse_host(struct xt_option_call *cb)
444{
445	struct addrinfo hints = {.ai_family = afinfo->family};
446	unsigned int adcount = 0;
447	struct addrinfo *res, *p;
448	int ret;
449
450	ret = getaddrinfo(cb->arg, NULL, &hints, &res);
451	if (ret < 0)
452		xt_params->exit_err(PARAMETER_PROBLEM,
453			"getaddrinfo: %s\n", gai_strerror(ret));
454
455	memset(&cb->val.hmask, 0xFF, sizeof(cb->val.hmask));
456	cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128;
457
458	for (p = res; p != NULL; p = p->ai_next) {
459		if (adcount == 0) {
460			memset(&cb->val.haddr, 0, sizeof(cb->val.haddr));
461			memcpy(&cb->val.haddr,
462			       xtables_sa_host(p->ai_addr, p->ai_family),
463			       xtables_sa_hostlen(p->ai_family));
464			++adcount;
465			continue;
466		}
467		if (memcmp(&cb->val.haddr,
468		    xtables_sa_host(p->ai_addr, p->ai_family),
469		    xtables_sa_hostlen(p->ai_family)) != 0)
470			xt_params->exit_err(PARAMETER_PROBLEM,
471				"%s resolves to more than one address\n",
472				cb->arg);
473	}
474
475	freeaddrinfo(res);
476	if (cb->entry->flags & XTOPT_PUT)
477		/* Validation in xtables_option_metavalidate */
478		memcpy(XTOPT_MKPTR(cb), &cb->val.haddr,
479		       sizeof(cb->val.haddr));
480}
481
482/**
483 * @name:	port name, or number as a string (e.g. "http" or "80")
484 *
485 * Resolve a port name to a number. Returns the port number in integral
486 * form on success, or <0 on error. (errno will not be set.)
487 */
488static int xtables_getportbyname(const char *name)
489{
490	struct addrinfo *res = NULL, *p;
491	int ret;
492
493	ret = getaddrinfo(NULL, name, NULL, &res);
494	if (ret < 0)
495		return -1;
496	ret = -1;
497	for (p = res; p != NULL; p = p->ai_next) {
498		if (p->ai_family == AF_INET6) {
499			ret = ((struct sockaddr_in6 *)p->ai_addr)->sin6_port;
500			break;
501		} else if (p->ai_family == AF_INET) {
502			ret = ((struct sockaddr_in *)p->ai_addr)->sin_port;
503			break;
504		}
505	}
506	freeaddrinfo(res);
507	if (ret < 0)
508		return ret;
509	return ntohs(ret);
510}
511
512/**
513 * Validate and parse a protocol specification (number or name) by use of
514 * /etc/protocols and put the result into @cb->val.protocol.
515 */
516static void xtopt_parse_protocol(struct xt_option_call *cb)
517{
518	cb->val.protocol = xtables_parse_protocol(cb->arg);
519	if (cb->entry->flags & XTOPT_PUT)
520		*(uint8_t *)XTOPT_MKPTR(cb) = cb->val.protocol;
521}
522
523/**
524 * Validate and parse a port specification and put the result into
525 * @cb->val.port.
526 */
527static void xtopt_parse_port(struct xt_option_call *cb)
528{
529	const struct xt_option_entry *entry = cb->entry;
530	int ret;
531
532	ret = xtables_getportbyname(cb->arg);
533	if (ret < 0)
534		xt_params->exit_err(PARAMETER_PROBLEM,
535			"Port \"%s\" does not resolve to anything.\n",
536			cb->arg);
537	if (entry->flags & XTOPT_NBO)
538		ret = htons(ret);
539	cb->val.port = ret;
540	if (entry->flags & XTOPT_PUT)
541		*(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port;
542}
543
544static void xtopt_parse_mport(struct xt_option_call *cb)
545{
546	static const size_t esize = sizeof(uint16_t);
547	const struct xt_option_entry *entry = cb->entry;
548	char *lo_arg, *wp_arg, *arg;
549	unsigned int maxiter;
550	int value;
551
552	wp_arg = lo_arg = strdup(cb->arg);
553	if (lo_arg == NULL)
554		xt_params->exit_err(RESOURCE_PROBLEM, "strdup");
555
556	maxiter = entry->size / esize;
557	if (maxiter == 0)
558		maxiter = 2; /* ARRAY_SIZE(cb->val.port_range) */
559	if (entry->size % esize != 0)
560		xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does "
561			"not have proper size\n", __func__);
562
563	cb->val.port_range[0] = 0;
564	cb->val.port_range[1] = UINT16_MAX;
565	cb->nvals = 0;
566
567	while ((arg = strsep(&wp_arg, ":")) != NULL) {
568		if (cb->nvals == maxiter)
569			xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many "
570				"components for option \"--%s\" (max: %u)\n",
571				cb->ext_name, entry->name, maxiter);
572		if (*arg == '\0') {
573			++cb->nvals;
574			continue;
575		}
576
577		value = xtables_getportbyname(arg);
578		if (value < 0)
579			xt_params->exit_err(PARAMETER_PROBLEM,
580				"Port \"%s\" does not resolve to "
581				"anything.\n", arg);
582		if (entry->flags & XTOPT_NBO)
583			value = htons(value);
584		if (cb->nvals < ARRAY_SIZE(cb->val.port_range))
585			cb->val.port_range[cb->nvals] = value;
586		++cb->nvals;
587	}
588
589	if (cb->nvals == 1) {
590		cb->val.port_range[1] = cb->val.port_range[0];
591		++cb->nvals;
592	}
593	if (entry->flags & XTOPT_PUT)
594		memcpy(XTOPT_MKPTR(cb), cb->val.port_range, sizeof(uint16_t) *
595		       (cb->nvals <= maxiter ? cb->nvals : maxiter));
596	free(lo_arg);
597}
598
599/**
600 * Parse an integer and ensure it is within the address family's prefix length
601 * limits. The result is stored in @cb->val.hlen.
602 */
603static void xtopt_parse_plen(struct xt_option_call *cb)
604{
605	const struct xt_option_entry *entry = cb->entry;
606	unsigned int prefix_len = 128; /* happiness is a warm gcc */
607
608	cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128;
609	if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen))
610		xt_params->exit_err(PARAMETER_PROBLEM,
611			"%s: bad value for option \"--%s\", "
612			"or out of range (%u-%u).\n",
613			cb->ext_name, entry->name, 0, cb->val.hlen);
614
615	cb->val.hlen = prefix_len;
616}
617
618/**
619 * Reuse xtopt_parse_plen for testing the integer. Afterwards convert this to
620 * a bitmask, and make it available through @cb->val.hmask (hlen remains
621 * valid). If %XTOPT_PUT is used, hmask will be copied to the target area.
622 */
623static void xtopt_parse_plenmask(struct xt_option_call *cb)
624{
625	const struct xt_option_entry *entry = cb->entry;
626	uint32_t *mask = cb->val.hmask.all;
627
628	xtopt_parse_plen(cb);
629
630	memset(mask, 0xFF, sizeof(union nf_inet_addr));
631	/* This shifting is AF-independent. */
632	if (cb->val.hlen == 0) {
633		mask[0] = mask[1] = mask[2] = mask[3] = 0;
634	} else if (cb->val.hlen <= 32) {
635		mask[0] <<= 32 - cb->val.hlen;
636		mask[1] = mask[2] = mask[3] = 0;
637	} else if (cb->val.hlen <= 64) {
638		mask[1] <<= 32 - (cb->val.hlen - 32);
639		mask[2] = mask[3] = 0;
640	} else if (cb->val.hlen <= 96) {
641		mask[2] <<= 32 - (cb->val.hlen - 64);
642		mask[3] = 0;
643	} else if (cb->val.hlen <= 128) {
644		mask[3] <<= 32 - (cb->val.hlen - 96);
645	}
646	mask[0] = htonl(mask[0]);
647	mask[1] = htonl(mask[1]);
648	mask[2] = htonl(mask[2]);
649	mask[3] = htonl(mask[3]);
650	if (entry->flags & XTOPT_PUT)
651		memcpy(XTOPT_MKPTR(cb), mask, sizeof(union nf_inet_addr));
652}
653
654static void xtopt_parse_hostmask(struct xt_option_call *cb)
655{
656	const char *orig_arg = cb->arg;
657	char *work, *p;
658
659	if (strchr(cb->arg, '/') == NULL) {
660		xtopt_parse_host(cb);
661		return;
662	}
663	work = strdup(orig_arg);
664	if (work == NULL)
665		xt_params->exit_err(PARAMETER_PROBLEM, "strdup");
666	p = strchr(work, '/'); /* by def this can't be NULL now */
667	*p++ = '\0';
668	/*
669	 * Because xtopt_parse_host and xtopt_parse_plenmask would store
670	 * different things in the same target area, XTTYPE_HOSTMASK must
671	 * disallow XTOPT_PUT, which it does by forcing its absence,
672	 * cf. not being listed in xtopt_psize.
673	 */
674	cb->arg = work;
675	xtopt_parse_host(cb);
676	cb->arg = p;
677	xtopt_parse_plenmask(cb);
678	cb->arg = orig_arg;
679}
680
681static void xtopt_parse_ethermac(struct xt_option_call *cb)
682{
683	const char *arg = cb->arg;
684	unsigned int i;
685	char *end;
686
687	for (i = 0; i < ARRAY_SIZE(cb->val.ethermac) - 1; ++i) {
688		cb->val.ethermac[i] = strtoul(arg, &end, 16);
689		if (cb->val.ethermac[i] > UINT8_MAX || *end != ':')
690			goto out;
691		arg = end + 1;
692	}
693	i = ARRAY_SIZE(cb->val.ethermac) - 1;
694	cb->val.ethermac[i] = strtoul(arg, &end, 16);
695	if (cb->val.ethermac[i] > UINT8_MAX || *end != '\0')
696		goto out;
697	if (cb->entry->flags & XTOPT_PUT)
698		memcpy(XTOPT_MKPTR(cb), cb->val.ethermac,
699		       sizeof(cb->val.ethermac));
700	return;
701 out:
702	xt_params->exit_err(PARAMETER_PROBLEM, "ether");
703}
704
705static void (*const xtopt_subparse[])(struct xt_option_call *) = {
706	[XTTYPE_UINT8]       = xtopt_parse_int,
707	[XTTYPE_UINT16]      = xtopt_parse_int,
708	[XTTYPE_UINT32]      = xtopt_parse_int,
709	[XTTYPE_UINT64]      = xtopt_parse_int,
710	[XTTYPE_UINT8RC]     = xtopt_parse_mint,
711	[XTTYPE_UINT16RC]    = xtopt_parse_mint,
712	[XTTYPE_UINT32RC]    = xtopt_parse_mint,
713	[XTTYPE_UINT64RC]    = xtopt_parse_mint,
714	[XTTYPE_DOUBLE]      = xtopt_parse_float,
715	[XTTYPE_STRING]      = xtopt_parse_string,
716	[XTTYPE_TOSMASK]     = xtopt_parse_tosmask,
717	[XTTYPE_MARKMASK32]  = xtopt_parse_markmask,
718	[XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel,
719	[XTTYPE_HOST]        = xtopt_parse_host,
720	[XTTYPE_HOSTMASK]    = xtopt_parse_hostmask,
721	[XTTYPE_PROTOCOL]    = xtopt_parse_protocol,
722	[XTTYPE_PORT]        = xtopt_parse_port,
723	[XTTYPE_PORTRC]      = xtopt_parse_mport,
724	[XTTYPE_PLEN]        = xtopt_parse_plen,
725	[XTTYPE_PLENMASK]    = xtopt_parse_plenmask,
726	[XTTYPE_ETHERMAC]    = xtopt_parse_ethermac,
727};
728
729static const size_t xtopt_psize[] = {
730	/*
731	 * All types not listed here, and thus essentially being initialized to
732	 * zero have zero on purpose.
733	 */
734	[XTTYPE_UINT8]       = sizeof(uint8_t),
735	[XTTYPE_UINT16]      = sizeof(uint16_t),
736	[XTTYPE_UINT32]      = sizeof(uint32_t),
737	[XTTYPE_UINT64]      = sizeof(uint64_t),
738	[XTTYPE_UINT8RC]     = sizeof(uint8_t[2]),
739	[XTTYPE_UINT16RC]    = sizeof(uint16_t[2]),
740	[XTTYPE_UINT32RC]    = sizeof(uint32_t[2]),
741	[XTTYPE_UINT64RC]    = sizeof(uint64_t[2]),
742	[XTTYPE_DOUBLE]      = sizeof(double),
743	[XTTYPE_STRING]      = -1,
744	[XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t),
745	[XTTYPE_HOST]        = sizeof(union nf_inet_addr),
746	[XTTYPE_HOSTMASK]    = sizeof(union nf_inet_addr),
747	[XTTYPE_PROTOCOL]    = sizeof(uint8_t),
748	[XTTYPE_PORT]        = sizeof(uint16_t),
749	[XTTYPE_PORTRC]      = sizeof(uint16_t[2]),
750	[XTTYPE_PLENMASK]    = sizeof(union nf_inet_addr),
751	[XTTYPE_ETHERMAC]    = sizeof(uint8_t[6]),
752};
753
754/**
755 * The master option parsing routine. May be used for the ".x6_parse"
756 * function pointer in extensions if fully automatic parsing is desired.
757 * It may be also called manually from a custom x6_parse function.
758 */
759void xtables_option_parse(struct xt_option_call *cb)
760{
761	const struct xt_option_entry *entry = cb->entry;
762	unsigned int eflag = 1 << cb->entry->id;
763
764	/*
765	 * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use
766	 * prevention. Though it turned out that this is too much typing (most
767	 * of the options are one-time use only), so now we also have
768	 * %XTOPT_MULTI.
769	 */
770	if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) &&
771	    cb->xflags & eflag)
772		xt_params->exit_err(PARAMETER_PROBLEM,
773			"%s: option \"--%s\" can only be used once.\n",
774			cb->ext_name, cb->entry->name);
775	if (cb->invert && !(entry->flags & XTOPT_INVERT))
776		xt_params->exit_err(PARAMETER_PROBLEM,
777			"%s: option \"--%s\" cannot be inverted.\n",
778			cb->ext_name, entry->name);
779	if (entry->type != XTTYPE_NONE && optarg == NULL)
780		xt_params->exit_err(PARAMETER_PROBLEM,
781			"%s: option \"--%s\" requires an argument.\n",
782			cb->ext_name, entry->name);
783	if (entry->type <= ARRAY_SIZE(xtopt_subparse) &&
784	    xtopt_subparse[entry->type] != NULL)
785		xtopt_subparse[entry->type](cb);
786	/* Exclusion with other flags tested later in finalize. */
787	cb->xflags |= 1 << entry->id;
788}
789
790/**
791 * Verifies that an extension's option map descriptor is valid, and ought to
792 * be called right after the extension has been loaded, and before option
793 * merging/xfrm.
794 */
795void xtables_option_metavalidate(const char *name,
796				 const struct xt_option_entry *entry)
797{
798	for (; entry->name != NULL; ++entry) {
799		if (entry->id >= CHAR_BIT * sizeof(unsigned int) ||
800		    entry->id >= XT_OPTION_OFFSET_SCALE)
801			xt_params->exit_err(OTHER_PROBLEM,
802				"Extension %s uses invalid ID %u\n",
803				name, entry->id);
804		if (!(entry->flags & XTOPT_PUT))
805			continue;
806		if (entry->type >= ARRAY_SIZE(xtopt_psize) ||
807		    xtopt_psize[entry->type] == 0)
808			xt_params->exit_err(OTHER_PROBLEM,
809				"%s: entry type of option \"--%s\" cannot be "
810				"combined with XTOPT_PUT\n",
811				name, entry->name);
812		if (xtopt_psize[entry->type] != -1 &&
813		    xtopt_psize[entry->type] != entry->size)
814			xt_params->exit_err(OTHER_PROBLEM,
815				"%s: option \"--%s\" points to a memory block "
816				"of wrong size (expected %zu, got %zu)\n",
817				name, entry->name,
818				xtopt_psize[entry->type], entry->size);
819	}
820}
821
822/**
823 * Find an option entry by its id.
824 */
825static const struct xt_option_entry *
826xtables_option_lookup(const struct xt_option_entry *entry, unsigned int id)
827{
828	for (; entry->name != NULL; ++entry)
829		if (entry->id == id)
830			return entry;
831	return NULL;
832}
833
834/**
835 * @c:		getopt id (i.e. with offset)
836 * @fw:		struct ipt_entry or ip6t_entry
837 *
838 * Dispatch arguments to the appropriate parse function, based upon the
839 * extension's choice of API.
840 */
841void xtables_option_tpcall(unsigned int c, char **argv, bool invert,
842			   struct xtables_target *t, void *fw)
843{
844	struct xt_option_call cb;
845
846	if (t->x6_parse == NULL) {
847		if (t->parse != NULL)
848			t->parse(c - t->option_offset, argv, invert,
849				 &t->tflags, fw, &t->t);
850		return;
851	}
852
853	c -= t->option_offset;
854	cb.entry = xtables_option_lookup(t->x6_options, c);
855	if (cb.entry == NULL)
856		xtables_error(OTHER_PROBLEM,
857			"Extension does not know id %u\n", c);
858	cb.arg      = optarg;
859	cb.invert   = invert;
860	cb.ext_name = t->name;
861	cb.data     = t->t->data;
862	cb.xflags   = t->tflags;
863	cb.target   = &t->t;
864	cb.xt_entry = fw;
865	t->x6_parse(&cb);
866	t->tflags = cb.xflags;
867}
868
869/**
870 * @c:		getopt id (i.e. with offset)
871 * @fw:		struct ipt_entry or ip6t_entry
872 *
873 * Dispatch arguments to the appropriate parse function, based upon the
874 * extension's choice of API.
875 */
876void xtables_option_mpcall(unsigned int c, char **argv, bool invert,
877			   struct xtables_match *m, void *fw)
878{
879	struct xt_option_call cb;
880
881	if (m->x6_parse == NULL) {
882		if (m->parse != NULL)
883			m->parse(c - m->option_offset, argv, invert,
884				 &m->mflags, fw, &m->m);
885		return;
886	}
887
888	c -= m->option_offset;
889	cb.entry = xtables_option_lookup(m->x6_options, c);
890	if (cb.entry == NULL)
891		xtables_error(OTHER_PROBLEM,
892			"Extension does not know id %u\n", c);
893	cb.arg      = optarg;
894	cb.invert   = invert;
895	cb.ext_name = m->name;
896	cb.data     = m->m->data;
897	cb.xflags   = m->mflags;
898	cb.match    = &m->m;
899	cb.xt_entry = fw;
900	m->x6_parse(&cb);
901	m->mflags = cb.xflags;
902}
903
904/**
905 * @name:	name of extension
906 * @entry:	current option (from all ext's entries) being validated
907 * @xflags:	flags the extension has collected
908 * @i:		conflicting option (id) to test for
909 */
910static void
911xtables_option_fcheck2(const char *name, const struct xt_option_entry *entry,
912		       const struct xt_option_entry *other,
913		       unsigned int xflags)
914{
915	unsigned int ef = 1 << entry->id, of = 1 << other->id;
916
917	if (entry->also & of && !(xflags & of))
918		xt_params->exit_err(PARAMETER_PROBLEM,
919			"%s: option \"--%s\" also requires \"--%s\".\n",
920			name, entry->name, other->name);
921
922	if (!(entry->excl & of))
923		/* Use of entry does not collide with other option, good. */
924		return;
925	if ((xflags & (ef | of)) != (ef | of))
926		/* Conflicting options were not used. */
927		return;
928
929	xt_params->exit_err(PARAMETER_PROBLEM,
930		"%s: option \"--%s\" cannot be used together with \"--%s\".\n",
931		name, entry->name, other->name);
932}
933
934/**
935 * @name:	name of extension
936 * @xflags:	accumulated flags
937 * @entry:	extension's option table
938 *
939 * Check that all option constraints have been met. This effectively replaces
940 * ->final_check of the older API.
941 */
942void xtables_options_fcheck(const char *name, unsigned int xflags,
943			    const struct xt_option_entry *table)
944{
945	const struct xt_option_entry *entry, *other;
946	unsigned int i;
947
948	for (entry = table; entry->name != NULL; ++entry) {
949		if (entry->flags & XTOPT_MAND &&
950		    !(xflags & (1 << entry->id)))
951			xt_params->exit_err(PARAMETER_PROBLEM,
952				"%s: option \"--%s\" must be specified\n",
953				name, entry->name);
954		if (!(xflags & (1 << entry->id)))
955			/* Not required, not specified, thus skip. */
956			continue;
957
958		for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) {
959			if (entry->id == i)
960				/*
961				 * Avoid conflict with self. Multi-use check
962				 * was done earlier in xtables_option_parse.
963				 */
964				continue;
965			other = xtables_option_lookup(table, i);
966			if (other == NULL)
967				continue;
968			xtables_option_fcheck2(name, entry, other, xflags);
969		}
970	}
971}
972
973/**
974 * Dispatch arguments to the appropriate final_check function, based upon the
975 * extension's choice of API.
976 */
977void xtables_option_tfcall(struct xtables_target *t)
978{
979	if (t->x6_fcheck != NULL) {
980		struct xt_fcheck_call cb;
981
982		cb.ext_name = t->name;
983		cb.data     = t->t->data;
984		cb.xflags   = t->tflags;
985		t->x6_fcheck(&cb);
986	} else if (t->final_check != NULL) {
987		t->final_check(t->tflags);
988	}
989	if (t->x6_options != NULL)
990		xtables_options_fcheck(t->name, t->tflags, t->x6_options);
991}
992
993/**
994 * Dispatch arguments to the appropriate final_check function, based upon the
995 * extension's choice of API.
996 */
997void xtables_option_mfcall(struct xtables_match *m)
998{
999	if (m->x6_fcheck != NULL) {
1000		struct xt_fcheck_call cb;
1001
1002		cb.ext_name = m->name;
1003		cb.data     = m->m->data;
1004		cb.xflags   = m->mflags;
1005		m->x6_fcheck(&cb);
1006	} else if (m->final_check != NULL) {
1007		m->final_check(m->mflags);
1008	}
1009	if (m->x6_options != NULL)
1010		xtables_options_fcheck(m->name, m->mflags, m->x6_options);
1011}
1012
1013struct xtables_lmap *xtables_lmap_init(const char *file)
1014{
1015	struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this;
1016	char buf[512];
1017	FILE *fp;
1018	char *cur, *nxt;
1019	int id;
1020
1021	fp = fopen(file, "re");
1022	if (fp == NULL)
1023		return NULL;
1024
1025	while (fgets(buf, sizeof(buf), fp) != NULL) {
1026		cur = buf;
1027		while (isspace(*cur))
1028			++cur;
1029		if (*cur == '#' || *cur == '\n' || *cur == '\0')
1030			continue;
1031
1032		/* iproute2 allows hex and dec format */
1033		errno = 0;
1034		id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10);
1035		if (nxt == cur || errno != 0)
1036			continue;
1037
1038		/* same boundaries as in iproute2 */
1039		if (id < 0 || id > 255)
1040			continue;
1041		cur = nxt;
1042
1043		if (!isspace(*cur))
1044			continue;
1045		while (isspace(*cur))
1046			++cur;
1047		if (*cur == '#' || *cur == '\n' || *cur == '\0')
1048			continue;
1049		nxt = cur;
1050		while (*nxt != '\0' && !isspace(*nxt))
1051			++nxt;
1052		if (nxt == cur)
1053			continue;
1054		*nxt = '\0';
1055
1056		/* found valid data */
1057		lmap_this = malloc(sizeof(*lmap_this));
1058		if (lmap_this == NULL) {
1059			perror("malloc");
1060			goto out;
1061		}
1062		lmap_this->id   = id;
1063		lmap_this->name = strdup(cur);
1064		if (lmap_this->name == NULL) {
1065			free(lmap_this);
1066			goto out;
1067		}
1068		lmap_this->next = NULL;
1069
1070		if (lmap_prev != NULL)
1071			lmap_prev->next = lmap_this;
1072		else
1073			lmap_head = lmap_this;
1074		lmap_prev = lmap_this;
1075	}
1076
1077	fclose(fp);
1078	return lmap_head;
1079 out:
1080	xtables_lmap_free(lmap_head);
1081	return NULL;
1082}
1083
1084void xtables_lmap_free(struct xtables_lmap *head)
1085{
1086	struct xtables_lmap *next;
1087
1088	for (; head != NULL; head = next) {
1089		next = head->next;
1090		free(head->name);
1091		free(head);
1092	}
1093}
1094
1095int xtables_lmap_name2id(const struct xtables_lmap *head, const char *name)
1096{
1097	for (; head != NULL; head = head->next)
1098		if (strcmp(head->name, name) == 0)
1099			return head->id;
1100	return -1;
1101}
1102
1103const char *xtables_lmap_id2name(const struct xtables_lmap *head, int id)
1104{
1105	for (; head != NULL; head = head->next)
1106		if (head->id == id)
1107			return head->name;
1108	return NULL;
1109}
1110