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