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