xtoptions.c revision 2e0ec4fa0fb5162c441cd666f55fe76777e40d5e
1aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/* 2aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Argument parser 3aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Copyright © Jan Engelhardt, 2011 4aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 5aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * This program is free software; you can redistribute it and/or 6aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * modify it under the terms of the GNU General Public License as 7aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * published by the Free Software Foundation; either version 2 of 8aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * the License, or (at your option) any later version. 9aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 102e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt#include <ctype.h> 11aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <errno.h> 12aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <getopt.h> 13aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <limits.h> 14aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <netdb.h> 15aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdbool.h> 16aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdint.h> 17aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdio.h> 18aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <stdlib.h> 19aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <string.h> 20aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <arpa/inet.h> 21aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "xtables.h" 22aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "xshared.h" 23aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 24aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#define XTOPT_MKPTR(cb) \ 25aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ((void *)((char *)(cb)->data + (cb)->entry->ptroff)) 26aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 27aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 28aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Creates getopt options from the x6-style option map, and assigns each a 29aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * getopt id. 30aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 31aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstruct option * 32aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_options_xfrm(struct option *orig_opts, struct option *oldopts, 33aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry, unsigned int *offset) 34aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 35aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int num_orig, num_old = 0, num_new, i; 36aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct option *merge, *mp; 37aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 38aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry == NULL) 39aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return oldopts; 40aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_orig = 0; orig_opts[num_orig].name != NULL; ++num_orig) 41aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 42aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (oldopts != NULL) 43aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_old = 0; oldopts[num_old].name != NULL; ++num_old) 44aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 45aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_new = 0; entry[num_new].name != NULL; ++num_new) 46aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 47aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 48aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 49aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Since @oldopts also has @orig_opts already (and does so at the 50aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * start), skip these entries. 51aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 52aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt oldopts += num_orig; 53aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt num_old -= num_orig; 54aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 55aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1)); 56aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (merge == NULL) 57aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return NULL; 58aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 59aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Let the base options -[ADI...] have precedence over everything */ 60aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memcpy(merge, orig_opts, sizeof(*mp) * num_orig); 61aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp = merge + num_orig; 62aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 63aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Second, the new options */ 64aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->option_offset += XT_OPTION_OFFSET_SCALE; 65aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *offset = xt_params->option_offset; 66aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 67aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (i = 0; i < num_new; ++i, ++mp, ++entry) { 68aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->name = entry->name; 69aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->has_arg = entry->type != XTTYPE_NONE; 70aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->flag = NULL; 71aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->val = entry->id + *offset; 72aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 73aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 74aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Third, the old options */ 75aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memcpy(mp, oldopts, sizeof(*mp) * num_old); 76aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp += num_old; 77aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_free_opts(0); 78aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 79aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Clear trailing entry */ 80aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memset(mp, 0, sizeof(*mp)); 81aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return merge; 82aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 83aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 84a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt/** 85a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt * Require a simple integer. 86a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt */ 87a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardtstatic void xtopt_parse_int(struct xt_option_call *cb) 88a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt{ 89a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 908b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt unsigned long long lmin = 0, lmax = UINT32_MAX; 91a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt unsigned int value; 92a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 93dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->type == XTTYPE_UINT8) 94dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt lmax = UINT8_MAX; 958b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt else if (entry->type == XTTYPE_UINT64) 968b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt lmax = UINT64_MAX; 97d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt if (cb->entry->min != 0) 98d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt lmin = cb->entry->min; 99d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt if (cb->entry->max != 0) 100d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt lmax = cb->entry->max; 101d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt 102a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt if (!xtables_strtoui(cb->arg, NULL, &value, lmin, lmax)) 103a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 104a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt "%s: bad value for option \"--%s\", " 1058b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt "or out of range (%llu-%llu).\n", 106a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt cb->ext_name, entry->name, lmin, lmax); 107a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 108dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->type == XTTYPE_UINT8) { 109dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt cb->val.u8 = value; 110dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->flags & XTOPT_PUT) 111dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8; 112dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt } else if (entry->type == XTTYPE_UINT32) { 113a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt cb->val.u32 = value; 114a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt if (entry->flags & XTOPT_PUT) 115a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt *(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32; 1168b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt } else if (entry->type == XTTYPE_UINT64) { 1178b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt cb->val.u64 = value; 1188b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt if (entry->flags & XTOPT_PUT) 1198b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt *(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64; 120a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt } 121a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt} 122a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 12304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt/** 12404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * Multiple integer parse routine. 12504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * 12604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * This function is capable of parsing any number of fields. Only the first 12704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * two values from the string will be put into @cb however (and as such, 12804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * @cb->val.uXX_range is just that large) to cater for the few extensions that 12904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * do not have a range[2] field, but {min, max}, and which cannot use 13004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * XTOPT_POINTER. 13104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt */ 13204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardtstatic void xtopt_parse_mint(struct xt_option_call *cb) 13304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt{ 13404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 13504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt const char *arg = cb->arg; 13604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt uint32_t *put = XTOPT_MKPTR(cb); 13704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt unsigned int maxiter, value; 13804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt char *end = ""; 13904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt char sep = ':'; 14004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 14104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt maxiter = entry->size / sizeof(uint32_t); 14204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (maxiter == 0) 14304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */ 14404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (entry->size % sizeof(uint32_t) != 0) 14504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " 14604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "not have proper size\n", __func__); 14704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 14804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->nvals = 0; 14904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt for (arg = cb->arg; ; arg = end + 1) { 15004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (cb->nvals == maxiter) 15104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " 15204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "components for option \"--%s\" (max: %u)\n", 15304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->ext_name, entry->name, maxiter); 15404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (!xtables_strtoui(arg, &end, &value, 0, UINT32_MAX)) 15504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 15604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "%s: bad value for option \"--%s\", " 15704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "or out of range (0-%u).\n", 15804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->ext_name, entry->name, UINT32_MAX); 15904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (*end != '\0' && *end != sep) 16004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 16104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "%s: Argument to \"--%s\" has unexpected " 16204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "characters.\n", cb->ext_name, entry->name); 16304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt ++cb->nvals; 16404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) 16504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->val.u32_range[cb->nvals] = value; 16604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (entry->flags & XTOPT_PUT) 16704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt *put++ = value; 16804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (*end == '\0') 16904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt break; 17004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt } 17104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt} 17204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 1734a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardtstatic void xtopt_parse_string(struct xt_option_call *cb) 1744a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt{ 1754a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt const struct xt_option_entry *entry = cb->entry; 1764a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt size_t z = strlen(cb->arg); 1774a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt char *p; 1784a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt 1794a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (entry->min != 0 && z < entry->min) 1804a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 1814a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "Argument must have a minimum length of " 1824a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "%u characters\n", entry->min); 1834a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (entry->max != 0 && z > entry->max) 1844a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 1854a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "Argument must have a maximum length of " 1864a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "%u characters\n", entry->max); 1874a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (!(entry->flags & XTOPT_PUT)) 1884a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt return; 1894a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (z >= entry->size) 1904a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt z = entry->size - 1; 1914a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt p = XTOPT_MKPTR(cb); 1924a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt strncpy(p, cb->arg, z); 1934a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt p[z] = '\0'; 1944a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt} 1954a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt 196d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt/** 197d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt * Validate the input for being conformant to "mark[/mask]". 198d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt */ 199d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardtstatic void xtopt_parse_markmask(struct xt_option_call *cb) 200d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt{ 201d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt unsigned int mark = 0, mask = ~0U; 202d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt char *end; 203d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt 204d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX)) 205d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 206d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: bad mark value for option \"--%s\", " 207d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "or out of range.\n", 208d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 209d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (*end == '/' && 210d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) 211d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 212d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: bad mask value for option \"--%s\", " 213d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "or out of range.\n", 214d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 215d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (*end != '\0') 216d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 217d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: trailing garbage after value " 218d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "for option \"--%s\".\n", 219d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 220d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->val.mark = mark; 221d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->val.mask = mask; 222d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt} 223d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt 224aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void (*const xtopt_subparse[])(struct xt_option_call *) = { 225dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt [XTTYPE_UINT8] = xtopt_parse_int, 226a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt [XTTYPE_UINT32] = xtopt_parse_int, 2278b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt [XTTYPE_UINT64] = xtopt_parse_int, 22804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt [XTTYPE_UINT32RC] = xtopt_parse_mint, 2294a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt [XTTYPE_STRING] = xtopt_parse_string, 230d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt [XTTYPE_MARKMASK32] = xtopt_parse_markmask, 231aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}; 232aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 233aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const size_t xtopt_psize[] = { 234dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt [XTTYPE_UINT8] = sizeof(uint8_t), 235a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt [XTTYPE_UINT32] = sizeof(uint32_t), 2368b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt [XTTYPE_UINT64] = sizeof(uint64_t), 23704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), 2384a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt [XTTYPE_STRING] = -1, 239aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}; 240aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 241aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 242aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * The master option parsing routine. May be used for the ".x6_parse" 243aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * function pointer in extensions if fully automatic parsing is desired. 244aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * It may be also called manually from a custom x6_parse function. 245aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 246aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_parse(struct xt_option_call *cb) 247aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 248aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 249aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int eflag = 1 << cb->entry->id; 250aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 251aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 252aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use 253aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * prevention. Though it turned out that this is too much typing (most 254aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * of the options are one-time use only), so now we also have 255aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * %XTOPT_MULTI. 256aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 257aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) && 258aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->xflags & eflag) 259aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 260aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" can only be used once.\n", 261aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, cb->entry->name); 262aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb->invert && !(entry->flags & XTOPT_INVERT)) 263aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 264aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" cannot be inverted.\n", 265aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, entry->name); 266aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type != XTTYPE_NONE && optarg == NULL) 267aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 268aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" requires an argument.\n", 269aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, entry->name); 270aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type <= ARRAY_SIZE(xtopt_subparse) && 271aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_subparse[entry->type] != NULL) 272aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_subparse[entry->type](cb); 273aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Exclusion with other flags tested later in finalize. */ 274aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->xflags |= 1 << entry->id; 275aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 276aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 277aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 278aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Verifies that an extension's option map descriptor is valid, and ought to 279aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * be called right after the extension has been loaded, and before option 280aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * merging/xfrm. 281aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 282aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_metavalidate(const char *name, 283aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry) 284aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 285aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (; entry->name != NULL; ++entry) { 286aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id >= CHAR_BIT * sizeof(unsigned int) || 287aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt entry->id >= XT_OPTION_OFFSET_SCALE) 288aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 289aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension %s uses invalid ID %u\n", 290aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->id); 291aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (!(entry->flags & XTOPT_PUT)) 292aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 293aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type >= ARRAY_SIZE(xtopt_psize)) 294aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 295aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: entry type of option \"--%s\" cannot be " 296aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "combined with XTOPT_PUT\n", 297aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name); 29804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (xtopt_psize[entry->type] != -1 && 29904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xtopt_psize[entry->type] != entry->size) 300aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 301aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" points to a memory block " 302aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "of wrong size (expected %zu, got %zu)\n", 303aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, 304aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_psize[entry->type], entry->size); 305aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 306aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 307aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 308aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 309aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Find an option entry by its id. 310aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 311aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const struct xt_option_entry * 312aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_lookup(const struct xt_option_entry *entry, unsigned int id) 313aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 314aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (; entry->name != NULL; ++entry) 315aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id == id) 316aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return entry; 317aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return NULL; 318aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 319aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 320aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 321aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c: getopt id (i.e. with offset) 322aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw: struct ipt_entry or ip6t_entry 323aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 324aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the 325aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API. 326aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 327aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_tpcall(unsigned int c, char **argv, bool invert, 328aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xtables_target *t, void *fw) 329aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 330aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xt_option_call cb; 331aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 332aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (t->x6_parse == NULL) { 333aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (t->parse != NULL) 334aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->parse(c - t->option_offset, argv, invert, 335aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt &t->tflags, fw, &t->t); 336aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 337aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 338aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 339aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt c -= t->option_offset; 340aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.entry = xtables_option_lookup(t->x6_options, c); 341aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb.entry == NULL) 342aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_error(OTHER_PROBLEM, 343aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension does not know id %u\n", c); 344aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.arg = optarg; 345aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.invert = invert; 346aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.ext_name = t->name; 347aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.data = t->t->data; 348aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.xflags = t->tflags; 349aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->x6_parse(&cb); 350aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->tflags = cb.xflags; 351aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 352aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 353aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 354aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c: getopt id (i.e. with offset) 355aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw: struct ipt_entry or ip6t_entry 356aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 357aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the 358aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API. 359aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 360aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_mpcall(unsigned int c, char **argv, bool invert, 361aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xtables_match *m, void *fw) 362aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 363aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xt_option_call cb; 364aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 365aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (m->x6_parse == NULL) { 366aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (m->parse != NULL) 367aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->parse(c - m->option_offset, argv, invert, 368aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt &m->mflags, fw, &m->m); 369aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 370aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 371aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 372aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt c -= m->option_offset; 373aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.entry = xtables_option_lookup(m->x6_options, c); 374aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb.entry == NULL) 375aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_error(OTHER_PROBLEM, 376aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension does not know id %u\n", c); 377aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.arg = optarg; 378aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.invert = invert; 379aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.ext_name = m->name; 380aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.data = m->m->data; 381aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.xflags = m->mflags; 382aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->x6_parse(&cb); 383aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->mflags = cb.xflags; 384aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 385aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 386aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 387aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name: name of extension 388aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry: current option (from all ext's entries) being validated 389aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags: flags the extension has collected 390aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @i: conflicting option (id) to test for 391aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 392aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void 393aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_fcheck2(const char *name, const struct xt_option_entry *entry, 394aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *other, 395aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int xflags) 396aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 397aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int ef = 1 << entry->id, of = 1 << other->id; 398aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 399aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->also & of && !(xflags & of)) 400aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 401aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" also requires \"--%s\".\n", 402aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, other->name); 403aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 404aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (!(entry->excl & of)) 405aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Use of entry does not collide with other option, good. */ 406aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 407aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if ((xflags & (ef | of)) != (ef | of)) 408aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Conflicting options were not used. */ 409aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 410aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 411aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 412aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" cannot be used together with \"--%s\".\n", 413aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, other->name); 414aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 415aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 416aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 417aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name: name of extension 418aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags: accumulated flags 419aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry: extension's option table 420aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 421aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Check that all option constraints have been met. This effectively replaces 422aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * ->final_check of the older API. 423aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 424aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_options_fcheck(const char *name, unsigned int xflags, 425aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *table) 426aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 427aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry, *other; 428aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int i; 429aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 430aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (entry = table; entry->name != NULL; ++entry) { 431aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->flags & XTOPT_MAND && 432aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt !(xflags & (1 << entry->id))) 433aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 434aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" must be specified\n", 435aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name); 436aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 437aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) { 438aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id == i) 439aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 440aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Avoid conflict with self. Multi-use check 441aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * was done earlier in xtables_option_parse. 442aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 443aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 444aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt other = xtables_option_lookup(table, i); 445aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (other == NULL) 446aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 447aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_option_fcheck2(name, entry, other, xflags); 448aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 449aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 450aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 4513af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 4523af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/** 4533af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the 4543af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API. 4553af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */ 4563af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_tfcall(struct xtables_target *t) 4573af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{ 4583af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (t->x6_fcheck != NULL) { 4593af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt struct xt_fcheck_call cb; 4603af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 4613af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.ext_name = t->name; 4623af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.data = t->t->data; 4633af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.xflags = t->tflags; 4643af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt t->x6_fcheck(&cb); 4653af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } else if (t->final_check != NULL) { 4663af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt t->final_check(t->tflags); 4673af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } 4683af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (t->x6_options != NULL) 4693af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt xtables_options_fcheck(t->name, t->tflags, t->x6_options); 4703af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt} 4713af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 4723af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/** 4733af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the 4743af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API. 4753af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */ 4763af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_mfcall(struct xtables_match *m) 4773af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{ 4783af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (m->x6_fcheck != NULL) { 4793af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt struct xt_fcheck_call cb; 4803af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 4813af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.ext_name = m->name; 4823af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.data = m->m->data; 4833af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.xflags = m->mflags; 4843af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt m->x6_fcheck(&cb); 4853af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } else if (m->final_check != NULL) { 4863af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt m->final_check(m->mflags); 4873af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } 4883af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (m->x6_options != NULL) 4893af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt xtables_options_fcheck(m->name, m->mflags, m->x6_options); 4903af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt} 4912e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 4922e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtstruct xtables_lmap *xtables_lmap_init(const char *file) 4932e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 4942e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this; 4952e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt char buf[512]; 4962e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt FILE *fp; 4972e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt char *cur, *nxt; 4982e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt int id; 4992e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5002e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt fp = fopen(file, "re"); 5012e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (fp == NULL) 5022e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 5032e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5042e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (fgets(buf, sizeof(buf), fp) != NULL) { 5052e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt cur = buf; 5062e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (isspace(*cur)) 5072e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++cur; 5082e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (*cur == '#' || *cur == '\n' || *cur == '\0') 5092e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 5102e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5112e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* iproute2 allows hex and dec format */ 5122e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt errno = 0; 5132e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10); 5142e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (nxt == cur || errno != 0) 5152e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 5162e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5172e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* same boundaries as in iproute2 */ 5182e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (id < 0 || id > 255) 5192e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 5202e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt cur = nxt; 5212e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5222e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (!isspace(*cur)) 5232e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 5242e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (isspace(*cur)) 5252e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++cur; 5262e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (*cur == '#' || *cur == '\n' || *cur == '\0') 5272e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 5282e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt nxt = cur; 5292e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (*nxt != '\0' && !isspace(*nxt)) 5302e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++nxt; 5312e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (nxt == cur) 5322e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 5332e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt *nxt = '\0'; 5342e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5352e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* found valid data */ 5362e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this = malloc(sizeof(*lmap_this)); 5372e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_this == NULL) { 5382e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt perror("malloc"); 5392e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt goto out; 5402e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 5412e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->id = id; 5422e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->name = strdup(cur); 5432e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_this->name == NULL) { 5442e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(lmap_this); 5452e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt goto out; 5462e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 5472e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->next = NULL; 5482e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5492e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_prev != NULL) 5502e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_prev->next = lmap_this; 5512e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt else 5522e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_head = lmap_this; 5532e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_prev = lmap_this; 5542e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 5552e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5562e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt fclose(fp); 5572e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return lmap_head; 5582e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt out: 5592e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt xtables_lmap_free(lmap_head); 5602e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 5612e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 5622e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5632e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtvoid xtables_lmap_free(struct xtables_lmap *head) 5642e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 5652e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt struct xtables_lmap *next; 5662e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5672e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = next) { 5682e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt next = head->next; 5692e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(head->name); 5702e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(head); 5712e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 5722e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 5732e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5742e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtint xtables_lmap_name2id(const struct xtables_lmap *head, const char *name) 5752e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 5762e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = head->next) 5772e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (strcmp(head->name, name) == 0) 5782e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return head->id; 5792e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return -1; 5802e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 5812e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 5822e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtconst char *xtables_lmap_id2name(const struct xtables_lmap *head, int id) 5832e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 5842e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = head->next) 5852e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (head->id == id) 5862e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return head->name; 5872e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 5882e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 589