xtoptions.c revision 57e2e37ebe5319cf84381bdb319ea94143b1bf97
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> 2261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt#include <netinet/ip.h> 23aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "xtables.h" 24aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "xshared.h" 2561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt#ifndef IPTOS_NORMALSVC 2661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt# define IPTOS_NORMALSVC 0 2761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt#endif 28aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 29aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#define XTOPT_MKPTR(cb) \ 30aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ((void *)((char *)(cb)->data + (cb)->entry->ptroff)) 31aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 32aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 3341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt * Simple key-value pairs for syslog levels 3441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt */ 3541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardtstruct syslog_level { 3641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt char name[8]; 3741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt uint8_t level; 3841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt}; 3941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 4061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardtstruct tos_value_mask { 4161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt uint8_t value, mask; 4261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt}; 4361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 4441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt/** 45aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Creates getopt options from the x6-style option map, and assigns each a 46aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * getopt id. 47aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 48aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstruct option * 49aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_options_xfrm(struct option *orig_opts, struct option *oldopts, 50aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry, unsigned int *offset) 51aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 52aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int num_orig, num_old = 0, num_new, i; 53aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct option *merge, *mp; 54aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 55aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry == NULL) 56aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return oldopts; 57aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_orig = 0; orig_opts[num_orig].name != NULL; ++num_orig) 58aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 59aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (oldopts != NULL) 60aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_old = 0; oldopts[num_old].name != NULL; ++num_old) 61aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 62aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_new = 0; entry[num_new].name != NULL; ++num_new) 63aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 64aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 65aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 66aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Since @oldopts also has @orig_opts already (and does so at the 67aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * start), skip these entries. 68aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 69aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt oldopts += num_orig; 70aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt num_old -= num_orig; 71aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 72aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1)); 73aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (merge == NULL) 74aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return NULL; 75aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 76aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Let the base options -[ADI...] have precedence over everything */ 77aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memcpy(merge, orig_opts, sizeof(*mp) * num_orig); 78aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp = merge + num_orig; 79aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 80aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Second, the new options */ 81aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->option_offset += XT_OPTION_OFFSET_SCALE; 82aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *offset = xt_params->option_offset; 83aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 84aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (i = 0; i < num_new; ++i, ++mp, ++entry) { 85aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->name = entry->name; 86aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->has_arg = entry->type != XTTYPE_NONE; 87aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->flag = NULL; 88aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->val = entry->id + *offset; 89aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 90aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 91aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Third, the old options */ 92aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memcpy(mp, oldopts, sizeof(*mp) * num_old); 93aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp += num_old; 94aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_free_opts(0); 95aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 96aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Clear trailing entry */ 97aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memset(mp, 0, sizeof(*mp)); 98aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return merge; 99aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 100aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 10157e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardtstatic uintmax_t xtopt_max_by_type(enum xt_option_type type) 10257e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt{ 10357e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt switch (type) { 10457e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT8: 10557e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT8RC: 10657e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt return UINT8_MAX; 10757e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT16: 10857e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT16RC: 10957e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt return UINT16_MAX; 11057e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT32: 11157e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT32RC: 11257e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt return UINT32_MAX; 11357e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT64: 11457e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT64RC: 11557e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt return UINT64_MAX; 11657e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt default: 11757e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt return 0; 11857e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt } 11957e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt} 12057e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt 121a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt/** 122a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt * Require a simple integer. 123a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt */ 124a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardtstatic void xtopt_parse_int(struct xt_option_call *cb) 125a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt{ 126a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 12757e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt uintmax_t lmin = 0, lmax = xtopt_max_by_type(entry->type); 1280b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt uintmax_t value; 129a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 130d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt if (cb->entry->min != 0) 131d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt lmin = cb->entry->min; 132d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt if (cb->entry->max != 0) 133d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt lmax = cb->entry->max; 134d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt 1352305d5fb42fc059f38fc1bdf53411dbeecdb310bJP Abgrall if (!xtables_strtoul(cb->arg, NULL, &value, lmin, lmax)) 136a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 137a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt "%s: bad value for option \"--%s\", " 1380b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt "or out of range (%ju-%ju).\n", 139a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt cb->ext_name, entry->name, lmin, lmax); 140a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 141dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->type == XTTYPE_UINT8) { 142dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt cb->val.u8 = value; 143dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->flags & XTOPT_PUT) 144dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8; 1450eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt } else if (entry->type == XTTYPE_UINT16) { 1460eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt cb->val.u16 = value; 1470eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt if (entry->flags & XTOPT_PUT) 1480eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16; 149dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt } else if (entry->type == XTTYPE_UINT32) { 150a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt cb->val.u32 = value; 151a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt if (entry->flags & XTOPT_PUT) 152a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt *(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32; 1538b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt } else if (entry->type == XTTYPE_UINT64) { 1548b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt cb->val.u64 = value; 1558b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt if (entry->flags & XTOPT_PUT) 1568b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt *(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64; 157a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt } 158a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt} 159a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 16004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt/** 161f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt * Require a simple floating point number. 162f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt */ 163f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardtstatic void xtopt_parse_float(struct xt_option_call *cb) 164f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt{ 165f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 166f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt double value; 167f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt char *end; 168f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt 169f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt value = strtod(cb->arg, &end); 170f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt if (end == cb->arg || *end != '\0' || 171f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt (entry->min != entry->max && 172f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt (value < entry->min || value > entry->max))) 173f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 174f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt "%s: bad value for option \"--%s\", " 175f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt "or out of range (%u-%u).\n", 176f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt cb->ext_name, entry->name, entry->min, entry->max); 177f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt 178f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt cb->val.dbl = value; 179f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt if (entry->flags & XTOPT_PUT) 180f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt *(double *)XTOPT_MKPTR(cb) = cb->val.dbl; 181f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt} 182f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt 183f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt/** 18404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * Multiple integer parse routine. 18504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * 18604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * This function is capable of parsing any number of fields. Only the first 18704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * two values from the string will be put into @cb however (and as such, 18804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * @cb->val.uXX_range is just that large) to cater for the few extensions that 18904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * do not have a range[2] field, but {min, max}, and which cannot use 19004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * XTOPT_POINTER. 19104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt */ 19204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardtstatic void xtopt_parse_mint(struct xt_option_call *cb) 19304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt{ 19404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 19504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt const char *arg = cb->arg; 196564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt size_t esize = sizeof(uint32_t); 19757e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt uintmax_t lmax = xtopt_max_by_type(entry->type); 198564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt char *put = XTOPT_MKPTR(cb); 19957e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt unsigned int maxiter; 20057e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt uintmax_t value; 20104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt char *end = ""; 20204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt char sep = ':'; 20304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 2048bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt if (entry->type == XTTYPE_UINT8RC) 2058bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt esize = sizeof(uint8_t); 2068bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt else if (entry->type == XTTYPE_UINT16RC) 207564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt esize = sizeof(uint16_t); 208bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt else if (entry->type == XTTYPE_UINT64RC) 209bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt esize = sizeof(uint64_t); 210564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt maxiter = entry->size / esize; 21104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (maxiter == 0) 21204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */ 213564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt if (entry->size % esize != 0) 21404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " 21504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "not have proper size\n", __func__); 21604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 21704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->nvals = 0; 21804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt for (arg = cb->arg; ; arg = end + 1) { 21904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (cb->nvals == maxiter) 22004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " 22104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "components for option \"--%s\" (max: %u)\n", 22204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->ext_name, entry->name, maxiter); 22357e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt if (!xtables_strtoul(arg, &end, &value, 0, lmax)) 22404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 2255e35b7d435c5bc1b3641f76a6601a55d32d63ac8Jan Engelhardt "%s: bad value for option \"--%s\" near " 22657e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt "\"%s\", or out of range (0-%ju).\n", 22757e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt cb->ext_name, entry->name, arg, lmax); 22804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (*end != '\0' && *end != sep) 22904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 23004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "%s: Argument to \"--%s\" has unexpected " 2315e35b7d435c5bc1b3641f76a6601a55d32d63ac8Jan Engelhardt "characters near \"%s\".\n", 2325e35b7d435c5bc1b3641f76a6601a55d32d63ac8Jan Engelhardt cb->ext_name, entry->name, end); 233564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) { 2348bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt if (entry->type == XTTYPE_UINT8RC) 2358bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt cb->val.u8_range[cb->nvals] = value; 2368bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt else if (entry->type == XTTYPE_UINT16RC) 237564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt cb->val.u16_range[cb->nvals] = value; 238564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt else if (entry->type == XTTYPE_UINT32RC) 239564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt cb->val.u32_range[cb->nvals] = value; 240bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt else if (entry->type == XTTYPE_UINT64RC) 241bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt cb->val.u64_range[cb->nvals] = value; 242564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt } 2430787a82873fe9db5dea478942b183e6ff2a8500dJan Engelhardt ++cb->nvals; 244564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt if (entry->flags & XTOPT_PUT) { 2458bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt if (entry->type == XTTYPE_UINT8RC) 2468bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt *(uint8_t *)put = value; 2478bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt else if (entry->type == XTTYPE_UINT16RC) 248564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt *(uint16_t *)put = value; 249564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt else if (entry->type == XTTYPE_UINT32RC) 250564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt *(uint32_t *)put = value; 251bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt else if (entry->type == XTTYPE_UINT64RC) 252bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt *(uint64_t *)put = value; 253564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt put += esize; 254564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt } 25504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (*end == '\0') 25604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt break; 25704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt } 25804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt} 25904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 2604a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardtstatic void xtopt_parse_string(struct xt_option_call *cb) 2614a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt{ 2624a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt const struct xt_option_entry *entry = cb->entry; 2634a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt size_t z = strlen(cb->arg); 2644a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt char *p; 2654a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt 2664a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (entry->min != 0 && z < entry->min) 2674a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 2684a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "Argument must have a minimum length of " 2694a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "%u characters\n", entry->min); 2704a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (entry->max != 0 && z > entry->max) 2714a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 2724a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "Argument must have a maximum length of " 2734a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "%u characters\n", entry->max); 2744a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (!(entry->flags & XTOPT_PUT)) 2754a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt return; 2764a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (z >= entry->size) 2774a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt z = entry->size - 1; 2784a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt p = XTOPT_MKPTR(cb); 2794a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt strncpy(p, cb->arg, z); 2804a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt p[z] = '\0'; 2814a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt} 2824a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt 28361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardtstatic const struct tos_symbol_info { 28461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt unsigned char value; 28561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt const char *name; 28661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt} tos_symbol_names[] = { 28761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_LOWDELAY, "Minimize-Delay"}, 28861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_THROUGHPUT, "Maximize-Throughput"}, 28961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_RELIABILITY, "Maximize-Reliability"}, 29061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_MINCOST, "Minimize-Cost"}, 29161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_NORMALSVC, "Normal-Service"}, 29261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {}, 29361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt}; 29461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 29561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt/* 29661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * tos_parse_numeric - parse a string like "15/255" 29761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * 29861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @str: input string 29961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @tvm: (value/mask) tuple 30061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @max: maximum allowed value (must be pow(2,some_int)-1) 30161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt */ 30261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardtstatic bool tos_parse_numeric(const char *str, struct xt_option_call *cb, 30361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt unsigned int max) 30461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt{ 30561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt unsigned int value; 30661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt char *end; 30761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 30861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_strtoui(str, &end, &value, 0, max); 30961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_value = value; 31061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_mask = max; 31161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 31261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (*end == '/') { 31361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt const char *p = end + 1; 31461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 31561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (!xtables_strtoui(p, &end, &value, 0, max)) 31661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", 31761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt str); 31861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_mask = value; 31961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt } 32061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 32161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (*end != '\0') 32261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str); 32361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt return true; 32461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt} 32561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 32661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt/** 32761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @str: input string 32861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @tvm: (value/mask) tuple 32961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @def_mask: mask to force when a symbolic name is used 33061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt */ 33161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardtstatic void xtopt_parse_tosmask(struct xt_option_call *cb) 33261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt{ 33361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt const struct tos_symbol_info *symbol; 33461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt char *tmp; 33561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 33661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (xtables_strtoui(cb->arg, &tmp, NULL, 0, UINT8_MAX)) { 33761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt tos_parse_numeric(cb->arg, cb, UINT8_MAX); 33861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt return; 33961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt } 34061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt /* 34161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * This is our way we deal with different defaults 34261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * for different revisions. 34361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt */ 34461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_mask = cb->entry->max; 34561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol) 34661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (strcasecmp(cb->arg, symbol->name) == 0) { 34761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_value = symbol->value; 34861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt return; 34961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt } 35061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 35161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown", 35261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->arg); 35361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt} 35461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 355d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt/** 356d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt * Validate the input for being conformant to "mark[/mask]". 357d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt */ 358d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardtstatic void xtopt_parse_markmask(struct xt_option_call *cb) 359d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt{ 360d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt unsigned int mark = 0, mask = ~0U; 361d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt char *end; 362d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt 363d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX)) 364d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 365d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: bad mark value for option \"--%s\", " 366d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "or out of range.\n", 367d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 368d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (*end == '/' && 369d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) 370d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 371d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: bad mask value for option \"--%s\", " 372d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "or out of range.\n", 373d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 374d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (*end != '\0') 375d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 376d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: trailing garbage after value " 377d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "for option \"--%s\".\n", 378d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 379d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->val.mark = mark; 380d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->val.mask = mask; 381d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt} 382d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt 38341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardtstatic int xtopt_sysloglvl_compare(const void *a, const void *b) 38441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt{ 38541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const char *name = a; 38641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const struct syslog_level *entry = b; 38741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 38841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt return strcmp(name, entry->name); 38941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt} 39041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 39141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardtstatic void xtopt_parse_sysloglevel(struct xt_option_call *cb) 39241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt{ 39341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt static const struct syslog_level log_names[] = { /* must be sorted */ 39441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"alert", LOG_ALERT}, 39541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"crit", LOG_CRIT}, 39641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"debug", LOG_DEBUG}, 39741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"emerg", LOG_EMERG}, 39841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"error", LOG_ERR}, /* deprecated */ 39941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"info", LOG_INFO}, 40041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"notice", LOG_NOTICE}, 40141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"panic", LOG_EMERG}, /* deprecated */ 40241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"warning", LOG_WARNING}, 40341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt }; 40441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const struct syslog_level *e; 40541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt unsigned int num = 0; 40641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 40741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (!xtables_strtoui(cb->arg, NULL, &num, 0, 7)) { 40841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt e = bsearch(cb->arg, log_names, ARRAY_SIZE(log_names), 40941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt sizeof(*log_names), xtopt_sysloglvl_compare); 41041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (e == NULL) 41141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 41241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt "log level \"%s\" unknown\n", cb->arg); 41341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt num = e->level; 41441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt } 41541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt cb->val.syslog_level = num; 41641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 41741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt *(uint8_t *)XTOPT_MKPTR(cb) = num; 41841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt} 41941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 4202b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardtstatic void *xtables_sa_host(const void *sa, unsigned int afproto) 4212b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 4222b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (afproto == AF_INET6) 4232b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return &((struct sockaddr_in6 *)sa)->sin6_addr; 4242b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt else if (afproto == AF_INET) 4252b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return &((struct sockaddr_in *)sa)->sin_addr; 4262b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return (void *)sa; 4272b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 4282b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 4292b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardtstatic socklen_t xtables_sa_hostlen(unsigned int afproto) 4302b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 4312b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (afproto == AF_INET6) 4322b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return sizeof(struct in6_addr); 4332b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt else if (afproto == AF_INET) 4342b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return sizeof(struct in_addr); 4352b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return 0; 4362b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 4372b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 4382b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt/** 439d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * Accepts: a hostname (DNS), or a single inetaddr - without any mask. The 440d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * result is stored in @cb->val.haddr. Additionally, @cb->val.hmask and 441d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * @cb->val.hlen are set for completeness to the appropriate values. 4422b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt */ 443d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardtstatic void xtopt_parse_host(struct xt_option_call *cb) 4442b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 4452b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt struct addrinfo hints = {.ai_family = afinfo->family}; 4462b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt unsigned int adcount = 0; 4472b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt struct addrinfo *res, *p; 4482b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt int ret; 4492b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 4502b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt ret = getaddrinfo(cb->arg, NULL, &hints, &res); 4512b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (ret < 0) 4522b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 4532b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt "getaddrinfo: %s\n", gai_strerror(ret)); 4542b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 455d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt memset(&cb->val.hmask, 0xFF, sizeof(cb->val.hmask)); 456d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; 457d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt 4582b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt for (p = res; p != NULL; p = p->ai_next) { 4592b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (adcount == 0) { 460d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt memset(&cb->val.haddr, 0, sizeof(cb->val.haddr)); 461d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt memcpy(&cb->val.haddr, 4622b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_host(p->ai_addr, p->ai_family), 4632b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_hostlen(p->ai_family)); 4642b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt ++adcount; 4652b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt continue; 4662b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt } 467d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt if (memcmp(&cb->val.haddr, 4682b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_host(p->ai_addr, p->ai_family), 4692b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_hostlen(p->ai_family)) != 0) 4702b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 4712b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt "%s resolves to more than one address\n", 4722b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt cb->arg); 4732b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt } 4742b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 4752b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt freeaddrinfo(res); 4762b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 4772b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt /* Validation in xtables_option_metavalidate */ 478d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt memcpy(XTOPT_MKPTR(cb), &cb->val.haddr, 479d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt sizeof(cb->val.haddr)); 4802b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 4812b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 482b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt/** 483b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * @name: port name, or number as a string (e.g. "http" or "80") 484b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * 485b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * Resolve a port name to a number. Returns the port number in integral 486b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * form on success, or <0 on error. (errno will not be set.) 487b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt */ 488b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardtstatic int xtables_getportbyname(const char *name) 489b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt{ 490b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt struct addrinfo *res = NULL, *p; 491b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt int ret; 492b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 493b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = getaddrinfo(NULL, name, NULL, &res); 494b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (ret < 0) 495b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt return -1; 496b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = -1; 497b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt for (p = res; p != NULL; p = p->ai_next) { 498b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (p->ai_family == AF_INET6) { 499b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = ((struct sockaddr_in6 *)p->ai_addr)->sin6_port; 500b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt break; 501b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } else if (p->ai_family == AF_INET) { 502b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = ((struct sockaddr_in *)p->ai_addr)->sin_port; 503b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt break; 504b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } 505b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } 506b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt freeaddrinfo(res); 50744517bda3d8130638882f69478a8091316f30cbbJan Engelhardt if (ret < 0) 50844517bda3d8130638882f69478a8091316f30cbbJan Engelhardt return ret; 509b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt return ntohs(ret); 510b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt} 511b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 512b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt/** 513170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt * Validate and parse a protocol specification (number or name) by use of 514170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt * /etc/protocols and put the result into @cb->val.protocol. 515170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt */ 516170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardtstatic void xtopt_parse_protocol(struct xt_option_call *cb) 517170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt{ 51885f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt cb->val.protocol = xtables_parse_protocol(cb->arg); 519170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt if (cb->entry->flags & XTOPT_PUT) 520170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.protocol; 521170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt} 522170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt 523170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt/** 524d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * Validate and parse a port specification and put the result into 525d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * @cb->val.port. 526b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt */ 527b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardtstatic void xtopt_parse_port(struct xt_option_call *cb) 528b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt{ 529c02c92d1fcaa1223caf9a5eef32bedcb78f1e714Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 530b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt int ret; 531b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 532b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = xtables_getportbyname(cb->arg); 533b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (ret < 0) 534b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 535b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt "Port \"%s\" does not resolve to anything.\n", 536b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt cb->arg); 537c02c92d1fcaa1223caf9a5eef32bedcb78f1e714Jan Engelhardt if (entry->flags & XTOPT_NBO) 538c02c92d1fcaa1223caf9a5eef32bedcb78f1e714Jan Engelhardt ret = htons(ret); 539b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt cb->val.port = ret; 540c02c92d1fcaa1223caf9a5eef32bedcb78f1e714Jan Engelhardt if (entry->flags & XTOPT_PUT) 541b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port; 542b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt} 543b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 544f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardtstatic void xtopt_parse_mport(struct xt_option_call *cb) 545f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt{ 546f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt static const size_t esize = sizeof(uint16_t); 547f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 548f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt char *lo_arg, *wp_arg, *arg; 549f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt unsigned int maxiter; 550f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt int value; 551f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 552f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt wp_arg = lo_arg = strdup(cb->arg); 553f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (lo_arg == NULL) 554f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(RESOURCE_PROBLEM, "strdup"); 555f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 556f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt maxiter = entry->size / esize; 557f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (maxiter == 0) 558f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt maxiter = 2; /* ARRAY_SIZE(cb->val.port_range) */ 559f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (entry->size % esize != 0) 560f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " 561f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "not have proper size\n", __func__); 562f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 563f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[0] = 0; 564f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[1] = UINT16_MAX; 565f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->nvals = 0; 566f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 567f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt while ((arg = strsep(&wp_arg, ":")) != NULL) { 568f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (cb->nvals == maxiter) 569f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " 570f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "components for option \"--%s\" (max: %u)\n", 571f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->ext_name, entry->name, maxiter); 572f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (*arg == '\0') { 573f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt ++cb->nvals; 574f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt continue; 575f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt } 576f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 577f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt value = xtables_getportbyname(arg); 578f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (value < 0) 579f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 580f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "Port \"%s\" does not resolve to " 581f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "anything.\n", arg); 582c02c92d1fcaa1223caf9a5eef32bedcb78f1e714Jan Engelhardt if (entry->flags & XTOPT_NBO) 583f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt value = htons(value); 584f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (cb->nvals < ARRAY_SIZE(cb->val.port_range)) 585f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[cb->nvals] = value; 586f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt ++cb->nvals; 587f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt } 588f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 589f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (cb->nvals == 1) { 590f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[1] = cb->val.port_range[0]; 591f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt ++cb->nvals; 592f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt } 593f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (entry->flags & XTOPT_PUT) 594f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt memcpy(XTOPT_MKPTR(cb), cb->val.port_range, sizeof(uint16_t) * 595f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt (cb->nvals <= maxiter ? cb->nvals : maxiter)); 596f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt free(lo_arg); 597f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt} 598f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 599d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt/** 600d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * Parse an integer and ensure it is within the address family's prefix length 601fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt * limits. The result is stored in @cb->val.hlen. 602d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt */ 603fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardtstatic void xtopt_parse_plen(struct xt_option_call *cb) 604e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt{ 605e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 606fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt unsigned int prefix_len = 128; /* happiness is a warm gcc */ 607e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt 608d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; 609d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen)) 610e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 611e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt "%s: bad value for option \"--%s\", " 612e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt "or out of range (%u-%u).\n", 613d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt cb->ext_name, entry->name, 0, cb->val.hlen); 614e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt 615d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt cb->val.hlen = prefix_len; 616fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt} 617fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt 618fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt/** 619fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt * Reuse xtopt_parse_plen for testing the integer. Afterwards convert this to 620fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt * a bitmask, and make it available through @cb->val.hmask (hlen remains 621fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt * valid). If %XTOPT_PUT is used, hmask will be copied to the target area. 622fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt */ 623fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardtstatic void xtopt_parse_plenmask(struct xt_option_call *cb) 624fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt{ 625fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 626fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt uint32_t *mask = cb->val.hmask.all; 627fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt 628fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt xtopt_parse_plen(cb); 629fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt 630e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt memset(mask, 0xFF, sizeof(union nf_inet_addr)); 631d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt /* This shifting is AF-independent. */ 632fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt if (cb->val.hlen == 0) { 633e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[0] = mask[1] = mask[2] = mask[3] = 0; 634fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt } else if (cb->val.hlen <= 32) { 635fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt mask[0] <<= 32 - cb->val.hlen; 636e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[1] = mask[2] = mask[3] = 0; 637fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt } else if (cb->val.hlen <= 64) { 638fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt mask[1] <<= 32 - (cb->val.hlen - 32); 639e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[2] = mask[3] = 0; 640fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt } else if (cb->val.hlen <= 96) { 641fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt mask[2] <<= 32 - (cb->val.hlen - 64); 642e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[3] = 0; 643fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt } else if (cb->val.hlen <= 128) { 644fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt mask[3] <<= 32 - (cb->val.hlen - 96); 645e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt } 646e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[0] = htonl(mask[0]); 647e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[1] = htonl(mask[1]); 648e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[2] = htonl(mask[2]); 649e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[3] = htonl(mask[3]); 650e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt if (entry->flags & XTOPT_PUT) 651e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt memcpy(XTOPT_MKPTR(cb), mask, sizeof(union nf_inet_addr)); 652e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt} 653e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt 65466266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardtstatic void xtopt_parse_hostmask(struct xt_option_call *cb) 65566266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt{ 65666266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt const char *orig_arg = cb->arg; 65766266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt char *work, *p; 65866266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt 65966266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt if (strchr(cb->arg, '/') == NULL) { 66066266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt xtopt_parse_host(cb); 66166266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt return; 66266266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt } 66366266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt work = strdup(orig_arg); 66466266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt if (work == NULL) 66566266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "strdup"); 66666266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt p = strchr(work, '/'); /* by def this can't be NULL now */ 66766266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt *p++ = '\0'; 66866266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt /* 66966266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt * Because xtopt_parse_host and xtopt_parse_plenmask would store 67066266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt * different things in the same target area, XTTYPE_HOSTMASK must 67166266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt * disallow XTOPT_PUT, which it does by forcing its absence, 67266266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt * cf. not being listed in xtopt_psize. 67366266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt */ 67466266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt cb->arg = work; 67566266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt xtopt_parse_host(cb); 67666266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt cb->arg = p; 67766266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt xtopt_parse_plenmask(cb); 67866266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt cb->arg = orig_arg; 67966266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt} 68066266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt 681cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardtstatic void xtopt_parse_ethermac(struct xt_option_call *cb) 682cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt{ 683cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt const char *arg = cb->arg; 684cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt unsigned int i; 685cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt char *end; 686cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt 687cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt for (i = 0; i < ARRAY_SIZE(cb->val.ethermac) - 1; ++i) { 688cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt cb->val.ethermac[i] = strtoul(arg, &end, 16); 689cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt if (cb->val.ethermac[i] > UINT8_MAX || *end != ':') 690cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt goto out; 691cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt arg = end + 1; 692cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt } 693cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt i = ARRAY_SIZE(cb->val.ethermac) - 1; 694cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt cb->val.ethermac[i] = strtoul(arg, &end, 16); 695cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt if (cb->val.ethermac[i] > UINT8_MAX || *end != '\0') 696cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt goto out; 697cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 698cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt memcpy(XTOPT_MKPTR(cb), cb->val.ethermac, 699cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt sizeof(cb->val.ethermac)); 700cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt return; 701cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt out: 702cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "ether"); 703cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt} 704cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt 705aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void (*const xtopt_subparse[])(struct xt_option_call *) = { 706dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt [XTTYPE_UINT8] = xtopt_parse_int, 7070eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt [XTTYPE_UINT16] = xtopt_parse_int, 708a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt [XTTYPE_UINT32] = xtopt_parse_int, 7098b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt [XTTYPE_UINT64] = xtopt_parse_int, 7108bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt [XTTYPE_UINT8RC] = xtopt_parse_mint, 711564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt [XTTYPE_UINT16RC] = xtopt_parse_mint, 71204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt [XTTYPE_UINT32RC] = xtopt_parse_mint, 713bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt [XTTYPE_UINT64RC] = xtopt_parse_mint, 714f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt [XTTYPE_DOUBLE] = xtopt_parse_float, 7154a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt [XTTYPE_STRING] = xtopt_parse_string, 71661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt [XTTYPE_TOSMASK] = xtopt_parse_tosmask, 717d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt [XTTYPE_MARKMASK32] = xtopt_parse_markmask, 71841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, 719d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt [XTTYPE_HOST] = xtopt_parse_host, 72066266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt [XTTYPE_HOSTMASK] = xtopt_parse_hostmask, 721170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt [XTTYPE_PROTOCOL] = xtopt_parse_protocol, 722b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt [XTTYPE_PORT] = xtopt_parse_port, 723f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt [XTTYPE_PORTRC] = xtopt_parse_mport, 724fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt [XTTYPE_PLEN] = xtopt_parse_plen, 725e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt [XTTYPE_PLENMASK] = xtopt_parse_plenmask, 726cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt [XTTYPE_ETHERMAC] = xtopt_parse_ethermac, 727aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}; 728aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 729aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const size_t xtopt_psize[] = { 730d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt /* 731d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * All types not listed here, and thus essentially being initialized to 732d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * zero have zero on purpose. 733d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt */ 734dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt [XTTYPE_UINT8] = sizeof(uint8_t), 7350eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt [XTTYPE_UINT16] = sizeof(uint16_t), 736a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt [XTTYPE_UINT32] = sizeof(uint32_t), 7378b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt [XTTYPE_UINT64] = sizeof(uint64_t), 7388bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt [XTTYPE_UINT8RC] = sizeof(uint8_t[2]), 739564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), 74004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), 741bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), 742f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt [XTTYPE_DOUBLE] = sizeof(double), 7434a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt [XTTYPE_STRING] = -1, 74441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), 745d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt [XTTYPE_HOST] = sizeof(union nf_inet_addr), 74666266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt [XTTYPE_HOSTMASK] = sizeof(union nf_inet_addr), 747170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt [XTTYPE_PROTOCOL] = sizeof(uint8_t), 748b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt [XTTYPE_PORT] = sizeof(uint16_t), 749f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt [XTTYPE_PORTRC] = sizeof(uint16_t[2]), 750e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt [XTTYPE_PLENMASK] = sizeof(union nf_inet_addr), 751cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt [XTTYPE_ETHERMAC] = sizeof(uint8_t[6]), 752aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}; 753aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 754aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 755aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * The master option parsing routine. May be used for the ".x6_parse" 756aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * function pointer in extensions if fully automatic parsing is desired. 757aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * It may be also called manually from a custom x6_parse function. 758aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 759aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_parse(struct xt_option_call *cb) 760aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 761aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 762aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int eflag = 1 << cb->entry->id; 763aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 764aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 765aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use 766aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * prevention. Though it turned out that this is too much typing (most 767aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * of the options are one-time use only), so now we also have 768aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * %XTOPT_MULTI. 769aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 770aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) && 771aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->xflags & eflag) 772aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 773aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" can only be used once.\n", 774aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, cb->entry->name); 775aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb->invert && !(entry->flags & XTOPT_INVERT)) 776aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 777aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" cannot be inverted.\n", 778aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, entry->name); 779aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type != XTTYPE_NONE && optarg == NULL) 780aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 781aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" requires an argument.\n", 782aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, entry->name); 783aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type <= ARRAY_SIZE(xtopt_subparse) && 784aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_subparse[entry->type] != NULL) 785aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_subparse[entry->type](cb); 786aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Exclusion with other flags tested later in finalize. */ 787aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->xflags |= 1 << entry->id; 788aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 789aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 790aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 791aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Verifies that an extension's option map descriptor is valid, and ought to 792aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * be called right after the extension has been loaded, and before option 793aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * merging/xfrm. 794aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 795aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_metavalidate(const char *name, 796aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry) 797aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 798aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (; entry->name != NULL; ++entry) { 799aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id >= CHAR_BIT * sizeof(unsigned int) || 800aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt entry->id >= XT_OPTION_OFFSET_SCALE) 801aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 802aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension %s uses invalid ID %u\n", 803aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->id); 804aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (!(entry->flags & XTOPT_PUT)) 805aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 806269cbfd30aac18c1fd251be83430dabc60abee0cJan Engelhardt if (entry->type >= ARRAY_SIZE(xtopt_psize) || 807269cbfd30aac18c1fd251be83430dabc60abee0cJan Engelhardt xtopt_psize[entry->type] == 0) 808aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 809aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: entry type of option \"--%s\" cannot be " 810aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "combined with XTOPT_PUT\n", 811aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name); 81204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (xtopt_psize[entry->type] != -1 && 81304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xtopt_psize[entry->type] != entry->size) 814aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 815aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" points to a memory block " 816aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "of wrong size (expected %zu, got %zu)\n", 817aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, 818aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_psize[entry->type], entry->size); 819aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 820aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 821aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 822aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 823aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Find an option entry by its id. 824aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 825aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const struct xt_option_entry * 826aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_lookup(const struct xt_option_entry *entry, unsigned int id) 827aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 828aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (; entry->name != NULL; ++entry) 829aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id == id) 830aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return entry; 831aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return NULL; 832aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 833aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 834aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 835aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c: getopt id (i.e. with offset) 836aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw: struct ipt_entry or ip6t_entry 837aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 838aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the 839aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API. 840aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 841aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_tpcall(unsigned int c, char **argv, bool invert, 842aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xtables_target *t, void *fw) 843aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 844aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xt_option_call cb; 845aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 846aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (t->x6_parse == NULL) { 847aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (t->parse != NULL) 848aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->parse(c - t->option_offset, argv, invert, 849aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt &t->tflags, fw, &t->t); 850aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 851aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 852aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 853aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt c -= t->option_offset; 854aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.entry = xtables_option_lookup(t->x6_options, c); 855aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb.entry == NULL) 856aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_error(OTHER_PROBLEM, 857aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension does not know id %u\n", c); 858aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.arg = optarg; 859aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.invert = invert; 860aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.ext_name = t->name; 861aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.data = t->t->data; 862aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.xflags = t->tflags; 86333d180871bea281a448efd0c1a49517318162382Jan Engelhardt cb.target = &t->t; 86487a34d7aef2cba833f4f36536575dee304bbece5Jan Engelhardt cb.xt_entry = fw; 865aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->x6_parse(&cb); 866aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->tflags = cb.xflags; 867aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 868aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 869aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 870aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c: getopt id (i.e. with offset) 871aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw: struct ipt_entry or ip6t_entry 872aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 873aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the 874aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API. 875aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 876aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_mpcall(unsigned int c, char **argv, bool invert, 877aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xtables_match *m, void *fw) 878aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 879aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xt_option_call cb; 880aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 881aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (m->x6_parse == NULL) { 882aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (m->parse != NULL) 883aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->parse(c - m->option_offset, argv, invert, 884aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt &m->mflags, fw, &m->m); 885aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 886aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 887aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 888aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt c -= m->option_offset; 889aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.entry = xtables_option_lookup(m->x6_options, c); 890aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb.entry == NULL) 891aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_error(OTHER_PROBLEM, 892aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension does not know id %u\n", c); 893aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.arg = optarg; 894aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.invert = invert; 895aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.ext_name = m->name; 896aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.data = m->m->data; 897aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.xflags = m->mflags; 89833d180871bea281a448efd0c1a49517318162382Jan Engelhardt cb.match = &m->m; 89987a34d7aef2cba833f4f36536575dee304bbece5Jan Engelhardt cb.xt_entry = fw; 900aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->x6_parse(&cb); 901aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->mflags = cb.xflags; 902aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 903aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 904aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 905aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name: name of extension 906aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry: current option (from all ext's entries) being validated 907aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags: flags the extension has collected 908aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @i: conflicting option (id) to test for 909aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 910aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void 911aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_fcheck2(const char *name, const struct xt_option_entry *entry, 912aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *other, 913aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int xflags) 914aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 915aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int ef = 1 << entry->id, of = 1 << other->id; 916aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 917aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->also & of && !(xflags & of)) 918aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 919aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" also requires \"--%s\".\n", 920aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, other->name); 921aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 922aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (!(entry->excl & of)) 923aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Use of entry does not collide with other option, good. */ 924aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 925aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if ((xflags & (ef | of)) != (ef | of)) 926aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Conflicting options were not used. */ 927aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 928aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 929aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 930aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" cannot be used together with \"--%s\".\n", 931aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, other->name); 932aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 933aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 934aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 935aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name: name of extension 936aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags: accumulated flags 937aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry: extension's option table 938aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 939aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Check that all option constraints have been met. This effectively replaces 940aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * ->final_check of the older API. 941aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 942aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_options_fcheck(const char *name, unsigned int xflags, 943aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *table) 944aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 945aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry, *other; 946aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int i; 947aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 948aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (entry = table; entry->name != NULL; ++entry) { 949aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->flags & XTOPT_MAND && 950aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt !(xflags & (1 << entry->id))) 951aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 952aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" must be specified\n", 953aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name); 954ab847dfe38529d2aa67cc8178a54d5b45af11cfaJan Engelhardt if (!(xflags & (1 << entry->id))) 955ab847dfe38529d2aa67cc8178a54d5b45af11cfaJan Engelhardt /* Not required, not specified, thus skip. */ 956ab847dfe38529d2aa67cc8178a54d5b45af11cfaJan Engelhardt continue; 957aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 958aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) { 959aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id == i) 960aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 961aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Avoid conflict with self. Multi-use check 962aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * was done earlier in xtables_option_parse. 963aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 964aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 965aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt other = xtables_option_lookup(table, i); 966aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (other == NULL) 967aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 968aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_option_fcheck2(name, entry, other, xflags); 969aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 970aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 971aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 9723af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 9733af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/** 9743af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the 9753af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API. 9763af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */ 9773af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_tfcall(struct xtables_target *t) 9783af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{ 9793af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (t->x6_fcheck != NULL) { 9803af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt struct xt_fcheck_call cb; 9813af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 9823af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.ext_name = t->name; 9833af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.data = t->t->data; 9843af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.xflags = t->tflags; 9853af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt t->x6_fcheck(&cb); 9863af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } else if (t->final_check != NULL) { 9873af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt t->final_check(t->tflags); 9883af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } 9893af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (t->x6_options != NULL) 9903af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt xtables_options_fcheck(t->name, t->tflags, t->x6_options); 9913af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt} 9923af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 9933af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/** 9943af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the 9953af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API. 9963af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */ 9973af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_mfcall(struct xtables_match *m) 9983af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{ 9993af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (m->x6_fcheck != NULL) { 10003af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt struct xt_fcheck_call cb; 10013af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 10023af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.ext_name = m->name; 10033af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.data = m->m->data; 10043af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.xflags = m->mflags; 10053af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt m->x6_fcheck(&cb); 10063af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } else if (m->final_check != NULL) { 10073af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt m->final_check(m->mflags); 10083af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } 10093af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (m->x6_options != NULL) 10103af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt xtables_options_fcheck(m->name, m->mflags, m->x6_options); 10113af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt} 10122e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10132e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtstruct xtables_lmap *xtables_lmap_init(const char *file) 10142e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 10152e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this; 10162e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt char buf[512]; 10172e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt FILE *fp; 10182e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt char *cur, *nxt; 10192e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt int id; 10202e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10212e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt fp = fopen(file, "re"); 10222e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (fp == NULL) 10232e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 10242e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10252e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (fgets(buf, sizeof(buf), fp) != NULL) { 10262e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt cur = buf; 10272e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (isspace(*cur)) 10282e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++cur; 10292e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (*cur == '#' || *cur == '\n' || *cur == '\0') 10302e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 10312e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10322e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* iproute2 allows hex and dec format */ 10332e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt errno = 0; 10342e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10); 10352e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (nxt == cur || errno != 0) 10362e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 10372e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10382e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* same boundaries as in iproute2 */ 10392e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (id < 0 || id > 255) 10402e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 10412e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt cur = nxt; 10422e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10432e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (!isspace(*cur)) 10442e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 10452e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (isspace(*cur)) 10462e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++cur; 10472e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (*cur == '#' || *cur == '\n' || *cur == '\0') 10482e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 10492e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt nxt = cur; 10502e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (*nxt != '\0' && !isspace(*nxt)) 10512e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++nxt; 10522e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (nxt == cur) 10532e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 10542e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt *nxt = '\0'; 10552e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10562e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* found valid data */ 10572e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this = malloc(sizeof(*lmap_this)); 10582e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_this == NULL) { 10592e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt perror("malloc"); 10602e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt goto out; 10612e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 10622e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->id = id; 10632e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->name = strdup(cur); 10642e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_this->name == NULL) { 10652e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(lmap_this); 10662e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt goto out; 10672e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 10682e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->next = NULL; 10692e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10702e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_prev != NULL) 10712e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_prev->next = lmap_this; 10722e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt else 10732e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_head = lmap_this; 10742e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_prev = lmap_this; 10752e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 10762e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10772e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt fclose(fp); 10782e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return lmap_head; 10792e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt out: 10802e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt xtables_lmap_free(lmap_head); 10812e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 10822e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 10832e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10842e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtvoid xtables_lmap_free(struct xtables_lmap *head) 10852e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 10862e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt struct xtables_lmap *next; 10872e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10882e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = next) { 10892e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt next = head->next; 10902e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(head->name); 10912e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(head); 10922e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 10932e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 10942e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 10952e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtint xtables_lmap_name2id(const struct xtables_lmap *head, const char *name) 10962e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 10972e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = head->next) 10982e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (strcmp(head->name, name) == 0) 10992e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return head->id; 11002e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return -1; 11012e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 11022e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11032e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtconst char *xtables_lmap_id2name(const struct xtables_lmap *head, int id) 11042e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 11052e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = head->next) 11062e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (head->id == id) 11072e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return head->name; 11082e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 11092e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 1110