xtoptions.c revision f30231a02e145020fb47524f9a0daeb498a4f7d0
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 101a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt/** 102a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt * Require a simple integer. 103a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt */ 104a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardtstatic void xtopt_parse_int(struct xt_option_call *cb) 105a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt{ 106a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 1078b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt unsigned long long lmin = 0, lmax = UINT32_MAX; 108a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt unsigned int value; 109a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 110dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->type == XTTYPE_UINT8) 111dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt lmax = UINT8_MAX; 1120eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt else if (entry->type == XTTYPE_UINT16) 1130eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt lmax = UINT16_MAX; 1148b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt else if (entry->type == XTTYPE_UINT64) 1158b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt lmax = UINT64_MAX; 116d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt if (cb->entry->min != 0) 117d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt lmin = cb->entry->min; 118d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt if (cb->entry->max != 0) 119d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt lmax = cb->entry->max; 120d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt 121a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt if (!xtables_strtoui(cb->arg, NULL, &value, lmin, lmax)) 122a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 123a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt "%s: bad value for option \"--%s\", " 1248b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt "or out of range (%llu-%llu).\n", 125a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt cb->ext_name, entry->name, lmin, lmax); 126a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 127dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->type == XTTYPE_UINT8) { 128dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt cb->val.u8 = value; 129dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->flags & XTOPT_PUT) 130dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8; 1310eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt } else if (entry->type == XTTYPE_UINT16) { 1320eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt cb->val.u16 = value; 1330eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt if (entry->flags & XTOPT_PUT) 1340eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16; 135dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt } else if (entry->type == XTTYPE_UINT32) { 136a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt cb->val.u32 = value; 137a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt if (entry->flags & XTOPT_PUT) 138a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt *(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32; 1398b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt } else if (entry->type == XTTYPE_UINT64) { 1408b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt cb->val.u64 = value; 1418b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt if (entry->flags & XTOPT_PUT) 1428b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt *(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64; 143a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt } 144a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt} 145a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 14604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt/** 14704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * Multiple integer parse routine. 14804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * 14904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * This function is capable of parsing any number of fields. Only the first 15004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * two values from the string will be put into @cb however (and as such, 15104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * @cb->val.uXX_range is just that large) to cater for the few extensions that 15204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * do not have a range[2] field, but {min, max}, and which cannot use 15304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * XTOPT_POINTER. 15404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt */ 15504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardtstatic void xtopt_parse_mint(struct xt_option_call *cb) 15604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt{ 15704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 15804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt const char *arg = cb->arg; 159564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt size_t esize = sizeof(uint32_t); 160564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt char *put = XTOPT_MKPTR(cb); 16104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt unsigned int maxiter, value; 16204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt char *end = ""; 16304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt char sep = ':'; 16404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 1658bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt if (entry->type == XTTYPE_UINT8RC) 1668bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt esize = sizeof(uint8_t); 1678bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt else if (entry->type == XTTYPE_UINT16RC) 168564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt esize = sizeof(uint16_t); 169bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt else if (entry->type == XTTYPE_UINT64RC) 170bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt esize = sizeof(uint64_t); 171564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt maxiter = entry->size / esize; 17204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (maxiter == 0) 17304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */ 174564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt if (entry->size % esize != 0) 17504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " 17604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "not have proper size\n", __func__); 17704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 17804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->nvals = 0; 17904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt for (arg = cb->arg; ; arg = end + 1) { 18004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (cb->nvals == maxiter) 18104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " 18204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "components for option \"--%s\" (max: %u)\n", 18304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->ext_name, entry->name, maxiter); 18404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (!xtables_strtoui(arg, &end, &value, 0, UINT32_MAX)) 18504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 18604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "%s: bad value for option \"--%s\", " 18704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "or out of range (0-%u).\n", 18804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->ext_name, entry->name, UINT32_MAX); 18904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (*end != '\0' && *end != sep) 19004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 19104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "%s: Argument to \"--%s\" has unexpected " 19204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "characters.\n", cb->ext_name, entry->name); 19304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt ++cb->nvals; 194564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) { 1958bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt if (entry->type == XTTYPE_UINT8RC) 1968bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt cb->val.u8_range[cb->nvals] = value; 1978bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt else if (entry->type == XTTYPE_UINT16RC) 198564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt cb->val.u16_range[cb->nvals] = value; 199564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt else if (entry->type == XTTYPE_UINT32RC) 200564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt cb->val.u32_range[cb->nvals] = value; 201bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt else if (entry->type == XTTYPE_UINT64RC) 202bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt cb->val.u64_range[cb->nvals] = value; 203564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt } 204564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt if (entry->flags & XTOPT_PUT) { 2058bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt if (entry->type == XTTYPE_UINT8RC) 2068bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt *(uint8_t *)put = value; 2078bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt else if (entry->type == XTTYPE_UINT16RC) 208564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt *(uint16_t *)put = value; 209564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt else if (entry->type == XTTYPE_UINT32RC) 210564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt *(uint32_t *)put = value; 211bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt else if (entry->type == XTTYPE_UINT64RC) 212bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt *(uint64_t *)put = value; 213564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt put += esize; 214564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt } 21504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (*end == '\0') 21604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt break; 21704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt } 21804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt} 21904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 2204a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardtstatic void xtopt_parse_string(struct xt_option_call *cb) 2214a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt{ 2224a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt const struct xt_option_entry *entry = cb->entry; 2234a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt size_t z = strlen(cb->arg); 2244a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt char *p; 2254a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt 2264a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (entry->min != 0 && z < entry->min) 2274a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 2284a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "Argument must have a minimum length of " 2294a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "%u characters\n", entry->min); 2304a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (entry->max != 0 && z > entry->max) 2314a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 2324a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "Argument must have a maximum length of " 2334a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "%u characters\n", entry->max); 2344a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (!(entry->flags & XTOPT_PUT)) 2354a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt return; 2364a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (z >= entry->size) 2374a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt z = entry->size - 1; 2384a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt p = XTOPT_MKPTR(cb); 2394a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt strncpy(p, cb->arg, z); 2404a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt p[z] = '\0'; 2414a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt} 2424a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt 24361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardtstatic const struct tos_symbol_info { 24461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt unsigned char value; 24561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt const char *name; 24661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt} tos_symbol_names[] = { 24761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_LOWDELAY, "Minimize-Delay"}, 24861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_THROUGHPUT, "Maximize-Throughput"}, 24961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_RELIABILITY, "Maximize-Reliability"}, 25061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_MINCOST, "Minimize-Cost"}, 25161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_NORMALSVC, "Normal-Service"}, 25261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {}, 25361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt}; 25461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 25561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt/* 25661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * tos_parse_numeric - parse a string like "15/255" 25761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * 25861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @str: input string 25961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @tvm: (value/mask) tuple 26061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @max: maximum allowed value (must be pow(2,some_int)-1) 26161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt */ 26261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardtstatic bool tos_parse_numeric(const char *str, struct xt_option_call *cb, 26361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt unsigned int max) 26461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt{ 26561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt unsigned int value; 26661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt char *end; 26761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 26861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_strtoui(str, &end, &value, 0, max); 26961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_value = value; 27061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_mask = max; 27161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 27261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (*end == '/') { 27361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt const char *p = end + 1; 27461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 27561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (!xtables_strtoui(p, &end, &value, 0, max)) 27661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", 27761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt str); 27861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_mask = value; 27961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt } 28061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 28161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (*end != '\0') 28261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str); 28361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt return true; 28461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt} 28561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 28661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt/** 28761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @str: input string 28861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @tvm: (value/mask) tuple 28961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @def_mask: mask to force when a symbolic name is used 29061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt */ 29161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardtstatic void xtopt_parse_tosmask(struct xt_option_call *cb) 29261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt{ 29361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt const struct tos_symbol_info *symbol; 29461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt char *tmp; 29561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 29661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (xtables_strtoui(cb->arg, &tmp, NULL, 0, UINT8_MAX)) { 29761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt tos_parse_numeric(cb->arg, cb, UINT8_MAX); 29861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt return; 29961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt } 30061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt /* 30161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * This is our way we deal with different defaults 30261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * for different revisions. 30361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt */ 30461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_mask = cb->entry->max; 30561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol) 30661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (strcasecmp(cb->arg, symbol->name) == 0) { 30761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_value = symbol->value; 30861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt return; 30961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt } 31061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 31161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown", 31261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->arg); 31361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt} 31461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 315d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt/** 316d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt * Validate the input for being conformant to "mark[/mask]". 317d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt */ 318d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardtstatic void xtopt_parse_markmask(struct xt_option_call *cb) 319d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt{ 320d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt unsigned int mark = 0, mask = ~0U; 321d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt char *end; 322d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt 323d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX)) 324d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 325d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: bad mark value for option \"--%s\", " 326d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "or out of range.\n", 327d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 328d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (*end == '/' && 329d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) 330d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 331d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: bad mask value for option \"--%s\", " 332d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "or out of range.\n", 333d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 334d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (*end != '\0') 335d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 336d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: trailing garbage after value " 337d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "for option \"--%s\".\n", 338d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 339d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->val.mark = mark; 340d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->val.mask = mask; 341d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt} 342d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt 34341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardtstatic int xtopt_sysloglvl_compare(const void *a, const void *b) 34441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt{ 34541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const char *name = a; 34641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const struct syslog_level *entry = b; 34741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 34841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt return strcmp(name, entry->name); 34941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt} 35041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 35141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardtstatic void xtopt_parse_sysloglevel(struct xt_option_call *cb) 35241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt{ 35341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt static const struct syslog_level log_names[] = { /* must be sorted */ 35441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"alert", LOG_ALERT}, 35541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"crit", LOG_CRIT}, 35641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"debug", LOG_DEBUG}, 35741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"emerg", LOG_EMERG}, 35841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"error", LOG_ERR}, /* deprecated */ 35941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"info", LOG_INFO}, 36041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"notice", LOG_NOTICE}, 36141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"panic", LOG_EMERG}, /* deprecated */ 36241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"warning", LOG_WARNING}, 36341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt }; 36441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const struct syslog_level *e; 36541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt unsigned int num = 0; 36641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 36741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (!xtables_strtoui(cb->arg, NULL, &num, 0, 7)) { 36841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt e = bsearch(cb->arg, log_names, ARRAY_SIZE(log_names), 36941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt sizeof(*log_names), xtopt_sysloglvl_compare); 37041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (e == NULL) 37141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 37241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt "log level \"%s\" unknown\n", cb->arg); 37341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt num = e->level; 37441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt } 37541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt cb->val.syslog_level = num; 37641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 37741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt *(uint8_t *)XTOPT_MKPTR(cb) = num; 37841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt} 37941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 3802b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardtstatic void *xtables_sa_host(const void *sa, unsigned int afproto) 3812b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 3822b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (afproto == AF_INET6) 3832b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return &((struct sockaddr_in6 *)sa)->sin6_addr; 3842b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt else if (afproto == AF_INET) 3852b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return &((struct sockaddr_in *)sa)->sin_addr; 3862b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return (void *)sa; 3872b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 3882b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 3892b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardtstatic socklen_t xtables_sa_hostlen(unsigned int afproto) 3902b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 3912b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (afproto == AF_INET6) 3922b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return sizeof(struct in6_addr); 3932b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt else if (afproto == AF_INET) 3942b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return sizeof(struct in_addr); 3952b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return 0; 3962b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 3972b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 3982b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt/** 3992b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt * Accepts: a hostname (DNS), or a single inetaddr. 4002b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt */ 4012b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardtstatic void xtopt_parse_onehost(struct xt_option_call *cb) 4022b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 4032b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt struct addrinfo hints = {.ai_family = afinfo->family}; 4042b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt unsigned int adcount = 0; 4052b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt struct addrinfo *res, *p; 4062b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt int ret; 4072b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 4082b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt ret = getaddrinfo(cb->arg, NULL, &hints, &res); 4092b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (ret < 0) 4102b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 4112b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt "getaddrinfo: %s\n", gai_strerror(ret)); 4122b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 4132b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt for (p = res; p != NULL; p = p->ai_next) { 4142b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (adcount == 0) { 4152b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt memset(&cb->val.inetaddr, 0, sizeof(cb->val.inetaddr)); 4162b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt memcpy(&cb->val.inetaddr, 4172b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_host(p->ai_addr, p->ai_family), 4182b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_hostlen(p->ai_family)); 4192b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt ++adcount; 4202b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt continue; 4212b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt } 4222b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (memcmp(&cb->val.inetaddr, 4232b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_host(p->ai_addr, p->ai_family), 4242b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_hostlen(p->ai_family)) != 0) 4252b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 4262b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt "%s resolves to more than one address\n", 4272b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt cb->arg); 4282b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt } 4292b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 4302b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt freeaddrinfo(res); 4312b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 4322b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt /* Validation in xtables_option_metavalidate */ 4332b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt memcpy(XTOPT_MKPTR(cb), &cb->val.inetaddr, 4342b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt sizeof(cb->val.inetaddr)); 4352b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 4362b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 437b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt/** 438b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * @name: port name, or number as a string (e.g. "http" or "80") 439b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * 440b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * Resolve a port name to a number. Returns the port number in integral 441b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * form on success, or <0 on error. (errno will not be set.) 442b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt */ 443b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardtstatic int xtables_getportbyname(const char *name) 444b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt{ 445b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt struct addrinfo *res = NULL, *p; 446b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt int ret; 447b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 448b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = getaddrinfo(NULL, name, NULL, &res); 449b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (ret < 0) 450b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt return -1; 451b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = -1; 452b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt for (p = res; p != NULL; p = p->ai_next) { 453b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (p->ai_family == AF_INET6) { 454b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = ((struct sockaddr_in6 *)p->ai_addr)->sin6_port; 455b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt break; 456b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } else if (p->ai_family == AF_INET) { 457b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = ((struct sockaddr_in *)p->ai_addr)->sin_port; 458b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt break; 459b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } 460b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } 461b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt freeaddrinfo(res); 46244517bda3d8130638882f69478a8091316f30cbbJan Engelhardt if (ret < 0) 46344517bda3d8130638882f69478a8091316f30cbbJan Engelhardt return ret; 464b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt return ntohs(ret); 465b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt} 466b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 467b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt/** 468b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * Validate and parse a port specification and put the result into @cb. 469b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt */ 470b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardtstatic void xtopt_parse_port(struct xt_option_call *cb) 471b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt{ 472b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt int ret; 473b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 474b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = xtables_getportbyname(cb->arg); 475b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (ret < 0) 476b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 477b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt "Port \"%s\" does not resolve to anything.\n", 478b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt cb->arg); 479b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt cb->val.port = ret; 480b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (cb->entry->type == XTTYPE_PORT_NE) 481b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt cb->val.port = htons(cb->val.port); 482b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 483b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port; 484b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt} 485b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 486f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardtstatic void xtopt_parse_mport(struct xt_option_call *cb) 487f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt{ 488f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt static const size_t esize = sizeof(uint16_t); 489f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 490f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt char *lo_arg, *wp_arg, *arg; 491f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt unsigned int maxiter; 492f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt int value; 493f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 494f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt wp_arg = lo_arg = strdup(cb->arg); 495f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (lo_arg == NULL) 496f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(RESOURCE_PROBLEM, "strdup"); 497f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 498f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt maxiter = entry->size / esize; 499f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (maxiter == 0) 500f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt maxiter = 2; /* ARRAY_SIZE(cb->val.port_range) */ 501f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (entry->size % esize != 0) 502f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " 503f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "not have proper size\n", __func__); 504f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 505f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[0] = 0; 506f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[1] = UINT16_MAX; 507f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->nvals = 0; 508f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 509f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt while ((arg = strsep(&wp_arg, ":")) != NULL) { 510f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (cb->nvals == maxiter) 511f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " 512f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "components for option \"--%s\" (max: %u)\n", 513f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->ext_name, entry->name, maxiter); 514f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (*arg == '\0') { 515f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt ++cb->nvals; 516f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt continue; 517f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt } 518f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 519f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt value = xtables_getportbyname(arg); 520f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (value < 0) 521f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 522f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "Port \"%s\" does not resolve to " 523f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "anything.\n", arg); 524f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (entry->type == XTTYPE_PORTRC_NE) 525f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt value = htons(value); 526f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (cb->nvals < ARRAY_SIZE(cb->val.port_range)) 527f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[cb->nvals] = value; 528f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt ++cb->nvals; 529f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt } 530f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 531f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (cb->nvals == 1) { 532f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[1] = cb->val.port_range[0]; 533f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt ++cb->nvals; 534f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt } 535f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (entry->flags & XTOPT_PUT) 536f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt memcpy(XTOPT_MKPTR(cb), cb->val.port_range, sizeof(uint16_t) * 537f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt (cb->nvals <= maxiter ? cb->nvals : maxiter)); 538f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt free(lo_arg); 539f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt} 540f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 541aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void (*const xtopt_subparse[])(struct xt_option_call *) = { 542dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt [XTTYPE_UINT8] = xtopt_parse_int, 5430eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt [XTTYPE_UINT16] = xtopt_parse_int, 544a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt [XTTYPE_UINT32] = xtopt_parse_int, 5458b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt [XTTYPE_UINT64] = xtopt_parse_int, 5468bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt [XTTYPE_UINT8RC] = xtopt_parse_mint, 547564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt [XTTYPE_UINT16RC] = xtopt_parse_mint, 54804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt [XTTYPE_UINT32RC] = xtopt_parse_mint, 549bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt [XTTYPE_UINT64RC] = xtopt_parse_mint, 5504a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt [XTTYPE_STRING] = xtopt_parse_string, 55161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt [XTTYPE_TOSMASK] = xtopt_parse_tosmask, 552d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt [XTTYPE_MARKMASK32] = xtopt_parse_markmask, 55341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, 5542b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt [XTTYPE_ONEHOST] = xtopt_parse_onehost, 555b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt [XTTYPE_PORT] = xtopt_parse_port, 556b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt [XTTYPE_PORT_NE] = xtopt_parse_port, 557f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt [XTTYPE_PORTRC] = xtopt_parse_mport, 558f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt [XTTYPE_PORTRC_NE] = xtopt_parse_mport, 559aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}; 560aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 561aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const size_t xtopt_psize[] = { 562dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt [XTTYPE_UINT8] = sizeof(uint8_t), 5630eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt [XTTYPE_UINT16] = sizeof(uint16_t), 564a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt [XTTYPE_UINT32] = sizeof(uint32_t), 5658b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt [XTTYPE_UINT64] = sizeof(uint64_t), 5668bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt [XTTYPE_UINT8RC] = sizeof(uint8_t[2]), 567564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), 56804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), 569bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), 5704a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt [XTTYPE_STRING] = -1, 57141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), 5722b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt [XTTYPE_ONEHOST] = sizeof(union nf_inet_addr), 573b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt [XTTYPE_PORT] = sizeof(uint16_t), 574b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt [XTTYPE_PORT_NE] = sizeof(uint16_t), 575f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt [XTTYPE_PORTRC] = sizeof(uint16_t[2]), 576f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt [XTTYPE_PORTRC_NE] = sizeof(uint16_t[2]), 577aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}; 578aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 579aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 580aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * The master option parsing routine. May be used for the ".x6_parse" 581aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * function pointer in extensions if fully automatic parsing is desired. 582aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * It may be also called manually from a custom x6_parse function. 583aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 584aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_parse(struct xt_option_call *cb) 585aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 586aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 587aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int eflag = 1 << cb->entry->id; 588aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 589aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 590aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use 591aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * prevention. Though it turned out that this is too much typing (most 592aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * of the options are one-time use only), so now we also have 593aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * %XTOPT_MULTI. 594aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 595aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) && 596aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->xflags & eflag) 597aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 598aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" can only be used once.\n", 599aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, cb->entry->name); 600aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb->invert && !(entry->flags & XTOPT_INVERT)) 601aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 602aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" cannot be inverted.\n", 603aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, entry->name); 604aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type != XTTYPE_NONE && optarg == NULL) 605aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 606aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" requires an argument.\n", 607aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, entry->name); 608aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type <= ARRAY_SIZE(xtopt_subparse) && 609aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_subparse[entry->type] != NULL) 610aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_subparse[entry->type](cb); 611aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Exclusion with other flags tested later in finalize. */ 612aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->xflags |= 1 << entry->id; 613aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 614aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 615aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 616aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Verifies that an extension's option map descriptor is valid, and ought to 617aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * be called right after the extension has been loaded, and before option 618aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * merging/xfrm. 619aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 620aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_metavalidate(const char *name, 621aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry) 622aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 623aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (; entry->name != NULL; ++entry) { 624aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id >= CHAR_BIT * sizeof(unsigned int) || 625aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt entry->id >= XT_OPTION_OFFSET_SCALE) 626aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 627aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension %s uses invalid ID %u\n", 628aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->id); 629aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (!(entry->flags & XTOPT_PUT)) 630aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 631aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type >= ARRAY_SIZE(xtopt_psize)) 632aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 633aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: entry type of option \"--%s\" cannot be " 634aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "combined with XTOPT_PUT\n", 635aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name); 63604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (xtopt_psize[entry->type] != -1 && 63704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xtopt_psize[entry->type] != entry->size) 638aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 639aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" points to a memory block " 640aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "of wrong size (expected %zu, got %zu)\n", 641aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, 642aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_psize[entry->type], entry->size); 643aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 644aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 645aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 646aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 647aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Find an option entry by its id. 648aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 649aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const struct xt_option_entry * 650aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_lookup(const struct xt_option_entry *entry, unsigned int id) 651aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 652aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (; entry->name != NULL; ++entry) 653aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id == id) 654aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return entry; 655aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return NULL; 656aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 657aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 658aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 659aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c: getopt id (i.e. with offset) 660aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw: struct ipt_entry or ip6t_entry 661aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 662aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the 663aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API. 664aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 665aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_tpcall(unsigned int c, char **argv, bool invert, 666aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xtables_target *t, void *fw) 667aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 668aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xt_option_call cb; 669aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 670aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (t->x6_parse == NULL) { 671aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (t->parse != NULL) 672aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->parse(c - t->option_offset, argv, invert, 673aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt &t->tflags, fw, &t->t); 674aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 675aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 676aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 677aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt c -= t->option_offset; 678aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.entry = xtables_option_lookup(t->x6_options, c); 679aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb.entry == NULL) 680aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_error(OTHER_PROBLEM, 681aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension does not know id %u\n", c); 682aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.arg = optarg; 683aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.invert = invert; 684aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.ext_name = t->name; 685aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.data = t->t->data; 686aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.xflags = t->tflags; 68733d180871bea281a448efd0c1a49517318162382Jan Engelhardt cb.target = &t->t; 688aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->x6_parse(&cb); 689aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->tflags = cb.xflags; 690aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 691aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 692aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 693aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c: getopt id (i.e. with offset) 694aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw: struct ipt_entry or ip6t_entry 695aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 696aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the 697aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API. 698aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 699aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_mpcall(unsigned int c, char **argv, bool invert, 700aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xtables_match *m, void *fw) 701aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 702aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xt_option_call cb; 703aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 704aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (m->x6_parse == NULL) { 705aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (m->parse != NULL) 706aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->parse(c - m->option_offset, argv, invert, 707aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt &m->mflags, fw, &m->m); 708aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 709aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 710aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 711aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt c -= m->option_offset; 712aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.entry = xtables_option_lookup(m->x6_options, c); 713aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb.entry == NULL) 714aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_error(OTHER_PROBLEM, 715aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension does not know id %u\n", c); 716aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.arg = optarg; 717aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.invert = invert; 718aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.ext_name = m->name; 719aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.data = m->m->data; 720aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.xflags = m->mflags; 72133d180871bea281a448efd0c1a49517318162382Jan Engelhardt cb.match = &m->m; 722aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->x6_parse(&cb); 723aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->mflags = cb.xflags; 724aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 725aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 726aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 727aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name: name of extension 728aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry: current option (from all ext's entries) being validated 729aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags: flags the extension has collected 730aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @i: conflicting option (id) to test for 731aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 732aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void 733aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_fcheck2(const char *name, const struct xt_option_entry *entry, 734aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *other, 735aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int xflags) 736aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 737aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int ef = 1 << entry->id, of = 1 << other->id; 738aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 739aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->also & of && !(xflags & of)) 740aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 741aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" also requires \"--%s\".\n", 742aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, other->name); 743aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 744aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (!(entry->excl & of)) 745aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Use of entry does not collide with other option, good. */ 746aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 747aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if ((xflags & (ef | of)) != (ef | of)) 748aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Conflicting options were not used. */ 749aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 750aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 751aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 752aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" cannot be used together with \"--%s\".\n", 753aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, other->name); 754aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 755aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 756aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 757aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name: name of extension 758aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags: accumulated flags 759aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry: extension's option table 760aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 761aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Check that all option constraints have been met. This effectively replaces 762aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * ->final_check of the older API. 763aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 764aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_options_fcheck(const char *name, unsigned int xflags, 765aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *table) 766aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 767aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry, *other; 768aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int i; 769aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 770aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (entry = table; entry->name != NULL; ++entry) { 771aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->flags & XTOPT_MAND && 772aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt !(xflags & (1 << entry->id))) 773aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 774aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" must be specified\n", 775aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name); 776aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 777aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) { 778aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id == i) 779aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 780aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Avoid conflict with self. Multi-use check 781aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * was done earlier in xtables_option_parse. 782aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 783aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 784aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt other = xtables_option_lookup(table, i); 785aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (other == NULL) 786aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 787aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_option_fcheck2(name, entry, other, xflags); 788aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 789aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 790aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 7913af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 7923af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/** 7933af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the 7943af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API. 7953af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */ 7963af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_tfcall(struct xtables_target *t) 7973af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{ 7983af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (t->x6_fcheck != NULL) { 7993af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt struct xt_fcheck_call cb; 8003af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 8013af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.ext_name = t->name; 8023af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.data = t->t->data; 8033af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.xflags = t->tflags; 8043af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt t->x6_fcheck(&cb); 8053af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } else if (t->final_check != NULL) { 8063af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt t->final_check(t->tflags); 8073af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } 8083af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (t->x6_options != NULL) 8093af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt xtables_options_fcheck(t->name, t->tflags, t->x6_options); 8103af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt} 8113af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 8123af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/** 8133af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the 8143af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API. 8153af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */ 8163af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_mfcall(struct xtables_match *m) 8173af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{ 8183af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (m->x6_fcheck != NULL) { 8193af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt struct xt_fcheck_call cb; 8203af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 8213af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.ext_name = m->name; 8223af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.data = m->m->data; 8233af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.xflags = m->mflags; 8243af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt m->x6_fcheck(&cb); 8253af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } else if (m->final_check != NULL) { 8263af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt m->final_check(m->mflags); 8273af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } 8283af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (m->x6_options != NULL) 8293af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt xtables_options_fcheck(m->name, m->mflags, m->x6_options); 8303af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt} 8312e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 8322e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtstruct xtables_lmap *xtables_lmap_init(const char *file) 8332e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 8342e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this; 8352e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt char buf[512]; 8362e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt FILE *fp; 8372e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt char *cur, *nxt; 8382e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt int id; 8392e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 8402e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt fp = fopen(file, "re"); 8412e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (fp == NULL) 8422e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 8432e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 8442e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (fgets(buf, sizeof(buf), fp) != NULL) { 8452e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt cur = buf; 8462e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (isspace(*cur)) 8472e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++cur; 8482e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (*cur == '#' || *cur == '\n' || *cur == '\0') 8492e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 8502e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 8512e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* iproute2 allows hex and dec format */ 8522e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt errno = 0; 8532e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10); 8542e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (nxt == cur || errno != 0) 8552e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 8562e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 8572e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* same boundaries as in iproute2 */ 8582e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (id < 0 || id > 255) 8592e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 8602e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt cur = nxt; 8612e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 8622e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (!isspace(*cur)) 8632e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 8642e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (isspace(*cur)) 8652e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++cur; 8662e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (*cur == '#' || *cur == '\n' || *cur == '\0') 8672e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 8682e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt nxt = cur; 8692e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (*nxt != '\0' && !isspace(*nxt)) 8702e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++nxt; 8712e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (nxt == cur) 8722e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 8732e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt *nxt = '\0'; 8742e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 8752e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* found valid data */ 8762e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this = malloc(sizeof(*lmap_this)); 8772e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_this == NULL) { 8782e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt perror("malloc"); 8792e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt goto out; 8802e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 8812e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->id = id; 8822e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->name = strdup(cur); 8832e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_this->name == NULL) { 8842e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(lmap_this); 8852e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt goto out; 8862e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 8872e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->next = NULL; 8882e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 8892e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_prev != NULL) 8902e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_prev->next = lmap_this; 8912e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt else 8922e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_head = lmap_this; 8932e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_prev = lmap_this; 8942e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 8952e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 8962e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt fclose(fp); 8972e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return lmap_head; 8982e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt out: 8992e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt xtables_lmap_free(lmap_head); 9002e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 9012e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 9022e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 9032e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtvoid xtables_lmap_free(struct xtables_lmap *head) 9042e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 9052e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt struct xtables_lmap *next; 9062e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 9072e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = next) { 9082e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt next = head->next; 9092e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(head->name); 9102e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(head); 9112e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 9122e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 9132e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 9142e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtint xtables_lmap_name2id(const struct xtables_lmap *head, const char *name) 9152e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 9162e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = head->next) 9172e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (strcmp(head->name, name) == 0) 9182e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return head->id; 9192e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return -1; 9202e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 9212e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 9222e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtconst char *xtables_lmap_id2name(const struct xtables_lmap *head, int id) 9232e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 9242e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = head->next) 9252e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (head->id == id) 9262e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return head->name; 9272e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 9282e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 929