xtoptions.c revision b8592fa3352018646b0befaa48f930f75c5b7d92
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> 2041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt#include <syslog.h> 21aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include <arpa/inet.h> 22aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "xtables.h" 23aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "xshared.h" 24aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 25aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#define XTOPT_MKPTR(cb) \ 26aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ((void *)((char *)(cb)->data + (cb)->entry->ptroff)) 27aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 28aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 2941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt * Simple key-value pairs for syslog levels 3041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt */ 3141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardtstruct syslog_level { 3241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt char name[8]; 3341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt uint8_t level; 3441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt}; 3541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 3641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt/** 37aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Creates getopt options from the x6-style option map, and assigns each a 38aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * getopt id. 39aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 40aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstruct option * 41aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_options_xfrm(struct option *orig_opts, struct option *oldopts, 42aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry, unsigned int *offset) 43aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 44aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int num_orig, num_old = 0, num_new, i; 45aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct option *merge, *mp; 46aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 47aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry == NULL) 48aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return oldopts; 49aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_orig = 0; orig_opts[num_orig].name != NULL; ++num_orig) 50aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 51aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (oldopts != NULL) 52aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_old = 0; oldopts[num_old].name != NULL; ++num_old) 53aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 54aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_new = 0; entry[num_new].name != NULL; ++num_new) 55aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 56aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 57aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 58aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Since @oldopts also has @orig_opts already (and does so at the 59aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * start), skip these entries. 60aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 61aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt oldopts += num_orig; 62aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt num_old -= num_orig; 63aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 64aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1)); 65aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (merge == NULL) 66aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return NULL; 67aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 68aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Let the base options -[ADI...] have precedence over everything */ 69aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memcpy(merge, orig_opts, sizeof(*mp) * num_orig); 70aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp = merge + num_orig; 71aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 72aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Second, the new options */ 73aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->option_offset += XT_OPTION_OFFSET_SCALE; 74aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *offset = xt_params->option_offset; 75aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 76aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (i = 0; i < num_new; ++i, ++mp, ++entry) { 77aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->name = entry->name; 78aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->has_arg = entry->type != XTTYPE_NONE; 79aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->flag = NULL; 80aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->val = entry->id + *offset; 81aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 82aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 83aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Third, the old options */ 84aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memcpy(mp, oldopts, sizeof(*mp) * num_old); 85aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp += num_old; 86aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_free_opts(0); 87aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 88aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Clear trailing entry */ 89aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memset(mp, 0, sizeof(*mp)); 90aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return merge; 91aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 92aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 93a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt/** 94a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt * Require a simple integer. 95a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt */ 96a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardtstatic void xtopt_parse_int(struct xt_option_call *cb) 97a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt{ 98a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 998b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt unsigned long long lmin = 0, lmax = UINT32_MAX; 100a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt unsigned int value; 101a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 102dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->type == XTTYPE_UINT8) 103dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt lmax = UINT8_MAX; 1040eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt else if (entry->type == XTTYPE_UINT16) 1050eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt lmax = UINT16_MAX; 1068b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt else if (entry->type == XTTYPE_UINT64) 1078b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt lmax = UINT64_MAX; 108d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt if (cb->entry->min != 0) 109d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt lmin = cb->entry->min; 110d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt if (cb->entry->max != 0) 111d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt lmax = cb->entry->max; 112d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt 113a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt if (!xtables_strtoui(cb->arg, NULL, &value, lmin, lmax)) 114a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 115a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt "%s: bad value for option \"--%s\", " 1168b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt "or out of range (%llu-%llu).\n", 117a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt cb->ext_name, entry->name, lmin, lmax); 118a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 119dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->type == XTTYPE_UINT8) { 120dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt cb->val.u8 = value; 121dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->flags & XTOPT_PUT) 122dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8; 1230eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt } else if (entry->type == XTTYPE_UINT16) { 1240eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt cb->val.u16 = value; 1250eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt if (entry->flags & XTOPT_PUT) 1260eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16; 127dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt } else if (entry->type == XTTYPE_UINT32) { 128a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt cb->val.u32 = value; 129a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt if (entry->flags & XTOPT_PUT) 130a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt *(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32; 1318b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt } else if (entry->type == XTTYPE_UINT64) { 1328b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt cb->val.u64 = value; 1338b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt if (entry->flags & XTOPT_PUT) 1348b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt *(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64; 135a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt } 136a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt} 137a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 13804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt/** 13904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * Multiple integer parse routine. 14004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * 14104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * This function is capable of parsing any number of fields. Only the first 14204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * two values from the string will be put into @cb however (and as such, 14304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * @cb->val.uXX_range is just that large) to cater for the few extensions that 14404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * do not have a range[2] field, but {min, max}, and which cannot use 14504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * XTOPT_POINTER. 14604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt */ 14704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardtstatic void xtopt_parse_mint(struct xt_option_call *cb) 14804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt{ 14904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 15004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt const char *arg = cb->arg; 151564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt size_t esize = sizeof(uint32_t); 152564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt char *put = XTOPT_MKPTR(cb); 15304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt unsigned int maxiter, value; 15404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt char *end = ""; 15504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt char sep = ':'; 15604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 1578bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt if (entry->type == XTTYPE_UINT8RC) 1588bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt esize = sizeof(uint8_t); 1598bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt else if (entry->type == XTTYPE_UINT16RC) 160564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt esize = sizeof(uint16_t); 161bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt else if (entry->type == XTTYPE_UINT64RC) 162bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt esize = sizeof(uint64_t); 163564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt maxiter = entry->size / esize; 16404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (maxiter == 0) 16504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */ 166564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt if (entry->size % esize != 0) 16704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " 16804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "not have proper size\n", __func__); 16904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 17004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->nvals = 0; 17104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt for (arg = cb->arg; ; arg = end + 1) { 17204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (cb->nvals == maxiter) 17304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " 17404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "components for option \"--%s\" (max: %u)\n", 17504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->ext_name, entry->name, maxiter); 17604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (!xtables_strtoui(arg, &end, &value, 0, UINT32_MAX)) 17704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 17804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "%s: bad value for option \"--%s\", " 17904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "or out of range (0-%u).\n", 18004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->ext_name, entry->name, UINT32_MAX); 18104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (*end != '\0' && *end != sep) 18204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 18304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "%s: Argument to \"--%s\" has unexpected " 18404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "characters.\n", cb->ext_name, entry->name); 18504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt ++cb->nvals; 186564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) { 1878bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt if (entry->type == XTTYPE_UINT8RC) 1888bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt cb->val.u8_range[cb->nvals] = value; 1898bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt else if (entry->type == XTTYPE_UINT16RC) 190564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt cb->val.u16_range[cb->nvals] = value; 191564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt else if (entry->type == XTTYPE_UINT32RC) 192564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt cb->val.u32_range[cb->nvals] = value; 193bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt else if (entry->type == XTTYPE_UINT64RC) 194bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt cb->val.u64_range[cb->nvals] = value; 195564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt } 196564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt if (entry->flags & XTOPT_PUT) { 1978bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt if (entry->type == XTTYPE_UINT8RC) 1988bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt *(uint8_t *)put = value; 1998bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt else if (entry->type == XTTYPE_UINT16RC) 200564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt *(uint16_t *)put = value; 201564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt else if (entry->type == XTTYPE_UINT32RC) 202564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt *(uint32_t *)put = value; 203bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt else if (entry->type == XTTYPE_UINT64RC) 204bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt *(uint64_t *)put = value; 205564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt put += esize; 206564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt } 20704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (*end == '\0') 20804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt break; 20904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt } 21004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt} 21104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 2124a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardtstatic void xtopt_parse_string(struct xt_option_call *cb) 2134a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt{ 2144a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt const struct xt_option_entry *entry = cb->entry; 2154a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt size_t z = strlen(cb->arg); 2164a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt char *p; 2174a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt 2184a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (entry->min != 0 && z < entry->min) 2194a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 2204a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "Argument must have a minimum length of " 2214a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "%u characters\n", entry->min); 2224a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (entry->max != 0 && z > entry->max) 2234a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 2244a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "Argument must have a maximum length of " 2254a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "%u characters\n", entry->max); 2264a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (!(entry->flags & XTOPT_PUT)) 2274a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt return; 2284a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (z >= entry->size) 2294a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt z = entry->size - 1; 2304a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt p = XTOPT_MKPTR(cb); 2314a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt strncpy(p, cb->arg, z); 2324a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt p[z] = '\0'; 2334a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt} 2344a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt 235d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt/** 236d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt * Validate the input for being conformant to "mark[/mask]". 237d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt */ 238d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardtstatic void xtopt_parse_markmask(struct xt_option_call *cb) 239d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt{ 240d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt unsigned int mark = 0, mask = ~0U; 241d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt char *end; 242d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt 243d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX)) 244d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 245d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: bad mark value for option \"--%s\", " 246d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "or out of range.\n", 247d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 248d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (*end == '/' && 249d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) 250d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 251d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: bad mask value for option \"--%s\", " 252d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "or out of range.\n", 253d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 254d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (*end != '\0') 255d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 256d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: trailing garbage after value " 257d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "for option \"--%s\".\n", 258d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 259d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->val.mark = mark; 260d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->val.mask = mask; 261d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt} 262d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt 26341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardtstatic int xtopt_sysloglvl_compare(const void *a, const void *b) 26441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt{ 26541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const char *name = a; 26641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const struct syslog_level *entry = b; 26741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 26841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt return strcmp(name, entry->name); 26941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt} 27041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 27141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardtstatic void xtopt_parse_sysloglevel(struct xt_option_call *cb) 27241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt{ 27341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt static const struct syslog_level log_names[] = { /* must be sorted */ 27441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"alert", LOG_ALERT}, 27541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"crit", LOG_CRIT}, 27641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"debug", LOG_DEBUG}, 27741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"emerg", LOG_EMERG}, 27841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"error", LOG_ERR}, /* deprecated */ 27941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"info", LOG_INFO}, 28041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"notice", LOG_NOTICE}, 28141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"panic", LOG_EMERG}, /* deprecated */ 28241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"warning", LOG_WARNING}, 28341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt }; 28441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const struct syslog_level *e; 28541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt unsigned int num = 0; 28641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 28741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (!xtables_strtoui(cb->arg, NULL, &num, 0, 7)) { 28841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt e = bsearch(cb->arg, log_names, ARRAY_SIZE(log_names), 28941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt sizeof(*log_names), xtopt_sysloglvl_compare); 29041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (e == NULL) 29141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 29241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt "log level \"%s\" unknown\n", cb->arg); 29341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt num = e->level; 29441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt } 29541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt cb->val.syslog_level = num; 29641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 29741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt *(uint8_t *)XTOPT_MKPTR(cb) = num; 29841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt} 29941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 3002b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardtstatic void *xtables_sa_host(const void *sa, unsigned int afproto) 3012b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 3022b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (afproto == AF_INET6) 3032b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return &((struct sockaddr_in6 *)sa)->sin6_addr; 3042b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt else if (afproto == AF_INET) 3052b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return &((struct sockaddr_in *)sa)->sin_addr; 3062b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return (void *)sa; 3072b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 3082b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 3092b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardtstatic socklen_t xtables_sa_hostlen(unsigned int afproto) 3102b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 3112b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (afproto == AF_INET6) 3122b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return sizeof(struct in6_addr); 3132b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt else if (afproto == AF_INET) 3142b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return sizeof(struct in_addr); 3152b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return 0; 3162b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 3172b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 3182b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt/** 3192b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt * Accepts: a hostname (DNS), or a single inetaddr. 3202b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt */ 3212b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardtstatic void xtopt_parse_onehost(struct xt_option_call *cb) 3222b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 3232b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt struct addrinfo hints = {.ai_family = afinfo->family}; 3242b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt unsigned int adcount = 0; 3252b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt struct addrinfo *res, *p; 3262b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt int ret; 3272b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 3282b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt ret = getaddrinfo(cb->arg, NULL, &hints, &res); 3292b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (ret < 0) 3302b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 3312b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt "getaddrinfo: %s\n", gai_strerror(ret)); 3322b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 3332b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt for (p = res; p != NULL; p = p->ai_next) { 3342b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (adcount == 0) { 3352b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt memset(&cb->val.inetaddr, 0, sizeof(cb->val.inetaddr)); 3362b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt memcpy(&cb->val.inetaddr, 3372b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_host(p->ai_addr, p->ai_family), 3382b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_hostlen(p->ai_family)); 3392b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt ++adcount; 3402b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt continue; 3412b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt } 3422b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (memcmp(&cb->val.inetaddr, 3432b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_host(p->ai_addr, p->ai_family), 3442b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_hostlen(p->ai_family)) != 0) 3452b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 3462b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt "%s resolves to more than one address\n", 3472b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt cb->arg); 3482b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt } 3492b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 3502b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt freeaddrinfo(res); 3512b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 3522b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt /* Validation in xtables_option_metavalidate */ 3532b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt memcpy(XTOPT_MKPTR(cb), &cb->val.inetaddr, 3542b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt sizeof(cb->val.inetaddr)); 3552b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 3562b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 357b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt/** 358b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * @name: port name, or number as a string (e.g. "http" or "80") 359b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * 360b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * Resolve a port name to a number. Returns the port number in integral 361b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * form on success, or <0 on error. (errno will not be set.) 362b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt */ 363b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardtstatic int xtables_getportbyname(const char *name) 364b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt{ 365b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt struct addrinfo *res = NULL, *p; 366b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt int ret; 367b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 368b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = getaddrinfo(NULL, name, NULL, &res); 369b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (ret < 0) 370b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt return -1; 371b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = -1; 372b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt for (p = res; p != NULL; p = p->ai_next) { 373b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (p->ai_family == AF_INET6) { 374b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = ((struct sockaddr_in6 *)p->ai_addr)->sin6_port; 375b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt break; 376b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } else if (p->ai_family == AF_INET) { 377b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = ((struct sockaddr_in *)p->ai_addr)->sin_port; 378b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt break; 379b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } 380b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } 381b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt freeaddrinfo(res); 382b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt return ntohs(ret); 383b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt} 384b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 385b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt/** 386b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * Validate and parse a port specification and put the result into @cb. 387b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt */ 388b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardtstatic void xtopt_parse_port(struct xt_option_call *cb) 389b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt{ 390b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt int ret; 391b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 392b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = xtables_getportbyname(cb->arg); 393b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (ret < 0) 394b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 395b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt "Port \"%s\" does not resolve to anything.\n", 396b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt cb->arg); 397b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt cb->val.port = ret; 398b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (cb->entry->type == XTTYPE_PORT_NE) 399b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt cb->val.port = htons(cb->val.port); 400b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 401b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port; 402b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt} 403b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 404aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void (*const xtopt_subparse[])(struct xt_option_call *) = { 405dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt [XTTYPE_UINT8] = xtopt_parse_int, 4060eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt [XTTYPE_UINT16] = xtopt_parse_int, 407a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt [XTTYPE_UINT32] = xtopt_parse_int, 4088b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt [XTTYPE_UINT64] = xtopt_parse_int, 4098bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt [XTTYPE_UINT8RC] = xtopt_parse_mint, 410564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt [XTTYPE_UINT16RC] = xtopt_parse_mint, 41104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt [XTTYPE_UINT32RC] = xtopt_parse_mint, 412bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt [XTTYPE_UINT64RC] = xtopt_parse_mint, 4134a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt [XTTYPE_STRING] = xtopt_parse_string, 414d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt [XTTYPE_MARKMASK32] = xtopt_parse_markmask, 41541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, 4162b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt [XTTYPE_ONEHOST] = xtopt_parse_onehost, 417b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt [XTTYPE_PORT] = xtopt_parse_port, 418b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt [XTTYPE_PORT_NE] = xtopt_parse_port, 419aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}; 420aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 421aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const size_t xtopt_psize[] = { 422dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt [XTTYPE_UINT8] = sizeof(uint8_t), 4230eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt [XTTYPE_UINT16] = sizeof(uint16_t), 424a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt [XTTYPE_UINT32] = sizeof(uint32_t), 4258b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt [XTTYPE_UINT64] = sizeof(uint64_t), 4268bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt [XTTYPE_UINT8RC] = sizeof(uint8_t[2]), 427564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), 42804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), 429bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), 4304a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt [XTTYPE_STRING] = -1, 43141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), 4322b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt [XTTYPE_ONEHOST] = sizeof(union nf_inet_addr), 433b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt [XTTYPE_PORT] = sizeof(uint16_t), 434b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt [XTTYPE_PORT_NE] = sizeof(uint16_t), 435aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}; 436aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 437aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 438aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * The master option parsing routine. May be used for the ".x6_parse" 439aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * function pointer in extensions if fully automatic parsing is desired. 440aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * It may be also called manually from a custom x6_parse function. 441aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 442aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_parse(struct xt_option_call *cb) 443aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 444aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 445aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int eflag = 1 << cb->entry->id; 446aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 447aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 448aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use 449aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * prevention. Though it turned out that this is too much typing (most 450aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * of the options are one-time use only), so now we also have 451aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * %XTOPT_MULTI. 452aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 453aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) && 454aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->xflags & eflag) 455aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 456aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" can only be used once.\n", 457aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, cb->entry->name); 458aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb->invert && !(entry->flags & XTOPT_INVERT)) 459aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 460aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" cannot be inverted.\n", 461aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, entry->name); 462aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type != XTTYPE_NONE && optarg == NULL) 463aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 464aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" requires an argument.\n", 465aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, entry->name); 466aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type <= ARRAY_SIZE(xtopt_subparse) && 467aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_subparse[entry->type] != NULL) 468aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_subparse[entry->type](cb); 469aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Exclusion with other flags tested later in finalize. */ 470aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->xflags |= 1 << entry->id; 471aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 472aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 473aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 474aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Verifies that an extension's option map descriptor is valid, and ought to 475aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * be called right after the extension has been loaded, and before option 476aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * merging/xfrm. 477aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 478aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_metavalidate(const char *name, 479aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry) 480aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 481aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (; entry->name != NULL; ++entry) { 482aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id >= CHAR_BIT * sizeof(unsigned int) || 483aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt entry->id >= XT_OPTION_OFFSET_SCALE) 484aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 485aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension %s uses invalid ID %u\n", 486aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->id); 487aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (!(entry->flags & XTOPT_PUT)) 488aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 489aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type >= ARRAY_SIZE(xtopt_psize)) 490aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 491aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: entry type of option \"--%s\" cannot be " 492aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "combined with XTOPT_PUT\n", 493aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name); 49404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (xtopt_psize[entry->type] != -1 && 49504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xtopt_psize[entry->type] != entry->size) 496aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 497aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" points to a memory block " 498aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "of wrong size (expected %zu, got %zu)\n", 499aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, 500aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_psize[entry->type], entry->size); 501aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 502aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 503aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 504aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 505aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Find an option entry by its id. 506aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 507aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const struct xt_option_entry * 508aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_lookup(const struct xt_option_entry *entry, unsigned int id) 509aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 510aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (; entry->name != NULL; ++entry) 511aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id == id) 512aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return entry; 513aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return NULL; 514aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 515aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 516aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 517aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c: getopt id (i.e. with offset) 518aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw: struct ipt_entry or ip6t_entry 519aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 520aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the 521aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API. 522aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 523aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_tpcall(unsigned int c, char **argv, bool invert, 524aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xtables_target *t, void *fw) 525aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 526aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xt_option_call cb; 527aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 528aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (t->x6_parse == NULL) { 529aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (t->parse != NULL) 530aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->parse(c - t->option_offset, argv, invert, 531aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt &t->tflags, fw, &t->t); 532aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 533aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 534aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 535aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt c -= t->option_offset; 536aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.entry = xtables_option_lookup(t->x6_options, c); 537aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb.entry == NULL) 538aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_error(OTHER_PROBLEM, 539aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension does not know id %u\n", c); 540aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.arg = optarg; 541aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.invert = invert; 542aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.ext_name = t->name; 543aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.data = t->t->data; 544aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.xflags = t->tflags; 54533d180871bea281a448efd0c1a49517318162382Jan Engelhardt cb.target = &t->t; 546aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->x6_parse(&cb); 547aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->tflags = cb.xflags; 548aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 549aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 550aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 551aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c: getopt id (i.e. with offset) 552aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw: struct ipt_entry or ip6t_entry 553aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 554aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the 555aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API. 556aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 557aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_mpcall(unsigned int c, char **argv, bool invert, 558aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xtables_match *m, void *fw) 559aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 560aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xt_option_call cb; 561aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 562aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (m->x6_parse == NULL) { 563aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (m->parse != NULL) 564aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->parse(c - m->option_offset, argv, invert, 565aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt &m->mflags, fw, &m->m); 566aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 567aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 568aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 569aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt c -= m->option_offset; 570aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.entry = xtables_option_lookup(m->x6_options, c); 571aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb.entry == NULL) 572aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_error(OTHER_PROBLEM, 573aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension does not know id %u\n", c); 574aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.arg = optarg; 575aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.invert = invert; 576aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.ext_name = m->name; 577aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.data = m->m->data; 578aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.xflags = m->mflags; 57933d180871bea281a448efd0c1a49517318162382Jan Engelhardt cb.match = &m->m; 580aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->x6_parse(&cb); 581aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->mflags = cb.xflags; 582aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 583aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 584aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 585aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name: name of extension 586aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry: current option (from all ext's entries) being validated 587aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags: flags the extension has collected 588aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @i: conflicting option (id) to test for 589aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 590aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void 591aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_fcheck2(const char *name, const struct xt_option_entry *entry, 592aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *other, 593aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int xflags) 594aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 595aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int ef = 1 << entry->id, of = 1 << other->id; 596aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 597aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->also & of && !(xflags & of)) 598aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 599aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" also requires \"--%s\".\n", 600aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, other->name); 601aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 602aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (!(entry->excl & of)) 603aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Use of entry does not collide with other option, good. */ 604aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 605aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if ((xflags & (ef | of)) != (ef | of)) 606aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Conflicting options were not used. */ 607aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 608aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 609aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 610aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" cannot be used together with \"--%s\".\n", 611aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, other->name); 612aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 613aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 614aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 615aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name: name of extension 616aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags: accumulated flags 617aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry: extension's option table 618aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 619aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Check that all option constraints have been met. This effectively replaces 620aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * ->final_check of the older API. 621aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 622aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_options_fcheck(const char *name, unsigned int xflags, 623aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *table) 624aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 625aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry, *other; 626aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int i; 627aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 628aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (entry = table; entry->name != NULL; ++entry) { 629aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->flags & XTOPT_MAND && 630aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt !(xflags & (1 << entry->id))) 631aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 632aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" must be specified\n", 633aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name); 634aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 635aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) { 636aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id == i) 637aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 638aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Avoid conflict with self. Multi-use check 639aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * was done earlier in xtables_option_parse. 640aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 641aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 642aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt other = xtables_option_lookup(table, i); 643aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (other == NULL) 644aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 645aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_option_fcheck2(name, entry, other, xflags); 646aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 647aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 648aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 6493af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 6503af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/** 6513af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the 6523af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API. 6533af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */ 6543af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_tfcall(struct xtables_target *t) 6553af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{ 6563af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (t->x6_fcheck != NULL) { 6573af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt struct xt_fcheck_call cb; 6583af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 6593af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.ext_name = t->name; 6603af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.data = t->t->data; 6613af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.xflags = t->tflags; 6623af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt t->x6_fcheck(&cb); 6633af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } else if (t->final_check != NULL) { 6643af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt t->final_check(t->tflags); 6653af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } 6663af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (t->x6_options != NULL) 6673af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt xtables_options_fcheck(t->name, t->tflags, t->x6_options); 6683af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt} 6693af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 6703af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/** 6713af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the 6723af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API. 6733af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */ 6743af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_mfcall(struct xtables_match *m) 6753af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{ 6763af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (m->x6_fcheck != NULL) { 6773af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt struct xt_fcheck_call cb; 6783af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 6793af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.ext_name = m->name; 6803af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.data = m->m->data; 6813af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.xflags = m->mflags; 6823af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt m->x6_fcheck(&cb); 6833af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } else if (m->final_check != NULL) { 6843af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt m->final_check(m->mflags); 6853af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } 6863af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (m->x6_options != NULL) 6873af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt xtables_options_fcheck(m->name, m->mflags, m->x6_options); 6883af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt} 6892e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 6902e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtstruct xtables_lmap *xtables_lmap_init(const char *file) 6912e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 6922e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this; 6932e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt char buf[512]; 6942e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt FILE *fp; 6952e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt char *cur, *nxt; 6962e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt int id; 6972e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 6982e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt fp = fopen(file, "re"); 6992e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (fp == NULL) 7002e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 7012e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 7022e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (fgets(buf, sizeof(buf), fp) != NULL) { 7032e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt cur = buf; 7042e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (isspace(*cur)) 7052e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++cur; 7062e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (*cur == '#' || *cur == '\n' || *cur == '\0') 7072e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 7082e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 7092e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* iproute2 allows hex and dec format */ 7102e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt errno = 0; 7112e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10); 7122e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (nxt == cur || errno != 0) 7132e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 7142e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 7152e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* same boundaries as in iproute2 */ 7162e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (id < 0 || id > 255) 7172e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 7182e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt cur = nxt; 7192e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 7202e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (!isspace(*cur)) 7212e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 7222e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (isspace(*cur)) 7232e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++cur; 7242e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (*cur == '#' || *cur == '\n' || *cur == '\0') 7252e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 7262e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt nxt = cur; 7272e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (*nxt != '\0' && !isspace(*nxt)) 7282e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++nxt; 7292e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (nxt == cur) 7302e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 7312e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt *nxt = '\0'; 7322e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 7332e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* found valid data */ 7342e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this = malloc(sizeof(*lmap_this)); 7352e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_this == NULL) { 7362e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt perror("malloc"); 7372e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt goto out; 7382e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 7392e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->id = id; 7402e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->name = strdup(cur); 7412e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_this->name == NULL) { 7422e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(lmap_this); 7432e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt goto out; 7442e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 7452e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->next = NULL; 7462e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 7472e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_prev != NULL) 7482e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_prev->next = lmap_this; 7492e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt else 7502e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_head = lmap_this; 7512e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_prev = lmap_this; 7522e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 7532e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 7542e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt fclose(fp); 7552e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return lmap_head; 7562e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt out: 7572e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt xtables_lmap_free(lmap_head); 7582e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 7592e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 7602e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 7612e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtvoid xtables_lmap_free(struct xtables_lmap *head) 7622e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 7632e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt struct xtables_lmap *next; 7642e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 7652e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = next) { 7662e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt next = head->next; 7672e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(head->name); 7682e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(head); 7692e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 7702e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 7712e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 7722e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtint xtables_lmap_name2id(const struct xtables_lmap *head, const char *name) 7732e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 7742e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = head->next) 7752e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (strcmp(head->name, name) == 0) 7762e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return head->id; 7772e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return -1; 7782e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 7792e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 7802e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtconst char *xtables_lmap_id2name(const struct xtables_lmap *head, int id) 7812e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 7822e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = head->next) 7832e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (head->id == id) 7842e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return head->name; 7852e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 7862e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 787