xtoptions.c revision 2e0ec4fa0fb5162c441cd666f55fe76777e40d5e
1aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/*
2aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *	Argument parser
3aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *	Copyright © Jan Engelhardt, 2011
4aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
5aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *	This program is free software; you can redistribute it and/or
6aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *	modify it under the terms of the GNU General Public License as
7aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *	published by the Free Software Foundation; either version 2 of
8aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *	the License, or (at your option) any later version.
9aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
102e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt#include <ctype.h>
11aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <errno.h>
12aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <getopt.h>
13aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <limits.h>
14aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <netdb.h>
15aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdbool.h>
16aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdint.h>
17aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdio.h>
18aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdlib.h>
19aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <string.h>
20aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <arpa/inet.h>
21aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "xtables.h"
22aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "xshared.h"
23aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
24aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#define XTOPT_MKPTR(cb) \
25aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	((void *)((char *)(cb)->data + (cb)->entry->ptroff))
26aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
27aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
28aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Creates getopt options from the x6-style option map, and assigns each a
29aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * getopt id.
30aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
31aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstruct option *
32aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_options_xfrm(struct option *orig_opts, struct option *oldopts,
33aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		     const struct xt_option_entry *entry, unsigned int *offset)
34aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
35aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int num_orig, num_old = 0, num_new, i;
36aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	struct option *merge, *mp;
37aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
38aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry == NULL)
39aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return oldopts;
40aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (num_orig = 0; orig_opts[num_orig].name != NULL; ++num_orig)
41aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		;
42aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (oldopts != NULL)
43aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		for (num_old = 0; oldopts[num_old].name != NULL; ++num_old)
44aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			;
45aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (num_new = 0; entry[num_new].name != NULL; ++num_new)
46aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		;
47aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
48aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/*
49aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * Since @oldopts also has @orig_opts already (and does so at the
50aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * start), skip these entries.
51aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 */
52aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	oldopts += num_orig;
53aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	num_old -= num_orig;
54aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
55aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1));
56aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (merge == NULL)
57aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return NULL;
58aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
59aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Let the base options -[ADI...] have precedence over everything */
60aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	memcpy(merge, orig_opts, sizeof(*mp) * num_orig);
61aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	mp = merge + num_orig;
62aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
63aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Second, the new options */
64aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	xt_params->option_offset += XT_OPTION_OFFSET_SCALE;
65aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	*offset = xt_params->option_offset;
66aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
67aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (i = 0; i < num_new; ++i, ++mp, ++entry) {
68aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		mp->name         = entry->name;
69aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		mp->has_arg      = entry->type != XTTYPE_NONE;
70aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		mp->flag         = NULL;
71aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		mp->val          = entry->id + *offset;
72aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
73aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
74aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Third, the old options */
75aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	memcpy(mp, oldopts, sizeof(*mp) * num_old);
76aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	mp += num_old;
77aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	xtables_free_opts(0);
78aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
79aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Clear trailing entry */
80aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	memset(mp, 0, sizeof(*mp));
81aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	return merge;
82aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
83aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
84a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt/**
85a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt * Require a simple integer.
86a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt */
87a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardtstatic void xtopt_parse_int(struct xt_option_call *cb)
88a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt{
89a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	const struct xt_option_entry *entry = cb->entry;
908b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt	unsigned long long lmin = 0, lmax = UINT32_MAX;
91a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	unsigned int value;
92a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt
93dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt	if (entry->type == XTTYPE_UINT8)
94dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt		lmax = UINT8_MAX;
958b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt	else if (entry->type == XTTYPE_UINT64)
968b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt		lmax = UINT64_MAX;
97d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt	if (cb->entry->min != 0)
98d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt		lmin = cb->entry->min;
99d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt	if (cb->entry->max != 0)
100d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt		lmax = cb->entry->max;
101d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt
102a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	if (!xtables_strtoui(cb->arg, NULL, &value, lmin, lmax))
103a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
104a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt			"%s: bad value for option \"--%s\", "
1058b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt			"or out of range (%llu-%llu).\n",
106a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt			cb->ext_name, entry->name, lmin, lmax);
107a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt
108dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt	if (entry->type == XTTYPE_UINT8) {
109dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt		cb->val.u8 = value;
110dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt		if (entry->flags & XTOPT_PUT)
111dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt			*(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8;
112dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt	} else if (entry->type == XTTYPE_UINT32) {
113a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt		cb->val.u32 = value;
114a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt		if (entry->flags & XTOPT_PUT)
115a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt			*(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32;
1168b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt	} else if (entry->type == XTTYPE_UINT64) {
1178b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt		cb->val.u64 = value;
1188b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt		if (entry->flags & XTOPT_PUT)
1198b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt			*(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64;
120a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	}
121a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt}
122a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt
12304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt/**
12404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * Multiple integer parse routine.
12504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt *
12604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * This function is capable of parsing any number of fields. Only the first
12704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * two values from the string will be put into @cb however (and as such,
12804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * @cb->val.uXX_range is just that large) to cater for the few extensions that
12904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * do not have a range[2] field, but {min, max}, and which cannot use
13004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * XTOPT_POINTER.
13104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt */
13204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardtstatic void xtopt_parse_mint(struct xt_option_call *cb)
13304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt{
13404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	const struct xt_option_entry *entry = cb->entry;
13504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	const char *arg = cb->arg;
13604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	uint32_t *put = XTOPT_MKPTR(cb);
13704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	unsigned int maxiter, value;
13804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	char *end = "";
13904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	char sep = ':';
14004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt
14104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	maxiter = entry->size / sizeof(uint32_t);
14204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	if (maxiter == 0)
14304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */
14404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	if (entry->size % sizeof(uint32_t) != 0)
14504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does "
14604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			"not have proper size\n", __func__);
14704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt
14804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	cb->nvals = 0;
14904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	for (arg = cb->arg; ; arg = end + 1) {
15004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (cb->nvals == maxiter)
15104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many "
15204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				"components for option \"--%s\" (max: %u)\n",
15304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				cb->ext_name, entry->name, maxiter);
15404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (!xtables_strtoui(arg, &end, &value, 0, UINT32_MAX))
15504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
15604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				"%s: bad value for option \"--%s\", "
15704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				"or out of range (0-%u).\n",
15804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				cb->ext_name, entry->name, UINT32_MAX);
15904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (*end != '\0' && *end != sep)
16004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
16104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				"%s: Argument to \"--%s\" has unexpected "
16204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				"characters.\n", cb->ext_name, entry->name);
16304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		++cb->nvals;
16404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (cb->nvals < ARRAY_SIZE(cb->val.u32_range))
16504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			cb->val.u32_range[cb->nvals] = value;
16604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (entry->flags & XTOPT_PUT)
16704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			*put++ = value;
16804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (*end == '\0')
16904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			break;
17004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	}
17104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt}
17204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt
1734a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardtstatic void xtopt_parse_string(struct xt_option_call *cb)
1744a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt{
1754a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	const struct xt_option_entry *entry = cb->entry;
1764a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	size_t z = strlen(cb->arg);
1774a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	char *p;
1784a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt
1794a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	if (entry->min != 0 && z < entry->min)
1804a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
1814a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt			"Argument must have a minimum length of "
1824a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt			"%u characters\n", entry->min);
1834a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	if (entry->max != 0 && z > entry->max)
1844a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
1854a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt			"Argument must have a maximum length of "
1864a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt			"%u characters\n", entry->max);
1874a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	if (!(entry->flags & XTOPT_PUT))
1884a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt		return;
1894a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	if (z >= entry->size)
1904a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt		z = entry->size - 1;
1914a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	p = XTOPT_MKPTR(cb);
1924a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	strncpy(p, cb->arg, z);
1934a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	p[z] = '\0';
1944a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt}
1954a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt
196d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt/**
197d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt * Validate the input for being conformant to "mark[/mask]".
198d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt */
199d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardtstatic void xtopt_parse_markmask(struct xt_option_call *cb)
200d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt{
201d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	unsigned int mark = 0, mask = ~0U;
202d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	char *end;
203d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt
204d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX))
205d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
206d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"%s: bad mark value for option \"--%s\", "
207d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"or out of range.\n",
208d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			cb->ext_name, cb->entry->name);
209d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	if (*end == '/' &&
210d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	    !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
211d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
212d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"%s: bad mask value for option \"--%s\", "
213d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"or out of range.\n",
214d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			cb->ext_name, cb->entry->name);
215d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	if (*end != '\0')
216d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
217d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"%s: trailing garbage after value "
218d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"for option \"--%s\".\n",
219d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			cb->ext_name, cb->entry->name);
220d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	cb->val.mark = mark;
221d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	cb->val.mask = mask;
222d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt}
223d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt
224aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void (*const xtopt_subparse[])(struct xt_option_call *) = {
225dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt	[XTTYPE_UINT8]       = xtopt_parse_int,
226a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	[XTTYPE_UINT32]      = xtopt_parse_int,
2278b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt	[XTTYPE_UINT64]      = xtopt_parse_int,
22804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	[XTTYPE_UINT32RC]    = xtopt_parse_mint,
2294a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	[XTTYPE_STRING]      = xtopt_parse_string,
230d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	[XTTYPE_MARKMASK32]  = xtopt_parse_markmask,
231aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt};
232aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
233aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const size_t xtopt_psize[] = {
234dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt	[XTTYPE_UINT8]       = sizeof(uint8_t),
235a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	[XTTYPE_UINT32]      = sizeof(uint32_t),
2368b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt	[XTTYPE_UINT64]      = sizeof(uint64_t),
23704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	[XTTYPE_UINT32RC]    = sizeof(uint32_t[2]),
2384a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	[XTTYPE_STRING]      = -1,
239aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt};
240aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
241aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
242aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * The master option parsing routine. May be used for the ".x6_parse"
243aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * function pointer in extensions if fully automatic parsing is desired.
244aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * It may be also called manually from a custom x6_parse function.
245aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
246aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_parse(struct xt_option_call *cb)
247aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
248aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	const struct xt_option_entry *entry = cb->entry;
249aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int eflag = 1 << cb->entry->id;
250aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
251aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/*
252aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use
253aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * prevention. Though it turned out that this is too much typing (most
254aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * of the options are one-time use only), so now we also have
255aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * %XTOPT_MULTI.
256aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 */
257aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) &&
258aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	    cb->xflags & eflag)
259aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
260aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" can only be used once.\n",
261aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, cb->entry->name);
262aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb->invert && !(entry->flags & XTOPT_INVERT))
263aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
264aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" cannot be inverted.\n",
265aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, entry->name);
266aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->type != XTTYPE_NONE && optarg == NULL)
267aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
268aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" requires an argument.\n",
269aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, entry->name);
270aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->type <= ARRAY_SIZE(xtopt_subparse) &&
271aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	    xtopt_subparse[entry->type] != NULL)
272aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtopt_subparse[entry->type](cb);
273aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Exclusion with other flags tested later in finalize. */
274aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb->xflags |= 1 << entry->id;
275aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
276aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
277aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
278aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Verifies that an extension's option map descriptor is valid, and ought to
279aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * be called right after the extension has been loaded, and before option
280aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * merging/xfrm.
281aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
282aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_metavalidate(const char *name,
283aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 const struct xt_option_entry *entry)
284aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
285aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (; entry->name != NULL; ++entry) {
286aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->id >= CHAR_BIT * sizeof(unsigned int) ||
287aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		    entry->id >= XT_OPTION_OFFSET_SCALE)
288aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
289aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"Extension %s uses invalid ID %u\n",
290aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->id);
291aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (!(entry->flags & XTOPT_PUT))
292aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			continue;
293aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->type >= ARRAY_SIZE(xtopt_psize))
294aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
295aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: entry type of option \"--%s\" cannot be "
296aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"combined with XTOPT_PUT\n",
297aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name);
29804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (xtopt_psize[entry->type] != -1 &&
29904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		    xtopt_psize[entry->type] != entry->size)
300aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
301aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: option \"--%s\" points to a memory block "
302aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"of wrong size (expected %zu, got %zu)\n",
303aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name,
304aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				xtopt_psize[entry->type], entry->size);
305aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
306aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
307aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
308aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
309aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Find an option entry by its id.
310aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
311aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const struct xt_option_entry *
312aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_lookup(const struct xt_option_entry *entry, unsigned int id)
313aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
314aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (; entry->name != NULL; ++entry)
315aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->id == id)
316aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			return entry;
317aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	return NULL;
318aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
319aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
320aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
321aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c:		getopt id (i.e. with offset)
322aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw:		struct ipt_entry or ip6t_entry
323aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
324aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the
325aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API.
326aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
327aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_tpcall(unsigned int c, char **argv, bool invert,
328aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			   struct xtables_target *t, void *fw)
329aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
330aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	struct xt_option_call cb;
331aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
332aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (t->x6_parse == NULL) {
333aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (t->parse != NULL)
334aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			t->parse(c - t->option_offset, argv, invert,
335aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 &t->tflags, fw, &t->t);
336aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
337aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
338aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
339aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	c -= t->option_offset;
340aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.entry = xtables_option_lookup(t->x6_options, c);
341aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb.entry == NULL)
342aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_error(OTHER_PROBLEM,
343aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"Extension does not know id %u\n", c);
344aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.arg      = optarg;
345aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.invert   = invert;
346aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.ext_name = t->name;
347aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.data     = t->t->data;
348aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.xflags   = t->tflags;
349aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	t->x6_parse(&cb);
350aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	t->tflags = cb.xflags;
351aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
352aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
353aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
354aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c:		getopt id (i.e. with offset)
355aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw:		struct ipt_entry or ip6t_entry
356aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
357aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the
358aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API.
359aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
360aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_mpcall(unsigned int c, char **argv, bool invert,
361aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			   struct xtables_match *m, void *fw)
362aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
363aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	struct xt_option_call cb;
364aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
365aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (m->x6_parse == NULL) {
366aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (m->parse != NULL)
367aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			m->parse(c - m->option_offset, argv, invert,
368aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 &m->mflags, fw, &m->m);
369aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
370aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
371aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
372aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	c -= m->option_offset;
373aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.entry = xtables_option_lookup(m->x6_options, c);
374aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb.entry == NULL)
375aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_error(OTHER_PROBLEM,
376aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"Extension does not know id %u\n", c);
377aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.arg      = optarg;
378aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.invert   = invert;
379aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.ext_name = m->name;
380aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.data     = m->m->data;
381aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.xflags   = m->mflags;
382aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	m->x6_parse(&cb);
383aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	m->mflags = cb.xflags;
384aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
385aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
386aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
387aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name:	name of extension
388aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry:	current option (from all ext's entries) being validated
389aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags:	flags the extension has collected
390aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @i:		conflicting option (id) to test for
391aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
392aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void
393aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_fcheck2(const char *name, const struct xt_option_entry *entry,
394aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		       const struct xt_option_entry *other,
395aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		       unsigned int xflags)
396aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
397aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int ef = 1 << entry->id, of = 1 << other->id;
398aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
399aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->also & of && !(xflags & of))
400aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
401aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" also requires \"--%s\".\n",
402aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			name, entry->name, other->name);
403aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
404aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (!(entry->excl & of))
405aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		/* Use of entry does not collide with other option, good. */
406aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
407aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if ((xflags & (ef | of)) != (ef | of))
408aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		/* Conflicting options were not used. */
409aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
410aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
411aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	xt_params->exit_err(PARAMETER_PROBLEM,
412aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		"%s: option \"--%s\" cannot be used together with \"--%s\".\n",
413aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		name, entry->name, other->name);
414aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
415aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
416aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
417aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name:	name of extension
418aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags:	accumulated flags
419aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry:	extension's option table
420aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
421aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Check that all option constraints have been met. This effectively replaces
422aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * ->final_check of the older API.
423aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
424aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_options_fcheck(const char *name, unsigned int xflags,
425aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			    const struct xt_option_entry *table)
426aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
427aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	const struct xt_option_entry *entry, *other;
428aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int i;
429aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
430aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (entry = table; entry->name != NULL; ++entry) {
431aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->flags & XTOPT_MAND &&
432aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		    !(xflags & (1 << entry->id)))
433aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
434aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: option \"--%s\" must be specified\n",
435aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name);
436aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
437aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) {
438aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			if (entry->id == i)
439aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				/*
440aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 * Avoid conflict with self. Multi-use check
441aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 * was done earlier in xtables_option_parse.
442aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 */
443aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				continue;
444aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			other = xtables_option_lookup(table, i);
445aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			if (other == NULL)
446aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				continue;
447aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xtables_option_fcheck2(name, entry, other, xflags);
448aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		}
449aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
450aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
4513af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
4523af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/**
4533af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the
4543af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API.
4553af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */
4563af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_tfcall(struct xtables_target *t)
4573af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{
4583af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (t->x6_fcheck != NULL) {
4593af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		struct xt_fcheck_call cb;
4603af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
4613af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.ext_name = t->name;
4623af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.data     = t->t->data;
4633af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.xflags   = t->tflags;
4643af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		t->x6_fcheck(&cb);
4653af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	} else if (t->final_check != NULL) {
4663af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		t->final_check(t->tflags);
4673af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	}
4683af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (t->x6_options != NULL)
4693af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		xtables_options_fcheck(t->name, t->tflags, t->x6_options);
4703af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt}
4713af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
4723af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/**
4733af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the
4743af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API.
4753af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */
4763af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_mfcall(struct xtables_match *m)
4773af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{
4783af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (m->x6_fcheck != NULL) {
4793af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		struct xt_fcheck_call cb;
4803af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
4813af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.ext_name = m->name;
4823af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.data     = m->m->data;
4833af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.xflags   = m->mflags;
4843af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		m->x6_fcheck(&cb);
4853af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	} else if (m->final_check != NULL) {
4863af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		m->final_check(m->mflags);
4873af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	}
4883af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (m->x6_options != NULL)
4893af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		xtables_options_fcheck(m->name, m->mflags, m->x6_options);
4903af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt}
4912e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
4922e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtstruct xtables_lmap *xtables_lmap_init(const char *file)
4932e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{
4942e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this;
4952e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	char buf[512];
4962e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	FILE *fp;
4972e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	char *cur, *nxt;
4982e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	int id;
4992e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5002e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	fp = fopen(file, "re");
5012e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	if (fp == NULL)
5022e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		return NULL;
5032e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5042e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	while (fgets(buf, sizeof(buf), fp) != NULL) {
5052e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		cur = buf;
5062e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		while (isspace(*cur))
5072e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			++cur;
5082e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (*cur == '#' || *cur == '\n' || *cur == '\0')
5092e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5102e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5112e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		/* iproute2 allows hex and dec format */
5122e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		errno = 0;
5132e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10);
5142e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (nxt == cur || errno != 0)
5152e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5162e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5172e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		/* same boundaries as in iproute2 */
5182e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (id < 0 || id > 255)
5192e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5202e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		cur = nxt;
5212e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5222e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (!isspace(*cur))
5232e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5242e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		while (isspace(*cur))
5252e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			++cur;
5262e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (*cur == '#' || *cur == '\n' || *cur == '\0')
5272e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5282e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		nxt = cur;
5292e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		while (*nxt != '\0' && !isspace(*nxt))
5302e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			++nxt;
5312e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (nxt == cur)
5322e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5332e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		*nxt = '\0';
5342e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5352e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		/* found valid data */
5362e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		lmap_this = malloc(sizeof(*lmap_this));
5372e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (lmap_this == NULL) {
5382e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			perror("malloc");
5392e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			goto out;
5402e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		}
5412e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		lmap_this->id   = id;
5422e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		lmap_this->name = strdup(cur);
5432e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (lmap_this->name == NULL) {
5442e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			free(lmap_this);
5452e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			goto out;
5462e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		}
5472e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		lmap_this->next = NULL;
5482e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5492e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (lmap_prev != NULL)
5502e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			lmap_prev->next = lmap_this;
5512e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		else
5522e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			lmap_head = lmap_this;
5532e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		lmap_prev = lmap_this;
5542e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	}
5552e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5562e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	fclose(fp);
5572e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	return lmap_head;
5582e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt out:
5592e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	xtables_lmap_free(lmap_head);
5602e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	return NULL;
5612e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt}
5622e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5632e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtvoid xtables_lmap_free(struct xtables_lmap *head)
5642e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{
5652e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	struct xtables_lmap *next;
5662e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5672e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	for (; head != NULL; head = next) {
5682e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		next = head->next;
5692e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		free(head->name);
5702e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		free(head);
5712e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	}
5722e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt}
5732e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5742e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtint xtables_lmap_name2id(const struct xtables_lmap *head, const char *name)
5752e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{
5762e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	for (; head != NULL; head = head->next)
5772e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (strcmp(head->name, name) == 0)
5782e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			return head->id;
5792e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	return -1;
5802e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt}
5812e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5822e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtconst char *xtables_lmap_id2name(const struct xtables_lmap *head, int id)
5832e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{
5842e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	for (; head != NULL; head = head->next)
5852e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (head->id == id)
5862e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			return head->name;
5872e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	return NULL;
5882e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt}
589