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