xtoptions.c revision aa37acc1423126f555135935c687eb91995b9440
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
83aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void (*const xtopt_subparse[])(struct xt_option_call *) = {
84aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	[XTTYPE_NONE]        = NULL,
85aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt};
86aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
87aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const size_t xtopt_psize[] = {
88aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	[XTTYPE_NONE]        = 0,
89aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt};
90aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
91aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
92aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * The master option parsing routine. May be used for the ".x6_parse"
93aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * function pointer in extensions if fully automatic parsing is desired.
94aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * It may be also called manually from a custom x6_parse function.
95aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
96aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_parse(struct xt_option_call *cb)
97aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
98aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	const struct xt_option_entry *entry = cb->entry;
99aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int eflag = 1 << cb->entry->id;
100aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
101aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/*
102aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use
103aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * prevention. Though it turned out that this is too much typing (most
104aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * of the options are one-time use only), so now we also have
105aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * %XTOPT_MULTI.
106aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 */
107aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) &&
108aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	    cb->xflags & eflag)
109aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
110aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" can only be used once.\n",
111aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, cb->entry->name);
112aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb->invert && !(entry->flags & XTOPT_INVERT))
113aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
114aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" cannot be inverted.\n",
115aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, entry->name);
116aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->type != XTTYPE_NONE && optarg == NULL)
117aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
118aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" requires an argument.\n",
119aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, entry->name);
120aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->type <= ARRAY_SIZE(xtopt_subparse) &&
121aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	    xtopt_subparse[entry->type] != NULL)
122aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtopt_subparse[entry->type](cb);
123aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Exclusion with other flags tested later in finalize. */
124aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb->xflags |= 1 << entry->id;
125aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
126aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
127aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
128aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Verifies that an extension's option map descriptor is valid, and ought to
129aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * be called right after the extension has been loaded, and before option
130aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * merging/xfrm.
131aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
132aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_metavalidate(const char *name,
133aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 const struct xt_option_entry *entry)
134aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
135aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (; entry->name != NULL; ++entry) {
136aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->id >= CHAR_BIT * sizeof(unsigned int) ||
137aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		    entry->id >= XT_OPTION_OFFSET_SCALE)
138aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
139aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"Extension %s uses invalid ID %u\n",
140aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->id);
141aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (!(entry->flags & XTOPT_PUT))
142aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			continue;
143aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->type >= ARRAY_SIZE(xtopt_psize))
144aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
145aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: entry type of option \"--%s\" cannot be "
146aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"combined with XTOPT_PUT\n",
147aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name);
148aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (xtopt_psize[entry->type] != entry->size)
149aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
150aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: option \"--%s\" points to a memory block "
151aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"of wrong size (expected %zu, got %zu)\n",
152aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name,
153aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				xtopt_psize[entry->type], entry->size);
154aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
155aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
156aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
157aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
158aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Find an option entry by its id.
159aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
160aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const struct xt_option_entry *
161aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_lookup(const struct xt_option_entry *entry, unsigned int id)
162aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
163aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (; entry->name != NULL; ++entry)
164aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->id == id)
165aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			return entry;
166aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	return NULL;
167aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
168aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
169aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
170aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c:		getopt id (i.e. with offset)
171aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw:		struct ipt_entry or ip6t_entry
172aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
173aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the
174aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API.
175aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
176aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_tpcall(unsigned int c, char **argv, bool invert,
177aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			   struct xtables_target *t, void *fw)
178aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
179aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	struct xt_option_call cb;
180aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
181aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (t->x6_parse == NULL) {
182aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (t->parse != NULL)
183aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			t->parse(c - t->option_offset, argv, invert,
184aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 &t->tflags, fw, &t->t);
185aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
186aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
187aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
188aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	c -= t->option_offset;
189aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.entry = xtables_option_lookup(t->x6_options, c);
190aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb.entry == NULL)
191aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_error(OTHER_PROBLEM,
192aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"Extension does not know id %u\n", c);
193aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.arg      = optarg;
194aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.invert   = invert;
195aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.ext_name = t->name;
196aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.data     = t->t->data;
197aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.xflags   = t->tflags;
198aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	t->x6_parse(&cb);
199aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	t->tflags = cb.xflags;
200aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
201aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
202aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
203aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c:		getopt id (i.e. with offset)
204aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw:		struct ipt_entry or ip6t_entry
205aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
206aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the
207aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API.
208aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
209aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_mpcall(unsigned int c, char **argv, bool invert,
210aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			   struct xtables_match *m, void *fw)
211aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
212aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	struct xt_option_call cb;
213aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
214aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (m->x6_parse == NULL) {
215aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (m->parse != NULL)
216aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			m->parse(c - m->option_offset, argv, invert,
217aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 &m->mflags, fw, &m->m);
218aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
219aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
220aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
221aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	c -= m->option_offset;
222aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.entry = xtables_option_lookup(m->x6_options, c);
223aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb.entry == NULL)
224aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_error(OTHER_PROBLEM,
225aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"Extension does not know id %u\n", c);
226aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.arg      = optarg;
227aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.invert   = invert;
228aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.ext_name = m->name;
229aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.data     = m->m->data;
230aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.xflags   = m->mflags;
231aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	m->x6_parse(&cb);
232aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	m->mflags = cb.xflags;
233aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
234aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
235aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
236aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name:	name of extension
237aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry:	current option (from all ext's entries) being validated
238aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags:	flags the extension has collected
239aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @i:		conflicting option (id) to test for
240aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
241aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void
242aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_fcheck2(const char *name, const struct xt_option_entry *entry,
243aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		       const struct xt_option_entry *other,
244aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		       unsigned int xflags)
245aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
246aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int ef = 1 << entry->id, of = 1 << other->id;
247aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
248aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->also & of && !(xflags & of))
249aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
250aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" also requires \"--%s\".\n",
251aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			name, entry->name, other->name);
252aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
253aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (!(entry->excl & of))
254aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		/* Use of entry does not collide with other option, good. */
255aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
256aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if ((xflags & (ef | of)) != (ef | of))
257aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		/* Conflicting options were not used. */
258aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
259aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
260aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	xt_params->exit_err(PARAMETER_PROBLEM,
261aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		"%s: option \"--%s\" cannot be used together with \"--%s\".\n",
262aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		name, entry->name, other->name);
263aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
264aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
265aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
266aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name:	name of extension
267aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags:	accumulated flags
268aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry:	extension's option table
269aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
270aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Check that all option constraints have been met. This effectively replaces
271aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * ->final_check of the older API.
272aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
273aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_options_fcheck(const char *name, unsigned int xflags,
274aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			    const struct xt_option_entry *table)
275aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
276aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	const struct xt_option_entry *entry, *other;
277aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int i;
278aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
279aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (entry = table; entry->name != NULL; ++entry) {
280aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->flags & XTOPT_MAND &&
281aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		    !(xflags & (1 << entry->id)))
282aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
283aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: option \"--%s\" must be specified\n",
284aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name);
285aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
286aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) {
287aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			if (entry->id == i)
288aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				/*
289aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 * Avoid conflict with self. Multi-use check
290aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 * was done earlier in xtables_option_parse.
291aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 */
292aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				continue;
293aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			other = xtables_option_lookup(table, i);
294aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			if (other == NULL)
295aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				continue;
296aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xtables_option_fcheck2(name, entry, other, xflags);
297aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		}
298aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
299aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
300