xtoptions.c revision dfe99f1bf291b4b954d3608dbe95a43e16a8bb49
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Argument parser 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © Jan Engelhardt, 2011 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This program is free software; you can redistribute it and/or 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modify it under the terms of the GNU General Public License as 7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * published by the Free Software Foundation; either version 2 of 8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * the License, or (at your option) any later version. 9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) */ 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <errno.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <getopt.h> 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <limits.h> 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <netdb.h> 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <stdbool.h> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h> 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <stdio.h> 17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <stdlib.h> 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <string.h> 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <arpa/inet.h> 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xtables.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xshared.h" 22558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define XTOPT_MKPTR(cb) \ 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((void *)((char *)(cb)->data + (cb)->entry->ptroff)) 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/** 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Creates getopt options from the x6-style option map, and assigns each a 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * getopt id. 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct option * 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)xtables_options_xfrm(struct option *orig_opts, struct option *oldopts, 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const struct xt_option_entry *entry, unsigned int *offset) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int num_orig, num_old = 0, num_new, i; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct option *merge, *mp; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry == NULL) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return oldopts; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (num_orig = 0; orig_opts[num_orig].name != NULL; ++num_orig) 4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ; 4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (oldopts != NULL) 42bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch for (num_old = 0; oldopts[num_old].name != NULL; ++num_old) 43bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch ; 44bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch for (num_new = 0; entry[num_new].name != NULL; ++num_new) 45bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch ; 4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Since @oldopts also has @orig_opts already (and does so at the 49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * start), skip these entries. 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) */ 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oldopts += num_orig; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_old -= num_orig; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1)); 55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (merge == NULL) 56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return NULL; 57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) /* Let the base options -[ADI...] have precedence over everything */ 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(merge, orig_opts, sizeof(*mp) * num_orig); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mp = merge + num_orig; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Second, the new options */ 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xt_params->option_offset += XT_OPTION_OFFSET_SCALE; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *offset = xt_params->option_offset; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (i = 0; i < num_new; ++i, ++mp, ++entry) { 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mp->name = entry->name; 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mp->has_arg = entry->type != XTTYPE_NONE; 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mp->flag = NULL; 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mp->val = entry->id + *offset; 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* Third, the old options */ 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch memcpy(mp, oldopts, sizeof(*mp) * num_old); 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mp += num_old; 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch xtables_free_opts(0); 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* Clear trailing entry */ 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch memset(mp, 0, sizeof(*mp)); 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return merge; 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/** 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Require a simple integer. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void xtopt_parse_int(struct xt_option_call *cb) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct xt_option_entry *entry = cb->entry; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int lmin = 0, lmax = UINT32_MAX; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int value; 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->type == XTTYPE_UINT8) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmax = UINT8_MAX; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cb->entry->min != 0) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lmin = cb->entry->min; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cb->entry->max != 0) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lmax = cb->entry->max; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!xtables_strtoui(cb->arg, NULL, &value, lmin, lmax)) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xt_params->exit_err(PARAMETER_PROBLEM, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s: bad value for option \"--%s\", " 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "or out of range (%u-%u).\n", 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb->ext_name, entry->name, lmin, lmax); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->type == XTTYPE_UINT8) { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb->val.u8 = value; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (entry->flags & XTOPT_PUT) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (entry->type == XTTYPE_UINT32) { 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb->val.u32 = value; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (entry->flags & XTOPT_PUT) 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32; 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void (*const xtopt_subparse[])(struct xt_option_call *) = { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) [XTTYPE_UINT8] = xtopt_parse_int, 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) [XTTYPE_UINT32] = xtopt_parse_int, 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const size_t xtopt_psize[] = { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) [XTTYPE_UINT8] = sizeof(uint8_t), 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [XTTYPE_UINT32] = sizeof(uint32_t), 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * The master option parsing routine. May be used for the ".x6_parse" 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * function pointer in extensions if fully automatic parsing is desired. 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * It may be also called manually from a custom x6_parse function. 130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) */ 131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void xtables_option_parse(struct xt_option_call *cb) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const struct xt_option_entry *entry = cb->entry; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned int eflag = 1 << cb->entry->id; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * prevention. Though it turned out that this is too much typing (most 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * of the options are one-time use only), so now we also have 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * %XTOPT_MULTI. 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) && 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb->xflags & eflag) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xt_params->exit_err(PARAMETER_PROBLEM, 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "%s: option \"--%s\" can only be used once.\n", 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb->ext_name, cb->entry->name); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cb->invert && !(entry->flags & XTOPT_INVERT)) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xt_params->exit_err(PARAMETER_PROBLEM, 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "%s: option \"--%s\" cannot be inverted.\n", 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb->ext_name, entry->name); 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (entry->type != XTTYPE_NONE && optarg == NULL) 152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) xt_params->exit_err(PARAMETER_PROBLEM, 153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) "%s: option \"--%s\" requires an argument.\n", 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb->ext_name, entry->name); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (entry->type <= ARRAY_SIZE(xtopt_subparse) && 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xtopt_subparse[entry->type] != NULL) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xtopt_subparse[entry->type](cb); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* Exclusion with other flags tested later in finalize. */ 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb->xflags |= 1 << entry->id; 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * Verifies that an extension's option map descriptor is valid, and ought to 164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * be called right after the extension has been loaded, and before option 165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * merging/xfrm. 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void xtables_option_metavalidate(const char *name, 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const struct xt_option_entry *entry) 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (; entry->name != NULL; ++entry) { 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (entry->id >= CHAR_BIT * sizeof(unsigned int) || 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) entry->id >= XT_OPTION_OFFSET_SCALE) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xt_params->exit_err(OTHER_PROBLEM, 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Extension %s uses invalid ID %u\n", 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) name, entry->id); 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!(entry->flags & XTOPT_PUT)) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->type >= ARRAY_SIZE(xtopt_psize)) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xt_params->exit_err(OTHER_PROBLEM, 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "%s: entry type of option \"--%s\" cannot be " 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "combined with XTOPT_PUT\n", 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) name, entry->name); 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (xtopt_psize[entry->type] != entry->size) 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xt_params->exit_err(OTHER_PROBLEM, 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s: option \"--%s\" points to a memory block " 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "of wrong size (expected %zu, got %zu)\n", 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) name, entry->name, 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xtopt_psize[entry->type], entry->size); 1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * Find an option entry by its id. 194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) */ 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const struct xt_option_entry * 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)xtables_option_lookup(const struct xt_option_entry *entry, unsigned int id) 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (; entry->name != NULL; ++entry) 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (entry->id == id) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return entry; 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @c: getopt id (i.e. with offset) 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @fw: struct ipt_entry or ip6t_entry 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Dispatch arguments to the appropriate parse function, based upon the 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * extension's choice of API. 210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void xtables_option_tpcall(unsigned int c, char **argv, bool invert, 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct xtables_target *t, void *fw) 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct xt_option_call cb; 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (t->x6_parse == NULL) { 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (t->parse != NULL) 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) t->parse(c - t->option_offset, argv, invert, 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &t->tflags, fw, &t->t); 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) c -= t->option_offset; 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb.entry = xtables_option_lookup(t->x6_options, c); 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cb.entry == NULL) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xtables_error(OTHER_PROBLEM, 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Extension does not know id %u\n", c); 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb.arg = optarg; 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb.invert = invert; 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb.ext_name = t->name; 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cb.data = t->t->data; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.xflags = t->tflags; 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) t->x6_parse(&cb); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t->tflags = cb.xflags; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @c: getopt id (i.e. with offset) 239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * @fw: struct ipt_entry or ip6t_entry 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Dispatch arguments to the appropriate parse function, based upon the 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * extension's choice of API. 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void xtables_option_mpcall(unsigned int c, char **argv, bool invert, 245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) struct xtables_match *m, void *fw) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct xt_option_call cb; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (m->x6_parse == NULL) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (m->parse != NULL) 251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) m->parse(c - m->option_offset, argv, invert, 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &m->mflags, fw, &m->m); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) c -= m->option_offset; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.entry = xtables_option_lookup(m->x6_options, c); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cb.entry == NULL) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xtables_error(OTHER_PROBLEM, 260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) "Extension does not know id %u\n", c); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.arg = optarg; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.invert = invert; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.ext_name = m->name; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.data = m->m->data; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb.xflags = m->mflags; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m->x6_parse(&cb); 267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) m->mflags = cb.xflags; 268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @name: name of extension 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @entry: current option (from all ext's entries) being validated 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @xflags: flags the extension has collected 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @i: conflicting option (id) to test for 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xtables_option_fcheck2(const char *name, const struct xt_option_entry *entry, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct xt_option_entry *other, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int xflags) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int ef = 1 << entry->id, of = 1 << other->id; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (entry->also & of && !(xflags & of)) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xt_params->exit_err(PARAMETER_PROBLEM, 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s: option \"--%s\" also requires \"--%s\".\n", 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) name, entry->name, other->name); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(entry->excl & of)) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Use of entry does not collide with other option, good. */ 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((xflags & (ef | of)) != (ef | of)) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Conflicting options were not used. */ 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xt_params->exit_err(PARAMETER_PROBLEM, 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s: option \"--%s\" cannot be used together with \"--%s\".\n", 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name, entry->name, other->name); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)/** 301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @name: name of extension 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @xflags: accumulated flags 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @entry: extension's option table 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Check that all option constraints have been met. This effectively replaces 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ->final_check of the older API. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void xtables_options_fcheck(const char *name, unsigned int xflags, 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct xt_option_entry *table) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct xt_option_entry *entry, *other; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int i; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (entry = table; entry->name != NULL; ++entry) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->flags & XTOPT_MAND && 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(xflags & (1 << entry->id))) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xt_params->exit_err(PARAMETER_PROBLEM, 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s: option \"--%s\" must be specified\n", 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) name, entry->name); 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->id == i) 323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) /* 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Avoid conflict with self. Multi-use check 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * was done earlier in xtables_option_parse. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) other = xtables_option_lookup(table, i); 329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (other == NULL) 330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) continue; 331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) xtables_option_fcheck2(name, entry, other, xflags); 332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/** 337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * Dispatch arguments to the appropriate final_check function, based upon the 338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * extension's choice of API. 339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) */ 340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void xtables_option_tfcall(struct xtables_target *t) 341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){ 342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (t->x6_fcheck != NULL) { 343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) struct xt_fcheck_call cb; 344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cb.ext_name = t->name; 346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cb.data = t->t->data; 347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cb.xflags = t->tflags; 348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) t->x6_fcheck(&cb); 349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (t->final_check != NULL) { 350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) t->final_check(t->tflags); 351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (t->x6_options != NULL) 353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) xtables_options_fcheck(t->name, t->tflags, t->x6_options); 354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/** 357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * Dispatch arguments to the appropriate final_check function, based upon the 358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * extension's choice of API. 359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) */ 360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void xtables_option_mfcall(struct xtables_match *m) 361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){ 362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (m->x6_fcheck != NULL) { 363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) struct xt_fcheck_call cb; 364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cb.ext_name = m->name; 366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cb.data = m->m->data; 367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cb.xflags = m->mflags; 368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) m->x6_fcheck(&cb); 369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (m->final_check != NULL) { 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) m->final_check(m->mflags); 371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (m->x6_options != NULL) 373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) xtables_options_fcheck(m->name, m->mflags, m->x6_options); 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)