xtoptions.c revision 33d180871bea281a448efd0c1a49517318162382
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;
950eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt	else if (entry->type == XTTYPE_UINT16)
960eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt		lmax = UINT16_MAX;
978b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt	else if (entry->type == XTTYPE_UINT64)
988b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt		lmax = UINT64_MAX;
99d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt	if (cb->entry->min != 0)
100d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt		lmin = cb->entry->min;
101d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt	if (cb->entry->max != 0)
102d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt		lmax = cb->entry->max;
103d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt
104a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	if (!xtables_strtoui(cb->arg, NULL, &value, lmin, lmax))
105a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
106a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt			"%s: bad value for option \"--%s\", "
1078b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt			"or out of range (%llu-%llu).\n",
108a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt			cb->ext_name, entry->name, lmin, lmax);
109a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt
110dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt	if (entry->type == XTTYPE_UINT8) {
111dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt		cb->val.u8 = value;
112dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt		if (entry->flags & XTOPT_PUT)
113dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt			*(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8;
1140eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt	} else if (entry->type == XTTYPE_UINT16) {
1150eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt		cb->val.u16 = value;
1160eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt		if (entry->flags & XTOPT_PUT)
1170eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt			*(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16;
118dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt	} else if (entry->type == XTTYPE_UINT32) {
119a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt		cb->val.u32 = value;
120a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt		if (entry->flags & XTOPT_PUT)
121a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt			*(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32;
1228b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt	} else if (entry->type == XTTYPE_UINT64) {
1238b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt		cb->val.u64 = value;
1248b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt		if (entry->flags & XTOPT_PUT)
1258b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt			*(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64;
126a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	}
127a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt}
128a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt
12904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt/**
13004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * Multiple integer parse routine.
13104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt *
13204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * This function is capable of parsing any number of fields. Only the first
13304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * two values from the string will be put into @cb however (and as such,
13404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * @cb->val.uXX_range is just that large) to cater for the few extensions that
13504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * do not have a range[2] field, but {min, max}, and which cannot use
13604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * XTOPT_POINTER.
13704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt */
13804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardtstatic void xtopt_parse_mint(struct xt_option_call *cb)
13904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt{
14004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	const struct xt_option_entry *entry = cb->entry;
14104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	const char *arg = cb->arg;
142564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt	size_t esize = sizeof(uint32_t);
143564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt	char *put = XTOPT_MKPTR(cb);
14404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	unsigned int maxiter, value;
14504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	char *end = "";
14604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	char sep = ':';
14704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt
1488bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt	if (entry->type == XTTYPE_UINT8RC)
1498bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt		esize = sizeof(uint8_t);
1508bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt	else if (entry->type == XTTYPE_UINT16RC)
151564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt		esize = sizeof(uint16_t);
152bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt	else if (entry->type == XTTYPE_UINT64RC)
153bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt		esize = sizeof(uint64_t);
154564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt	maxiter = entry->size / esize;
15504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	if (maxiter == 0)
15604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */
157564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt	if (entry->size % esize != 0)
15804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does "
15904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			"not have proper size\n", __func__);
16004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt
16104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	cb->nvals = 0;
16204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	for (arg = cb->arg; ; arg = end + 1) {
16304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (cb->nvals == maxiter)
16404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many "
16504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				"components for option \"--%s\" (max: %u)\n",
16604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				cb->ext_name, entry->name, maxiter);
16704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (!xtables_strtoui(arg, &end, &value, 0, UINT32_MAX))
16804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
16904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				"%s: bad value for option \"--%s\", "
17004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				"or out of range (0-%u).\n",
17104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				cb->ext_name, entry->name, UINT32_MAX);
17204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (*end != '\0' && *end != sep)
17304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
17404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				"%s: Argument to \"--%s\" has unexpected "
17504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt				"characters.\n", cb->ext_name, entry->name);
17604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		++cb->nvals;
177564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt		if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) {
1788bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt			if (entry->type == XTTYPE_UINT8RC)
1798bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt				cb->val.u8_range[cb->nvals] = value;
1808bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt			else if (entry->type == XTTYPE_UINT16RC)
181564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt				cb->val.u16_range[cb->nvals] = value;
182564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt			else if (entry->type == XTTYPE_UINT32RC)
183564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt				cb->val.u32_range[cb->nvals] = value;
184bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt			else if (entry->type == XTTYPE_UINT64RC)
185bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt				cb->val.u64_range[cb->nvals] = value;
186564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt		}
187564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt		if (entry->flags & XTOPT_PUT) {
1888bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt			if (entry->type == XTTYPE_UINT8RC)
1898bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt				*(uint8_t *)put = value;
1908bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt			else if (entry->type == XTTYPE_UINT16RC)
191564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt				*(uint16_t *)put = value;
192564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt			else if (entry->type == XTTYPE_UINT32RC)
193564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt				*(uint32_t *)put = value;
194bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt			else if (entry->type == XTTYPE_UINT64RC)
195bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt				*(uint64_t *)put = value;
196564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt			put += esize;
197564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt		}
19804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (*end == '\0')
19904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt			break;
20004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	}
20104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt}
20204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt
2034a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardtstatic void xtopt_parse_string(struct xt_option_call *cb)
2044a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt{
2054a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	const struct xt_option_entry *entry = cb->entry;
2064a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	size_t z = strlen(cb->arg);
2074a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	char *p;
2084a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt
2094a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	if (entry->min != 0 && z < entry->min)
2104a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
2114a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt			"Argument must have a minimum length of "
2124a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt			"%u characters\n", entry->min);
2134a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	if (entry->max != 0 && z > entry->max)
2144a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
2154a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt			"Argument must have a maximum length of "
2164a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt			"%u characters\n", entry->max);
2174a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	if (!(entry->flags & XTOPT_PUT))
2184a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt		return;
2194a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	if (z >= entry->size)
2204a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt		z = entry->size - 1;
2214a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	p = XTOPT_MKPTR(cb);
2224a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	strncpy(p, cb->arg, z);
2234a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	p[z] = '\0';
2244a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt}
2254a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt
226d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt/**
227d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt * Validate the input for being conformant to "mark[/mask]".
228d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt */
229d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardtstatic void xtopt_parse_markmask(struct xt_option_call *cb)
230d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt{
231d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	unsigned int mark = 0, mask = ~0U;
232d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	char *end;
233d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt
234d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX))
235d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
236d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"%s: bad mark value for option \"--%s\", "
237d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"or out of range.\n",
238d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			cb->ext_name, cb->entry->name);
239d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	if (*end == '/' &&
240d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	    !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
241d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
242d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"%s: bad mask value for option \"--%s\", "
243d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"or out of range.\n",
244d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			cb->ext_name, cb->entry->name);
245d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	if (*end != '\0')
246d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
247d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"%s: trailing garbage after value "
248d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			"for option \"--%s\".\n",
249d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt			cb->ext_name, cb->entry->name);
250d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	cb->val.mark = mark;
251d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	cb->val.mask = mask;
252d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt}
253d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt
254aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void (*const xtopt_subparse[])(struct xt_option_call *) = {
255dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt	[XTTYPE_UINT8]       = xtopt_parse_int,
2560eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt	[XTTYPE_UINT16]      = xtopt_parse_int,
257a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	[XTTYPE_UINT32]      = xtopt_parse_int,
2588b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt	[XTTYPE_UINT64]      = xtopt_parse_int,
2598bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt	[XTTYPE_UINT8RC]     = xtopt_parse_mint,
260564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt	[XTTYPE_UINT16RC]    = xtopt_parse_mint,
26104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	[XTTYPE_UINT32RC]    = xtopt_parse_mint,
262bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt	[XTTYPE_UINT64RC]    = xtopt_parse_mint,
2634a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	[XTTYPE_STRING]      = xtopt_parse_string,
264d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt	[XTTYPE_MARKMASK32]  = xtopt_parse_markmask,
265aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt};
266aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
267aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const size_t xtopt_psize[] = {
268dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt	[XTTYPE_UINT8]       = sizeof(uint8_t),
2690eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt	[XTTYPE_UINT16]      = sizeof(uint16_t),
270a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt	[XTTYPE_UINT32]      = sizeof(uint32_t),
2718b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt	[XTTYPE_UINT64]      = sizeof(uint64_t),
2728bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt	[XTTYPE_UINT8RC]     = sizeof(uint8_t[2]),
273564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt	[XTTYPE_UINT16RC]    = sizeof(uint16_t[2]),
27404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt	[XTTYPE_UINT32RC]    = sizeof(uint32_t[2]),
275bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt	[XTTYPE_UINT64RC]    = sizeof(uint64_t[2]),
2764a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt	[XTTYPE_STRING]      = -1,
277aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt};
278aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
279aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
280aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * The master option parsing routine. May be used for the ".x6_parse"
281aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * function pointer in extensions if fully automatic parsing is desired.
282aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * It may be also called manually from a custom x6_parse function.
283aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
284aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_parse(struct xt_option_call *cb)
285aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
286aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	const struct xt_option_entry *entry = cb->entry;
287aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int eflag = 1 << cb->entry->id;
288aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
289aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/*
290aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use
291aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * prevention. Though it turned out that this is too much typing (most
292aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * of the options are one-time use only), so now we also have
293aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 * %XTOPT_MULTI.
294aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	 */
295aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) &&
296aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	    cb->xflags & eflag)
297aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
298aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" can only be used once.\n",
299aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, cb->entry->name);
300aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb->invert && !(entry->flags & XTOPT_INVERT))
301aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
302aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" cannot be inverted.\n",
303aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, entry->name);
304aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->type != XTTYPE_NONE && optarg == NULL)
305aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
306aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" requires an argument.\n",
307aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			cb->ext_name, entry->name);
308aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->type <= ARRAY_SIZE(xtopt_subparse) &&
309aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	    xtopt_subparse[entry->type] != NULL)
310aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtopt_subparse[entry->type](cb);
311aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	/* Exclusion with other flags tested later in finalize. */
312aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb->xflags |= 1 << entry->id;
313aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
314aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
315aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
316aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Verifies that an extension's option map descriptor is valid, and ought to
317aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * be called right after the extension has been loaded, and before option
318aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * merging/xfrm.
319aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
320aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_metavalidate(const char *name,
321aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 const struct xt_option_entry *entry)
322aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
323aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (; entry->name != NULL; ++entry) {
324aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->id >= CHAR_BIT * sizeof(unsigned int) ||
325aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		    entry->id >= XT_OPTION_OFFSET_SCALE)
326aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
327aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"Extension %s uses invalid ID %u\n",
328aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->id);
329aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (!(entry->flags & XTOPT_PUT))
330aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			continue;
331aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->type >= ARRAY_SIZE(xtopt_psize))
332aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
333aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: entry type of option \"--%s\" cannot be "
334aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"combined with XTOPT_PUT\n",
335aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name);
33604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		if (xtopt_psize[entry->type] != -1 &&
33704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt		    xtopt_psize[entry->type] != entry->size)
338aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(OTHER_PROBLEM,
339aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: option \"--%s\" points to a memory block "
340aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"of wrong size (expected %zu, got %zu)\n",
341aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name,
342aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				xtopt_psize[entry->type], entry->size);
343aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
344aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
345aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
346aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
347aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Find an option entry by its id.
348aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
349aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const struct xt_option_entry *
350aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_lookup(const struct xt_option_entry *entry, unsigned int id)
351aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
352aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (; entry->name != NULL; ++entry)
353aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->id == id)
354aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			return entry;
355aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	return NULL;
356aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
357aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
358aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
359aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c:		getopt id (i.e. with offset)
360aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw:		struct ipt_entry or ip6t_entry
361aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
362aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the
363aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API.
364aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
365aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_tpcall(unsigned int c, char **argv, bool invert,
366aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			   struct xtables_target *t, void *fw)
367aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
368aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	struct xt_option_call cb;
369aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
370aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (t->x6_parse == NULL) {
371aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (t->parse != NULL)
372aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			t->parse(c - t->option_offset, argv, invert,
373aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 &t->tflags, fw, &t->t);
374aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
375aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
376aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
377aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	c -= t->option_offset;
378aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.entry = xtables_option_lookup(t->x6_options, c);
379aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb.entry == NULL)
380aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_error(OTHER_PROBLEM,
381aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"Extension does not know id %u\n", c);
382aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.arg      = optarg;
383aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.invert   = invert;
384aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.ext_name = t->name;
385aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.data     = t->t->data;
386aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.xflags   = t->tflags;
38733d180871bea281a448efd0c1a49517318162382Jan Engelhardt	cb.target   = &t->t;
388aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	t->x6_parse(&cb);
389aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	t->tflags = cb.xflags;
390aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
391aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
392aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
393aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c:		getopt id (i.e. with offset)
394aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw:		struct ipt_entry or ip6t_entry
395aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
396aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the
397aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API.
398aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
399aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_mpcall(unsigned int c, char **argv, bool invert,
400aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			   struct xtables_match *m, void *fw)
401aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
402aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	struct xt_option_call cb;
403aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
404aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (m->x6_parse == NULL) {
405aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (m->parse != NULL)
406aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			m->parse(c - m->option_offset, argv, invert,
407aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 &m->mflags, fw, &m->m);
408aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
409aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
410aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
411aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	c -= m->option_offset;
412aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.entry = xtables_option_lookup(m->x6_options, c);
413aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (cb.entry == NULL)
414aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xtables_error(OTHER_PROBLEM,
415aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"Extension does not know id %u\n", c);
416aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.arg      = optarg;
417aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.invert   = invert;
418aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.ext_name = m->name;
419aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.data     = m->m->data;
420aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	cb.xflags   = m->mflags;
42133d180871bea281a448efd0c1a49517318162382Jan Engelhardt	cb.match    = &m->m;
422aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	m->x6_parse(&cb);
423aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	m->mflags = cb.xflags;
424aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
425aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
426aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
427aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name:	name of extension
428aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry:	current option (from all ext's entries) being validated
429aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags:	flags the extension has collected
430aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @i:		conflicting option (id) to test for
431aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
432aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void
433aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_fcheck2(const char *name, const struct xt_option_entry *entry,
434aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		       const struct xt_option_entry *other,
435aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		       unsigned int xflags)
436aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
437aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int ef = 1 << entry->id, of = 1 << other->id;
438aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
439aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (entry->also & of && !(xflags & of))
440aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		xt_params->exit_err(PARAMETER_PROBLEM,
441aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			"%s: option \"--%s\" also requires \"--%s\".\n",
442aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			name, entry->name, other->name);
443aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
444aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if (!(entry->excl & of))
445aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		/* Use of entry does not collide with other option, good. */
446aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
447aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	if ((xflags & (ef | of)) != (ef | of))
448aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		/* Conflicting options were not used. */
449aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		return;
450aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
451aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	xt_params->exit_err(PARAMETER_PROBLEM,
452aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		"%s: option \"--%s\" cannot be used together with \"--%s\".\n",
453aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		name, entry->name, other->name);
454aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
455aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
456aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/**
457aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name:	name of extension
458aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags:	accumulated flags
459aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry:	extension's option table
460aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *
461aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Check that all option constraints have been met. This effectively replaces
462aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * ->final_check of the older API.
463aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */
464aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_options_fcheck(const char *name, unsigned int xflags,
465aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			    const struct xt_option_entry *table)
466aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{
467aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	const struct xt_option_entry *entry, *other;
468aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	unsigned int i;
469aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
470aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	for (entry = table; entry->name != NULL; ++entry) {
471aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		if (entry->flags & XTOPT_MAND &&
472aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		    !(xflags & (1 << entry->id)))
473aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xt_params->exit_err(PARAMETER_PROBLEM,
474aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				"%s: option \"--%s\" must be specified\n",
475aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				name, entry->name);
476aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt
477aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) {
478aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			if (entry->id == i)
479aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				/*
480aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 * Avoid conflict with self. Multi-use check
481aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 * was done earlier in xtables_option_parse.
482aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				 */
483aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				continue;
484aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			other = xtables_option_lookup(table, i);
485aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			if (other == NULL)
486aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt				continue;
487aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt			xtables_option_fcheck2(name, entry, other, xflags);
488aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt		}
489aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt	}
490aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}
4913af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
4923af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/**
4933af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the
4943af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API.
4953af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */
4963af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_tfcall(struct xtables_target *t)
4973af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{
4983af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (t->x6_fcheck != NULL) {
4993af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		struct xt_fcheck_call cb;
5003af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
5013af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.ext_name = t->name;
5023af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.data     = t->t->data;
5033af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.xflags   = t->tflags;
5043af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		t->x6_fcheck(&cb);
5053af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	} else if (t->final_check != NULL) {
5063af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		t->final_check(t->tflags);
5073af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	}
5083af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (t->x6_options != NULL)
5093af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		xtables_options_fcheck(t->name, t->tflags, t->x6_options);
5103af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt}
5113af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
5123af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/**
5133af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the
5143af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API.
5153af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */
5163af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_mfcall(struct xtables_match *m)
5173af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{
5183af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (m->x6_fcheck != NULL) {
5193af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		struct xt_fcheck_call cb;
5203af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt
5213af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.ext_name = m->name;
5223af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.data     = m->m->data;
5233af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		cb.xflags   = m->mflags;
5243af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		m->x6_fcheck(&cb);
5253af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	} else if (m->final_check != NULL) {
5263af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		m->final_check(m->mflags);
5273af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	}
5283af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt	if (m->x6_options != NULL)
5293af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt		xtables_options_fcheck(m->name, m->mflags, m->x6_options);
5303af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt}
5312e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5322e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtstruct xtables_lmap *xtables_lmap_init(const char *file)
5332e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{
5342e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this;
5352e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	char buf[512];
5362e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	FILE *fp;
5372e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	char *cur, *nxt;
5382e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	int id;
5392e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5402e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	fp = fopen(file, "re");
5412e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	if (fp == NULL)
5422e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		return NULL;
5432e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5442e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	while (fgets(buf, sizeof(buf), fp) != NULL) {
5452e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		cur = buf;
5462e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		while (isspace(*cur))
5472e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			++cur;
5482e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (*cur == '#' || *cur == '\n' || *cur == '\0')
5492e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5502e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5512e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		/* iproute2 allows hex and dec format */
5522e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		errno = 0;
5532e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10);
5542e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (nxt == cur || errno != 0)
5552e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5562e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5572e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		/* same boundaries as in iproute2 */
5582e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (id < 0 || id > 255)
5592e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5602e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		cur = nxt;
5612e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5622e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (!isspace(*cur))
5632e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5642e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		while (isspace(*cur))
5652e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			++cur;
5662e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (*cur == '#' || *cur == '\n' || *cur == '\0')
5672e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5682e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		nxt = cur;
5692e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		while (*nxt != '\0' && !isspace(*nxt))
5702e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			++nxt;
5712e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (nxt == cur)
5722e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			continue;
5732e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		*nxt = '\0';
5742e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5752e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		/* found valid data */
5762e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		lmap_this = malloc(sizeof(*lmap_this));
5772e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (lmap_this == NULL) {
5782e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			perror("malloc");
5792e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			goto out;
5802e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		}
5812e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		lmap_this->id   = id;
5822e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		lmap_this->name = strdup(cur);
5832e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (lmap_this->name == NULL) {
5842e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			free(lmap_this);
5852e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			goto out;
5862e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		}
5872e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		lmap_this->next = NULL;
5882e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5892e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (lmap_prev != NULL)
5902e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			lmap_prev->next = lmap_this;
5912e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		else
5922e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			lmap_head = lmap_this;
5932e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		lmap_prev = lmap_this;
5942e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	}
5952e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
5962e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	fclose(fp);
5972e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	return lmap_head;
5982e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt out:
5992e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	xtables_lmap_free(lmap_head);
6002e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	return NULL;
6012e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt}
6022e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
6032e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtvoid xtables_lmap_free(struct xtables_lmap *head)
6042e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{
6052e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	struct xtables_lmap *next;
6062e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
6072e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	for (; head != NULL; head = next) {
6082e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		next = head->next;
6092e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		free(head->name);
6102e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		free(head);
6112e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	}
6122e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt}
6132e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
6142e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtint xtables_lmap_name2id(const struct xtables_lmap *head, const char *name)
6152e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{
6162e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	for (; head != NULL; head = head->next)
6172e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (strcmp(head->name, name) == 0)
6182e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			return head->id;
6192e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	return -1;
6202e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt}
6212e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt
6222e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtconst char *xtables_lmap_id2name(const struct xtables_lmap *head, int id)
6232e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{
6242e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	for (; head != NULL; head = head->next)
6252e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt		if (head->id == id)
6262e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt			return head->name;
6272e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt	return NULL;
6282e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt}
629