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