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