xtoptions.c revision d78254d7f9d18ef76377a3013302430cce8ea702
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 */
10aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <errno.h>
11aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <getopt.h>
12aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <limits.h>
13aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <netdb.h>
14aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdbool.h>
15aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdint.h>
16aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdio.h>
17aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdlib.h>
18aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <string.h>
19aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <arpa/inet.h>
20aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "xtables.h"
21aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "xshared.h"
22aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
23aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#define XTOPT_MKPTR(cb) \
24aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	((void *)((char *)(cb)->data + (cb)->entry->ptroff))
25aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
26aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
27aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Creates getopt options from the x6-style option map, and assigns each a
28aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * getopt id.
29aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
30aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstruct option *
31aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_options_xfrm(struct option *orig_opts, struct option *oldopts,
32aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		     const struct xt_option_entry *entry, unsigned int *offset)
33aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
34aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int num_orig, num_old = 0, num_new, i;
35aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	struct option *merge, *mp;
36aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
37aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry == NULL)
38aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return oldopts;
39aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (num_orig = 0; orig_opts[num_orig].name != NULL; ++num_orig)
40aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		;
41aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (oldopts != NULL)
42aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		for (num_old = 0; oldopts[num_old].name != NULL; ++num_old)
43aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			;
44aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (num_new = 0; entry[num_new].name != NULL; ++num_new)
45aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		;
46aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
47aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/*
48aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * Since @oldopts also has @orig_opts already (and does so at the
49aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * start), skip these entries.
50aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 */
51aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	oldopts += num_orig;
52aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	num_old -= num_orig;
53aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
54aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1));
55aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (merge == NULL)
56aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return NULL;
57aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
58aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Let the base options -[ADI...] have precedence over everything */
59aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	memcpy(merge, orig_opts, sizeof(*mp) * num_orig);
60aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	mp = merge + num_orig;
61aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
62aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Second, the new options */
63aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	xt_params->option_offset += XT_OPTION_OFFSET_SCALE;
64aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	*offset = xt_params->option_offset;
65aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
66aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (i = 0; i < num_new; ++i, ++mp, ++entry) {
67aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		mp->name         = entry->name;
68aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		mp->has_arg      = entry->type != XTTYPE_NONE;
69aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		mp->flag         = NULL;
70aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		mp->val          = entry->id + *offset;
71aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
72aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
73aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Third, the old options */
74aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	memcpy(mp, oldopts, sizeof(*mp) * num_old);
75aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	mp += num_old;
76aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	xtables_free_opts(0);
77aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
78aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Clear trailing entry */
79aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	memset(mp, 0, sizeof(*mp));
80aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	return merge;
81aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
82aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
83a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt/**
84a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt * Require a simple integer.
85a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt */
86a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardtstatic void xtopt_parse_int(struct xt_option_call *cb)
87a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt{
88a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	const struct xt_option_entry *entry = cb->entry;
89a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	unsigned int lmin = 0, lmax = UINT32_MAX;
90a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	unsigned int value;
91a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt
92d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt	if (cb->entry->min != 0)
93d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt		lmin = cb->entry->min;
94d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt	if (cb->entry->max != 0)
95d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt		lmax = cb->entry->max;
96d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt
97a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	if (!xtables_strtoui(cb->arg, NULL, &value, lmin, lmax))
98a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
99a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt			"%s: bad value for option \"--%s\", "
100a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt			"or out of range (%u-%u).\n",
101a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt			cb->ext_name, entry->name, lmin, lmax);
102a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt
103a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	if (entry->type == XTTYPE_UINT32) {
104a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt		cb->val.u32 = value;
105a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt		if (entry->flags & XTOPT_PUT)
106a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt			*(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32;
107a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	}
108a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt}
109a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt
110aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void (*const xtopt_subparse[])(struct xt_option_call *) = {
111a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	[XTTYPE_UINT32]      = xtopt_parse_int,
112aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt};
113aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
114aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const size_t xtopt_psize[] = {
115a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	[XTTYPE_UINT32]      = sizeof(uint32_t),
116aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt};
117aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
118aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
119aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * The master option parsing routine. May be used for the ".x6_parse"
120aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * function pointer in extensions if fully automatic parsing is desired.
121aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * It may be also called manually from a custom x6_parse function.
122aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
123aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_parse(struct xt_option_call *cb)
124aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
125aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	const struct xt_option_entry *entry = cb->entry;
126aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int eflag = 1 << cb->entry->id;
127aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
128aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/*
129aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use
130aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * prevention. Though it turned out that this is too much typing (most
131aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * of the options are one-time use only), so now we also have
132aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * %XTOPT_MULTI.
133aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 */
134aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) &&
135aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	    cb->xflags & eflag)
136aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
137aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" can only be used once.\n",
138aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, cb->entry->name);
139aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb->invert && !(entry->flags & XTOPT_INVERT))
140aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
141aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" cannot be inverted.\n",
142aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, entry->name);
143aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->type != XTTYPE_NONE && optarg == NULL)
144aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
145aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" requires an argument.\n",
146aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, entry->name);
147aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->type <= ARRAY_SIZE(xtopt_subparse) &&
148aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	    xtopt_subparse[entry->type] != NULL)
149aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtopt_subparse[entry->type](cb);
150aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Exclusion with other flags tested later in finalize. */
151aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb->xflags |= 1 << entry->id;
152aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
153aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
154aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
155aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Verifies that an extension's option map descriptor is valid, and ought to
156aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * be called right after the extension has been loaded, and before option
157aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * merging/xfrm.
158aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
159aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_metavalidate(const char *name,
160aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 const struct xt_option_entry *entry)
161aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
162aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (; entry->name != NULL; ++entry) {
163aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->id >= CHAR_BIT * sizeof(unsigned int) ||
164aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		    entry->id >= XT_OPTION_OFFSET_SCALE)
165aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
166aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"Extension %s uses invalid ID %u\n",
167aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->id);
168aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (!(entry->flags & XTOPT_PUT))
169aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			continue;
170aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->type >= ARRAY_SIZE(xtopt_psize))
171aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
172aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: entry type of option \"--%s\" cannot be "
173aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"combined with XTOPT_PUT\n",
174aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name);
175aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (xtopt_psize[entry->type] != entry->size)
176aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
177aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: option \"--%s\" points to a memory block "
178aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"of wrong size (expected %zu, got %zu)\n",
179aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name,
180aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				xtopt_psize[entry->type], entry->size);
181aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
182aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
183aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
184aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
185aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Find an option entry by its id.
186aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
187aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const struct xt_option_entry *
188aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_lookup(const struct xt_option_entry *entry, unsigned int id)
189aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
190aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (; entry->name != NULL; ++entry)
191aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->id == id)
192aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			return entry;
193aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	return NULL;
194aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
195aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
196aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
197aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c:		getopt id (i.e. with offset)
198aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw:		struct ipt_entry or ip6t_entry
199aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
200aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the
201aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API.
202aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
203aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_tpcall(unsigned int c, char **argv, bool invert,
204aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			   struct xtables_target *t, void *fw)
205aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
206aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	struct xt_option_call cb;
207aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
208aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (t->x6_parse == NULL) {
209aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (t->parse != NULL)
210aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			t->parse(c - t->option_offset, argv, invert,
211aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 &t->tflags, fw, &t->t);
212aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
213aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
214aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
215aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	c -= t->option_offset;
216aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.entry = xtables_option_lookup(t->x6_options, c);
217aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb.entry == NULL)
218aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_error(OTHER_PROBLEM,
219aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"Extension does not know id %u\n", c);
220aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.arg      = optarg;
221aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.invert   = invert;
222aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.ext_name = t->name;
223aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.data     = t->t->data;
224aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.xflags   = t->tflags;
225aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	t->x6_parse(&cb);
226aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	t->tflags = cb.xflags;
227aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
228aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
229aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
230aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c:		getopt id (i.e. with offset)
231aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw:		struct ipt_entry or ip6t_entry
232aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
233aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the
234aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API.
235aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
236aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_mpcall(unsigned int c, char **argv, bool invert,
237aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			   struct xtables_match *m, void *fw)
238aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
239aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	struct xt_option_call cb;
240aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
241aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (m->x6_parse == NULL) {
242aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (m->parse != NULL)
243aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			m->parse(c - m->option_offset, argv, invert,
244aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 &m->mflags, fw, &m->m);
245aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
246aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
247aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
248aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	c -= m->option_offset;
249aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.entry = xtables_option_lookup(m->x6_options, c);
250aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb.entry == NULL)
251aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_error(OTHER_PROBLEM,
252aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"Extension does not know id %u\n", c);
253aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.arg      = optarg;
254aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.invert   = invert;
255aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.ext_name = m->name;
256aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.data     = m->m->data;
257aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.xflags   = m->mflags;
258aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	m->x6_parse(&cb);
259aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	m->mflags = cb.xflags;
260aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
261aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
262aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
263aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name:	name of extension
264aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry:	current option (from all ext's entries) being validated
265aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags:	flags the extension has collected
266aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @i:		conflicting option (id) to test for
267aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
268aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void
269aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_fcheck2(const char *name, const struct xt_option_entry *entry,
270aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		       const struct xt_option_entry *other,
271aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		       unsigned int xflags)
272aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
273aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int ef = 1 << entry->id, of = 1 << other->id;
274aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
275aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->also & of && !(xflags & of))
276aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
277aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" also requires \"--%s\".\n",
278aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			name, entry->name, other->name);
279aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
280aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (!(entry->excl & of))
281aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		/* Use of entry does not collide with other option, good. */
282aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
283aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if ((xflags & (ef | of)) != (ef | of))
284aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		/* Conflicting options were not used. */
285aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
286aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
287aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	xt_params->exit_err(PARAMETER_PROBLEM,
288aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		"%s: option \"--%s\" cannot be used together with \"--%s\".\n",
289aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		name, entry->name, other->name);
290aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
291aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
292aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
293aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name:	name of extension
294aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags:	accumulated flags
295aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry:	extension's option table
296aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
297aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Check that all option constraints have been met. This effectively replaces
298aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * ->final_check of the older API.
299aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
300aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_options_fcheck(const char *name, unsigned int xflags,
301aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			    const struct xt_option_entry *table)
302aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
303aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	const struct xt_option_entry *entry, *other;
304aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int i;
305aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
306aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (entry = table; entry->name != NULL; ++entry) {
307aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->flags & XTOPT_MAND &&
308aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		    !(xflags & (1 << entry->id)))
309aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
310aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: option \"--%s\" must be specified\n",
311aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name);
312aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
313aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) {
314aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			if (entry->id == i)
315aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				/*
316aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 * Avoid conflict with self. Multi-use check
317aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 * was done earlier in xtables_option_parse.
318aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 */
319aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				continue;
320aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			other = xtables_option_lookup(table, i);
321aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			if (other == NULL)
322aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				continue;
323aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xtables_option_fcheck2(name, entry, other, xflags);
324aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		}
325aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
326aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
3273af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
3283af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/**
3293af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the
3303af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API.
3313af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */
3323af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_tfcall(struct xtables_target *t)
3333af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{
3343af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (t->x6_fcheck != NULL) {
3353af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		struct xt_fcheck_call cb;
3363af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
3373af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.ext_name = t->name;
3383af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.data     = t->t->data;
3393af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.xflags   = t->tflags;
3403af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		t->x6_fcheck(&cb);
3413af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	} else if (t->final_check != NULL) {
3423af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		t->final_check(t->tflags);
3433af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	}
3443af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (t->x6_options != NULL)
3453af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		xtables_options_fcheck(t->name, t->tflags, t->x6_options);
3463af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt}
3473af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
3483af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/**
3493af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the
3503af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API.
3513af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */
3523af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_mfcall(struct xtables_match *m)
3533af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{
3543af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (m->x6_fcheck != NULL) {
3553af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		struct xt_fcheck_call cb;
3563af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
3573af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.ext_name = m->name;
3583af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.data     = m->m->data;
3593af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.xflags   = m->mflags;
3603af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		m->x6_fcheck(&cb);
3613af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	} else if (m->final_check != NULL) {
3623af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		m->final_check(m->mflags);
3633af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	}
3643af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (m->x6_options != NULL)
3653af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		xtables_options_fcheck(m->name, m->mflags, m->x6_options);
3663af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt}
367