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 441b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardtstatic const size_t xtopt_psize[] = { 451b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt /* 461b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt * All types not listed here, and thus essentially being initialized to 471b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt * zero have zero on purpose. 481b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt */ 491b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_UINT8] = sizeof(uint8_t), 501b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_UINT16] = sizeof(uint16_t), 511b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_UINT32] = sizeof(uint32_t), 521b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_UINT64] = sizeof(uint64_t), 531b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_UINT8RC] = sizeof(uint8_t[2]), 541b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), 551b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), 561b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), 571b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_DOUBLE] = sizeof(double), 581b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_STRING] = -1, 591b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), 601b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_HOST] = sizeof(union nf_inet_addr), 611b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_HOSTMASK] = sizeof(union nf_inet_addr), 621b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_PROTOCOL] = sizeof(uint8_t), 631b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_PORT] = sizeof(uint16_t), 641b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_PORTRC] = sizeof(uint16_t[2]), 651b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_PLENMASK] = sizeof(union nf_inet_addr), 661b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt [XTTYPE_ETHERMAC] = sizeof(uint8_t[6]), 671b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt}; 681b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt 6941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt/** 70aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Creates getopt options from the x6-style option map, and assigns each a 71aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * getopt id. 72aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 73aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstruct option * 74aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_options_xfrm(struct option *orig_opts, struct option *oldopts, 75aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry, unsigned int *offset) 76aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 77aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int num_orig, num_old = 0, num_new, i; 78aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct option *merge, *mp; 79aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 80aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry == NULL) 81aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return oldopts; 82aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_orig = 0; orig_opts[num_orig].name != NULL; ++num_orig) 83aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 84aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (oldopts != NULL) 85aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_old = 0; oldopts[num_old].name != NULL; ++num_old) 86aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 87aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (num_new = 0; entry[num_new].name != NULL; ++num_new) 88aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt ; 89aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 90aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 91aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Since @oldopts also has @orig_opts already (and does so at the 92aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * start), skip these entries. 93aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 94aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt oldopts += num_orig; 95aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt num_old -= num_orig; 96aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 97aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1)); 98aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (merge == NULL) 99aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return NULL; 100aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 101aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Let the base options -[ADI...] have precedence over everything */ 102aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memcpy(merge, orig_opts, sizeof(*mp) * num_orig); 103aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp = merge + num_orig; 104aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 105aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Second, the new options */ 106aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->option_offset += XT_OPTION_OFFSET_SCALE; 107aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt *offset = xt_params->option_offset; 108aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 109aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (i = 0; i < num_new; ++i, ++mp, ++entry) { 110aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->name = entry->name; 111aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->has_arg = entry->type != XTTYPE_NONE; 112aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->flag = NULL; 113aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp->val = entry->id + *offset; 114aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 115aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 116aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Third, the old options */ 117aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memcpy(mp, oldopts, sizeof(*mp) * num_old); 118aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt mp += num_old; 119aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_free_opts(0); 120aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 121aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Clear trailing entry */ 122aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt memset(mp, 0, sizeof(*mp)); 123aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return merge; 124aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 125aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 1261b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt/** 1271b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt * Give the upper limit for a certain type. 1281b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt */ 12957e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardtstatic uintmax_t xtopt_max_by_type(enum xt_option_type type) 13057e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt{ 13157e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt switch (type) { 13257e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT8: 13357e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT8RC: 13457e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt return UINT8_MAX; 13557e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT16: 13657e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT16RC: 13757e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt return UINT16_MAX; 13857e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT32: 13957e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT32RC: 14057e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt return UINT32_MAX; 14157e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT64: 14257e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt case XTTYPE_UINT64RC: 14357e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt return UINT64_MAX; 14457e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt default: 14557e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt return 0; 14657e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt } 14757e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt} 14857e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt 149a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt/** 1501b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt * Return the size of a single entity based upon a type - predominantly an 1511b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt * XTTYPE_UINT*RC type. 1521b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt */ 1531b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardtstatic size_t xtopt_esize_by_type(enum xt_option_type type) 1541b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt{ 1551b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt switch (type) { 1561b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt case XTTYPE_UINT8RC: 1571b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt return xtopt_psize[XTTYPE_UINT8]; 1581b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt case XTTYPE_UINT16RC: 1591b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt return xtopt_psize[XTTYPE_UINT16]; 1601b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt case XTTYPE_UINT32RC: 1611b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt return xtopt_psize[XTTYPE_UINT32]; 1621b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt case XTTYPE_UINT64RC: 1631b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt return xtopt_psize[XTTYPE_UINT64]; 1641b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt default: 1651b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt return xtopt_psize[type]; 1661b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt } 1671b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt} 1681b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt 1691b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt/** 170a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt * Require a simple integer. 171a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt */ 172a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardtstatic void xtopt_parse_int(struct xt_option_call *cb) 173a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt{ 174a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 17557e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt uintmax_t lmin = 0, lmax = xtopt_max_by_type(entry->type); 1760b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt uintmax_t value; 177a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 178d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt if (cb->entry->min != 0) 179d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt lmin = cb->entry->min; 180d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt if (cb->entry->max != 0) 181d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt lmax = cb->entry->max; 182d78254d7f9d18ef76377a3013302430cce8ea702Jan Engelhardt 1832305d5fb42fc059f38fc1bdf53411dbeecdb310bJP Abgrall if (!xtables_strtoul(cb->arg, NULL, &value, lmin, lmax)) 184a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 185a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt "%s: bad value for option \"--%s\", " 1860b7a140944738d67b9c4e6f09992c8407eefb18aJan Engelhardt "or out of range (%ju-%ju).\n", 187a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt cb->ext_name, entry->name, lmin, lmax); 188a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 189dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->type == XTTYPE_UINT8) { 190dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt cb->val.u8 = value; 191dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt if (entry->flags & XTOPT_PUT) 192dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8; 1930eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt } else if (entry->type == XTTYPE_UINT16) { 1940eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt cb->val.u16 = value; 1950eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt if (entry->flags & XTOPT_PUT) 1960eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16; 197dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt } else if (entry->type == XTTYPE_UINT32) { 198a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt cb->val.u32 = value; 199a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt if (entry->flags & XTOPT_PUT) 200a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt *(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32; 2018b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt } else if (entry->type == XTTYPE_UINT64) { 2028b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt cb->val.u64 = value; 2038b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt if (entry->flags & XTOPT_PUT) 2048b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt *(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64; 205a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt } 206a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt} 207a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt 20804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt/** 209f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt * Require a simple floating point number. 210f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt */ 211f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardtstatic void xtopt_parse_float(struct xt_option_call *cb) 212f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt{ 213f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 214f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt double value; 215f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt char *end; 216f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt 217f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt value = strtod(cb->arg, &end); 218f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt if (end == cb->arg || *end != '\0' || 219f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt (entry->min != entry->max && 220f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt (value < entry->min || value > entry->max))) 221f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 222f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt "%s: bad value for option \"--%s\", " 223f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt "or out of range (%u-%u).\n", 224f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt cb->ext_name, entry->name, entry->min, entry->max); 225f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt 226f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt cb->val.dbl = value; 227f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt if (entry->flags & XTOPT_PUT) 228f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt *(double *)XTOPT_MKPTR(cb) = cb->val.dbl; 229f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt} 230f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt 231f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt/** 2321b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt * Copy the parsed value to the appropriate entry in cb->val. 2331b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt */ 2341b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardtstatic void xtopt_mint_value_to_cb(struct xt_option_call *cb, uintmax_t value) 2351b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt{ 2361b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 2371b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt 2381b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt if (cb->nvals >= ARRAY_SIZE(cb->val.u32_range)) 2391b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt return; 2401b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt if (entry->type == XTTYPE_UINT8RC) 2411b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt cb->val.u8_range[cb->nvals] = value; 2421b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt else if (entry->type == XTTYPE_UINT16RC) 2431b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt cb->val.u16_range[cb->nvals] = value; 2441b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt else if (entry->type == XTTYPE_UINT32RC) 2451b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt cb->val.u32_range[cb->nvals] = value; 2461b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt else if (entry->type == XTTYPE_UINT64RC) 2471b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt cb->val.u64_range[cb->nvals] = value; 2481b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt} 2491b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt 2501b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt/** 2511b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt * Copy the parsed value to the data area, using appropriate type access. 2521b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt */ 2531b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardtstatic void xtopt_mint_value_to_ptr(struct xt_option_call *cb, void **datap, 2541b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt uintmax_t value) 2551b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt{ 2561b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 2571b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt void *data = *datap; 2581b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt 2591b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt if (!(entry->flags & XTOPT_PUT)) 2601b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt return; 2611b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt if (entry->type == XTTYPE_UINT8RC) 2621b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt *(uint8_t *)data = value; 2631b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt else if (entry->type == XTTYPE_UINT16RC) 2641b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt *(uint16_t *)data = value; 2651b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt else if (entry->type == XTTYPE_UINT32RC) 2661b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt *(uint32_t *)data = value; 2671b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt else if (entry->type == XTTYPE_UINT64RC) 2681b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt *(uint64_t *)data = value; 2691b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt data += xtopt_esize_by_type(entry->type); 2701b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt *datap = data; 2711b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt} 2721b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt 2731b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt/** 27404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * Multiple integer parse routine. 27504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * 27604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * This function is capable of parsing any number of fields. Only the first 27704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * two values from the string will be put into @cb however (and as such, 27804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * @cb->val.uXX_range is just that large) to cater for the few extensions that 27904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * do not have a range[2] field, but {min, max}, and which cannot use 28004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt * XTOPT_POINTER. 28104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt */ 28204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardtstatic void xtopt_parse_mint(struct xt_option_call *cb) 28304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt{ 28404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 28504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt const char *arg = cb->arg; 2861b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt size_t esize = xtopt_esize_by_type(entry->type); 2876944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt const uintmax_t lmax = xtopt_max_by_type(entry->type); 2881b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt void *put = XTOPT_MKPTR(cb); 28957e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt unsigned int maxiter; 29057e2e37ebe5319cf84381bdb319ea94143b1bf97Jan Engelhardt uintmax_t value; 29104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt char *end = ""; 29204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt char sep = ':'; 29304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 294564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt maxiter = entry->size / esize; 29504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (maxiter == 0) 2966944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt maxiter = ARRAY_SIZE(cb->val.u32_range); 297564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt if (entry->size % esize != 0) 29804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " 29904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "not have proper size\n", __func__); 30004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 30104bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->nvals = 0; 3026944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt for (arg = cb->arg, end = (char *)arg; ; arg = end + 1) { 30304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (cb->nvals == maxiter) 30404bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " 30504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt "components for option \"--%s\" (max: %u)\n", 30604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt cb->ext_name, entry->name, maxiter); 3076944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt if (*arg == '\0' || *arg == sep) { 3086944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt /* Default range components when field not spec'd. */ 3096944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt end = (char *)arg; 3106944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt value = (cb->nvals == 1) ? lmax : 0; 3116944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt } else { 3126944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt if (!xtables_strtoul(arg, &end, &value, 0, lmax)) 3136944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 3146944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt "%s: bad value for option \"--%s\" near " 3156944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt "\"%s\", or out of range (0-%ju).\n", 3166944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt cb->ext_name, entry->name, arg, lmax); 3176944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt if (*end != '\0' && *end != sep) 3186944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 3196944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt "%s: Argument to \"--%s\" has " 3206944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt "unexpected characters near \"%s\".\n", 3216944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt cb->ext_name, entry->name, end); 3226944f2c8190f1c4319aeac748470c71b0ba45025Jan Engelhardt } 3231b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt xtopt_mint_value_to_cb(cb, value); 3240787a82873fe9db5dea478942b183e6ff2a8500dJan Engelhardt ++cb->nvals; 3251b6c7632e5e35ecce91f87a4ae36eca3103cfee2Jan Engelhardt xtopt_mint_value_to_ptr(cb, &put, value); 32604bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (*end == '\0') 32704bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt break; 32804bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt } 32904bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt} 33004bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt 3314a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardtstatic void xtopt_parse_string(struct xt_option_call *cb) 3324a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt{ 3334a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt const struct xt_option_entry *entry = cb->entry; 3344a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt size_t z = strlen(cb->arg); 3354a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt char *p; 3364a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt 3374a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (entry->min != 0 && z < entry->min) 3384a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 3394a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "Argument must have a minimum length of " 3404a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "%u characters\n", entry->min); 3414a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (entry->max != 0 && z > entry->max) 3424a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 3434a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "Argument must have a maximum length of " 3444a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt "%u characters\n", entry->max); 3454a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (!(entry->flags & XTOPT_PUT)) 3464a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt return; 3474a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt if (z >= entry->size) 3484a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt z = entry->size - 1; 3494a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt p = XTOPT_MKPTR(cb); 3504a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt strncpy(p, cb->arg, z); 3514a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt p[z] = '\0'; 3524a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt} 3534a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt 35461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardtstatic const struct tos_symbol_info { 35561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt unsigned char value; 35661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt const char *name; 35761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt} tos_symbol_names[] = { 35861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_LOWDELAY, "Minimize-Delay"}, 35961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_THROUGHPUT, "Maximize-Throughput"}, 36061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_RELIABILITY, "Maximize-Reliability"}, 36161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_MINCOST, "Minimize-Cost"}, 36261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {IPTOS_NORMALSVC, "Normal-Service"}, 36361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt {}, 36461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt}; 36561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 36661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt/* 36761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * tos_parse_numeric - parse a string like "15/255" 36861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * 36961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @str: input string 37061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @tvm: (value/mask) tuple 37161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @max: maximum allowed value (must be pow(2,some_int)-1) 37261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt */ 37361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardtstatic bool tos_parse_numeric(const char *str, struct xt_option_call *cb, 37461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt unsigned int max) 37561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt{ 37661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt unsigned int value; 37761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt char *end; 37861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 37961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_strtoui(str, &end, &value, 0, max); 38061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_value = value; 38161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_mask = max; 38261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 38361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (*end == '/') { 38461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt const char *p = end + 1; 38561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 38661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (!xtables_strtoui(p, &end, &value, 0, max)) 38761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", 38861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt str); 38961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_mask = value; 39061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt } 39161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 39261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (*end != '\0') 39361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str); 39461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt return true; 39561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt} 39661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 39761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt/** 39861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @str: input string 39961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @tvm: (value/mask) tuple 40061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * @def_mask: mask to force when a symbolic name is used 40161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt */ 40261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardtstatic void xtopt_parse_tosmask(struct xt_option_call *cb) 40361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt{ 40461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt const struct tos_symbol_info *symbol; 40561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt char *tmp; 40661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 40761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (xtables_strtoui(cb->arg, &tmp, NULL, 0, UINT8_MAX)) { 40861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt tos_parse_numeric(cb->arg, cb, UINT8_MAX); 40961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt return; 41061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt } 41161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt /* 41261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * This is our way we deal with different defaults 41361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt * for different revisions. 41461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt */ 41561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_mask = cb->entry->max; 41661cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol) 41761cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt if (strcasecmp(cb->arg, symbol->name) == 0) { 41861cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->val.tos_value = symbol->value; 41961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt return; 42061cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt } 42161cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 42261cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt xtables_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown", 42361cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt cb->arg); 42461cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt} 42561cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt 426d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt/** 427d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt * Validate the input for being conformant to "mark[/mask]". 428d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt */ 429d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardtstatic void xtopt_parse_markmask(struct xt_option_call *cb) 430d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt{ 431d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt unsigned int mark = 0, mask = ~0U; 432d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt char *end; 433d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt 434d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX)) 435d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 436d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: bad mark value for option \"--%s\", " 437d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "or out of range.\n", 438d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 439d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (*end == '/' && 440d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) 441d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 442d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: bad mask value for option \"--%s\", " 443d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "or out of range.\n", 444d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 445d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt if (*end != '\0') 446d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 447d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "%s: trailing garbage after value " 448d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt "for option \"--%s\".\n", 449d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->ext_name, cb->entry->name); 450d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->val.mark = mark; 451d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt cb->val.mask = mask; 452d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt} 453d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt 45441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardtstatic int xtopt_sysloglvl_compare(const void *a, const void *b) 45541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt{ 45641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const char *name = a; 45741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const struct syslog_level *entry = b; 45841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 45941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt return strcmp(name, entry->name); 46041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt} 46141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 46241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardtstatic void xtopt_parse_sysloglevel(struct xt_option_call *cb) 46341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt{ 46441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt static const struct syslog_level log_names[] = { /* must be sorted */ 46541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"alert", LOG_ALERT}, 46641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"crit", LOG_CRIT}, 46741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"debug", LOG_DEBUG}, 46841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"emerg", LOG_EMERG}, 46941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"error", LOG_ERR}, /* deprecated */ 47041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"info", LOG_INFO}, 47141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"notice", LOG_NOTICE}, 47241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"panic", LOG_EMERG}, /* deprecated */ 47341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt {"warning", LOG_WARNING}, 47441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt }; 47541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt const struct syslog_level *e; 47641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt unsigned int num = 0; 47741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 47841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (!xtables_strtoui(cb->arg, NULL, &num, 0, 7)) { 47941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt e = bsearch(cb->arg, log_names, ARRAY_SIZE(log_names), 48041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt sizeof(*log_names), xtopt_sysloglvl_compare); 48141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (e == NULL) 48241a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 48341a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt "log level \"%s\" unknown\n", cb->arg); 48441a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt num = e->level; 48541a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt } 48641a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt cb->val.syslog_level = num; 48741a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 48841a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt *(uint8_t *)XTOPT_MKPTR(cb) = num; 48941a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt} 49041a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt 4912b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardtstatic void *xtables_sa_host(const void *sa, unsigned int afproto) 4922b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 4932b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (afproto == AF_INET6) 4942b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return &((struct sockaddr_in6 *)sa)->sin6_addr; 4952b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt else if (afproto == AF_INET) 4962b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return &((struct sockaddr_in *)sa)->sin_addr; 4972b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return (void *)sa; 4982b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 4992b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 5002b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardtstatic socklen_t xtables_sa_hostlen(unsigned int afproto) 5012b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 5022b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (afproto == AF_INET6) 5032b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return sizeof(struct in6_addr); 5042b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt else if (afproto == AF_INET) 5052b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return sizeof(struct in_addr); 5062b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt return 0; 5072b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 5082b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 5092b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt/** 510d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * Accepts: a hostname (DNS), or a single inetaddr - without any mask. The 511d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * result is stored in @cb->val.haddr. Additionally, @cb->val.hmask and 512d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * @cb->val.hlen are set for completeness to the appropriate values. 5132b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt */ 514d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardtstatic void xtopt_parse_host(struct xt_option_call *cb) 5152b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt{ 5162b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt struct addrinfo hints = {.ai_family = afinfo->family}; 5172b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt unsigned int adcount = 0; 5182b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt struct addrinfo *res, *p; 5192b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt int ret; 5202b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 5212b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt ret = getaddrinfo(cb->arg, NULL, &hints, &res); 5222b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (ret < 0) 5232b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 5242b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt "getaddrinfo: %s\n", gai_strerror(ret)); 5252b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 526d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt memset(&cb->val.hmask, 0xFF, sizeof(cb->val.hmask)); 527d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; 528d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt 5292b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt for (p = res; p != NULL; p = p->ai_next) { 5302b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (adcount == 0) { 531d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt memset(&cb->val.haddr, 0, sizeof(cb->val.haddr)); 532d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt memcpy(&cb->val.haddr, 5332b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_host(p->ai_addr, p->ai_family), 5342b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_hostlen(p->ai_family)); 5352b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt ++adcount; 5362b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt continue; 5372b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt } 538d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt if (memcmp(&cb->val.haddr, 5392b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_host(p->ai_addr, p->ai_family), 5402b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xtables_sa_hostlen(p->ai_family)) != 0) 5412b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 5422b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt "%s resolves to more than one address\n", 5432b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt cb->arg); 5442b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt } 5452b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 5462b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt freeaddrinfo(res); 5472b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 5482b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt /* Validation in xtables_option_metavalidate */ 549d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt memcpy(XTOPT_MKPTR(cb), &cb->val.haddr, 550d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt sizeof(cb->val.haddr)); 5512b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt} 5522b01f706e7ba48d72e57f8e47457a86d9ed44992Jan Engelhardt 553b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt/** 554b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * @name: port name, or number as a string (e.g. "http" or "80") 555b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * 556b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * Resolve a port name to a number. Returns the port number in integral 557b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt * form on success, or <0 on error. (errno will not be set.) 558b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt */ 559b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardtstatic int xtables_getportbyname(const char *name) 560b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt{ 561b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt struct addrinfo *res = NULL, *p; 562b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt int ret; 563b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 564b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = getaddrinfo(NULL, name, NULL, &res); 565b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (ret < 0) 566b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt return -1; 567b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = -1; 568b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt for (p = res; p != NULL; p = p->ai_next) { 569b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (p->ai_family == AF_INET6) { 570b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = ((struct sockaddr_in6 *)p->ai_addr)->sin6_port; 571b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt break; 572b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } else if (p->ai_family == AF_INET) { 573b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = ((struct sockaddr_in *)p->ai_addr)->sin_port; 574b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt break; 575b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } 576b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt } 577b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt freeaddrinfo(res); 57844517bda3d8130638882f69478a8091316f30cbbJan Engelhardt if (ret < 0) 57944517bda3d8130638882f69478a8091316f30cbbJan Engelhardt return ret; 580b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt return ntohs(ret); 581b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt} 582b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 583b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt/** 584170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt * Validate and parse a protocol specification (number or name) by use of 585170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt * /etc/protocols and put the result into @cb->val.protocol. 586170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt */ 587170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardtstatic void xtopt_parse_protocol(struct xt_option_call *cb) 588170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt{ 58985f423addb46736e414f70b59c9f885e99aeb488Jan Engelhardt cb->val.protocol = xtables_parse_protocol(cb->arg); 590170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt if (cb->entry->flags & XTOPT_PUT) 591170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.protocol; 592170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt} 593170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt 594170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt/** 595d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * Validate and parse a port specification and put the result into 596d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * @cb->val.port. 597b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt */ 598b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardtstatic void xtopt_parse_port(struct xt_option_call *cb) 599b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt{ 600c02c92d1fcaa1223caf9a5eef32bedcb78f1e714Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 601b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt int ret; 602b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 603b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt ret = xtables_getportbyname(cb->arg); 604b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt if (ret < 0) 605b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 606b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt "Port \"%s\" does not resolve to anything.\n", 607b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt cb->arg); 608c02c92d1fcaa1223caf9a5eef32bedcb78f1e714Jan Engelhardt if (entry->flags & XTOPT_NBO) 609c02c92d1fcaa1223caf9a5eef32bedcb78f1e714Jan Engelhardt ret = htons(ret); 610b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt cb->val.port = ret; 611c02c92d1fcaa1223caf9a5eef32bedcb78f1e714Jan Engelhardt if (entry->flags & XTOPT_PUT) 612b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port; 613b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt} 614b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt 615f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardtstatic void xtopt_parse_mport(struct xt_option_call *cb) 616f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt{ 617f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt static const size_t esize = sizeof(uint16_t); 618f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 619f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt char *lo_arg, *wp_arg, *arg; 620f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt unsigned int maxiter; 621f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt int value; 622f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 623f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt wp_arg = lo_arg = strdup(cb->arg); 624f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (lo_arg == NULL) 625f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(RESOURCE_PROBLEM, "strdup"); 626f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 627f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt maxiter = entry->size / esize; 628f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (maxiter == 0) 629f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt maxiter = 2; /* ARRAY_SIZE(cb->val.port_range) */ 630f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (entry->size % esize != 0) 631f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " 632f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "not have proper size\n", __func__); 633f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 634f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[0] = 0; 635f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[1] = UINT16_MAX; 636f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->nvals = 0; 637f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 638f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt while ((arg = strsep(&wp_arg, ":")) != NULL) { 639f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (cb->nvals == maxiter) 640f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many " 641f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "components for option \"--%s\" (max: %u)\n", 642f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->ext_name, entry->name, maxiter); 643f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (*arg == '\0') { 644f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt ++cb->nvals; 645f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt continue; 646f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt } 647f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 648f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt value = xtables_getportbyname(arg); 649f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (value < 0) 650f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 651f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "Port \"%s\" does not resolve to " 652f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt "anything.\n", arg); 653c02c92d1fcaa1223caf9a5eef32bedcb78f1e714Jan Engelhardt if (entry->flags & XTOPT_NBO) 654f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt value = htons(value); 655f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (cb->nvals < ARRAY_SIZE(cb->val.port_range)) 656f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[cb->nvals] = value; 657f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt ++cb->nvals; 658f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt } 659f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 660f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (cb->nvals == 1) { 661f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt cb->val.port_range[1] = cb->val.port_range[0]; 662f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt ++cb->nvals; 663f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt } 664f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt if (entry->flags & XTOPT_PUT) 665f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt memcpy(XTOPT_MKPTR(cb), cb->val.port_range, sizeof(uint16_t) * 666f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt (cb->nvals <= maxiter ? cb->nvals : maxiter)); 667f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt free(lo_arg); 668f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt} 669f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt 67033e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayusostatic int xtopt_parse_mask(struct xt_option_call *cb) 67133e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso{ 67233e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso struct addrinfo hints = {.ai_family = afinfo->family, 67333e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso .ai_flags = AI_NUMERICHOST }; 67433e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso struct addrinfo *res; 67533e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso int ret; 67633e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso 67733e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso ret = getaddrinfo(cb->arg, NULL, &hints, &res); 67833e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso if (ret < 0) 67933e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso return 0; 68033e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso 68133e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso memcpy(&cb->val.hmask, xtables_sa_host(res->ai_addr, res->ai_family), 68233e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso xtables_sa_hostlen(res->ai_family)); 68333e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso 68433e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso switch(afinfo->family) { 68533e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso case AF_INET: 68633e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso cb->val.hlen = xtables_ipmask_to_cidr(&cb->val.hmask.in); 68733e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso break; 68833e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso case AF_INET6: 68933e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso cb->val.hlen = xtables_ip6mask_to_cidr(&cb->val.hmask.in6); 69033e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso break; 69133e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso } 69233e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso 69333e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso freeaddrinfo(res); 69433e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso return 1; 69533e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso} 69633e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso 697d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt/** 698d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt * Parse an integer and ensure it is within the address family's prefix length 699fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt * limits. The result is stored in @cb->val.hlen. 700d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt */ 701fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardtstatic void xtopt_parse_plen(struct xt_option_call *cb) 702e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt{ 703e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 704fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt unsigned int prefix_len = 128; /* happiness is a warm gcc */ 705e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt 706d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; 70733e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen)) { 70833e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso /* Is this mask expressed in full format? e.g. 255.255.255.0 */ 70933e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso if (xtopt_parse_mask(cb)) 71033e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso return; 71133e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso 712e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 713e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt "%s: bad value for option \"--%s\", " 71433e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso "neither a valid network mask " 71533e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso "nor valid CIDR (%u-%u).\n", 716d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt cb->ext_name, entry->name, 0, cb->val.hlen); 71733e262d4f80afcc464014f28012491bf0c5567efPablo Neira Ayuso } 718d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt cb->val.hlen = prefix_len; 719fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt} 720fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt 721fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt/** 722fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt * Reuse xtopt_parse_plen for testing the integer. Afterwards convert this to 723fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt * a bitmask, and make it available through @cb->val.hmask (hlen remains 724fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt * valid). If %XTOPT_PUT is used, hmask will be copied to the target area. 725fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt */ 726fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardtstatic void xtopt_parse_plenmask(struct xt_option_call *cb) 727fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt{ 728fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 729fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt uint32_t *mask = cb->val.hmask.all; 730fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt 731fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt xtopt_parse_plen(cb); 732fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt 733e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt memset(mask, 0xFF, sizeof(union nf_inet_addr)); 734d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt /* This shifting is AF-independent. */ 735fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt if (cb->val.hlen == 0) { 736e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[0] = mask[1] = mask[2] = mask[3] = 0; 737fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt } else if (cb->val.hlen <= 32) { 738fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt mask[0] <<= 32 - cb->val.hlen; 739e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[1] = mask[2] = mask[3] = 0; 740fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt } else if (cb->val.hlen <= 64) { 741fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt mask[1] <<= 32 - (cb->val.hlen - 32); 742e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[2] = mask[3] = 0; 743fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt } else if (cb->val.hlen <= 96) { 744fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt mask[2] <<= 32 - (cb->val.hlen - 64); 745e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[3] = 0; 746fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt } else if (cb->val.hlen <= 128) { 747fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt mask[3] <<= 32 - (cb->val.hlen - 96); 748e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt } 749e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[0] = htonl(mask[0]); 750e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[1] = htonl(mask[1]); 751e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[2] = htonl(mask[2]); 752e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt mask[3] = htonl(mask[3]); 753e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt if (entry->flags & XTOPT_PUT) 754e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt memcpy(XTOPT_MKPTR(cb), mask, sizeof(union nf_inet_addr)); 755e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt} 756e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt 75766266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardtstatic void xtopt_parse_hostmask(struct xt_option_call *cb) 75866266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt{ 75966266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt const char *orig_arg = cb->arg; 76066266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt char *work, *p; 76166266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt 76266266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt if (strchr(cb->arg, '/') == NULL) { 76366266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt xtopt_parse_host(cb); 76466266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt return; 76566266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt } 76666266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt work = strdup(orig_arg); 76766266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt if (work == NULL) 76866266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "strdup"); 76966266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt p = strchr(work, '/'); /* by def this can't be NULL now */ 77066266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt *p++ = '\0'; 77166266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt /* 77266266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt * Because xtopt_parse_host and xtopt_parse_plenmask would store 77366266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt * different things in the same target area, XTTYPE_HOSTMASK must 77466266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt * disallow XTOPT_PUT, which it does by forcing its absence, 77566266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt * cf. not being listed in xtopt_psize. 77666266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt */ 77766266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt cb->arg = work; 77866266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt xtopt_parse_host(cb); 77966266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt cb->arg = p; 78066266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt xtopt_parse_plenmask(cb); 78166266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt cb->arg = orig_arg; 78266266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt} 78366266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt 784cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardtstatic void xtopt_parse_ethermac(struct xt_option_call *cb) 785cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt{ 786cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt const char *arg = cb->arg; 787cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt unsigned int i; 788cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt char *end; 789cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt 790cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt for (i = 0; i < ARRAY_SIZE(cb->val.ethermac) - 1; ++i) { 791cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt cb->val.ethermac[i] = strtoul(arg, &end, 16); 79243896add0eb9c6bc94b7323e76f137d402e0f7feJan Engelhardt if (*end != ':' || end - arg > 2) 793cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt goto out; 794cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt arg = end + 1; 795cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt } 796cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt i = ARRAY_SIZE(cb->val.ethermac) - 1; 797cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt cb->val.ethermac[i] = strtoul(arg, &end, 16); 79843896add0eb9c6bc94b7323e76f137d402e0f7feJan Engelhardt if (*end != '\0' || end - arg > 2) 799cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt goto out; 800cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt if (cb->entry->flags & XTOPT_PUT) 801cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt memcpy(XTOPT_MKPTR(cb), cb->val.ethermac, 802cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt sizeof(cb->val.ethermac)); 803cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt return; 804cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt out: 805cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, "ether"); 806cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt} 807cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt 808aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void (*const xtopt_subparse[])(struct xt_option_call *) = { 809dfe99f1bf291b4b954d3608dbe95a43e16a8bb49Jan Engelhardt [XTTYPE_UINT8] = xtopt_parse_int, 8100eff54bd407aae6b99c3b189d356929e399b5a38Jan Engelhardt [XTTYPE_UINT16] = xtopt_parse_int, 811a93142d5f55db74ebd7d49be9bd88f7a499ded40Jan Engelhardt [XTTYPE_UINT32] = xtopt_parse_int, 8128b5bdea659f1fb86b3288a2568ab104a90b914e5Jan Engelhardt [XTTYPE_UINT64] = xtopt_parse_int, 8138bf513ada0aae0e4b1ac5160113fc532c2f525d0Jan Engelhardt [XTTYPE_UINT8RC] = xtopt_parse_mint, 814564eaf48e14411803a353206eefbb89d525c63ffJan Engelhardt [XTTYPE_UINT16RC] = xtopt_parse_mint, 81504bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt [XTTYPE_UINT32RC] = xtopt_parse_mint, 816bc438c4cbdab09fafbbceecddd54e44e4234a4a1Jan Engelhardt [XTTYPE_UINT64RC] = xtopt_parse_mint, 817f012b3c9190cd95ac170072f759a97575613ea07Jan Engelhardt [XTTYPE_DOUBLE] = xtopt_parse_float, 8184a0a17620017c1f45946b2cde7139ef18ea3d93cJan Engelhardt [XTTYPE_STRING] = xtopt_parse_string, 81961cc52b6f9edfa3efb1d0c9ea9531abb42828ec2Jan Engelhardt [XTTYPE_TOSMASK] = xtopt_parse_tosmask, 820d25e217578492d17f7752bf77cfab5f2c2509795Jan Engelhardt [XTTYPE_MARKMASK32] = xtopt_parse_markmask, 82141a4cea0f4109fb76762dca073c3c1217658ee06Jan Engelhardt [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, 822d7282413763b0ba85d512c1cd49174b762ff449cJan Engelhardt [XTTYPE_HOST] = xtopt_parse_host, 82366266abd17adc9631f3769ef0b82968c0bac6f38Jan Engelhardt [XTTYPE_HOSTMASK] = xtopt_parse_hostmask, 824170cf49a630fd0d237818b537c01794dde00b07aJan Engelhardt [XTTYPE_PROTOCOL] = xtopt_parse_protocol, 825b8592fa3352018646b0befaa48f930f75c5b7d92Jan Engelhardt [XTTYPE_PORT] = xtopt_parse_port, 826f30231a02e145020fb47524f9a0daeb498a4f7d0Jan Engelhardt [XTTYPE_PORTRC] = xtopt_parse_mport, 827fa9b759bacc0ad6a093892ef508811e7feb981b0Jan Engelhardt [XTTYPE_PLEN] = xtopt_parse_plen, 828e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2Jan Engelhardt [XTTYPE_PLENMASK] = xtopt_parse_plenmask, 829cb225e26856accf5661dcbc3cf34d7f77b2f0c36Jan Engelhardt [XTTYPE_ETHERMAC] = xtopt_parse_ethermac, 830aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt}; 831aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 832aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 833aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * The master option parsing routine. May be used for the ".x6_parse" 834aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * function pointer in extensions if fully automatic parsing is desired. 835aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * It may be also called manually from a custom x6_parse function. 836aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 837aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_parse(struct xt_option_call *cb) 838aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 839aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry = cb->entry; 840aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int eflag = 1 << cb->entry->id; 841aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 842aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 843aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use 844aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * prevention. Though it turned out that this is too much typing (most 845aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * of the options are one-time use only), so now we also have 846aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * %XTOPT_MULTI. 847aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 848aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) && 849aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->xflags & eflag) 850aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 851aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" can only be used once.\n", 852aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, cb->entry->name); 853aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb->invert && !(entry->flags & XTOPT_INVERT)) 854aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 855aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" cannot be inverted.\n", 856aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, entry->name); 857aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type != XTTYPE_NONE && optarg == NULL) 858aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 859aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" requires an argument.\n", 860aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->ext_name, entry->name); 861fdb2a27825e558393fb715374c07873830d4d149Jan Engelhardt /* 862fdb2a27825e558393fb715374c07873830d4d149Jan Engelhardt * Fill in fallback value for "nvals", in case an extension (as it 863fdb2a27825e558393fb715374c07873830d4d149Jan Engelhardt * happened with libxt_conntrack.2) tries to read it, despite not using 864fdb2a27825e558393fb715374c07873830d4d149Jan Engelhardt * a *RC option type. 865fdb2a27825e558393fb715374c07873830d4d149Jan Engelhardt */ 866fdb2a27825e558393fb715374c07873830d4d149Jan Engelhardt cb->nvals = 1; 867aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->type <= ARRAY_SIZE(xtopt_subparse) && 868aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_subparse[entry->type] != NULL) 869aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_subparse[entry->type](cb); 870aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Exclusion with other flags tested later in finalize. */ 871aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb->xflags |= 1 << entry->id; 872aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 873aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 874aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 875aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Verifies that an extension's option map descriptor is valid, and ought to 876aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * be called right after the extension has been loaded, and before option 877aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * merging/xfrm. 878aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 879aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_metavalidate(const char *name, 880aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry) 881aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 882aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (; entry->name != NULL; ++entry) { 883aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id >= CHAR_BIT * sizeof(unsigned int) || 884aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt entry->id >= XT_OPTION_OFFSET_SCALE) 885aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 886aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension %s uses invalid ID %u\n", 887aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->id); 888735f3d76ccd3a7deab13703d7c227c87c666a97bJan Engelhardt if (!(entry->flags & XTOPT_PUT)) { 889735f3d76ccd3a7deab13703d7c227c87c666a97bJan Engelhardt if (entry->ptroff != 0) 890735f3d76ccd3a7deab13703d7c227c87c666a97bJan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 891735f3d76ccd3a7deab13703d7c227c87c666a97bJan Engelhardt "%s: ptroff for \"--%s\" is non-" 892735f3d76ccd3a7deab13703d7c227c87c666a97bJan Engelhardt "zero but no XTOPT_PUT is specified. " 893735f3d76ccd3a7deab13703d7c227c87c666a97bJan Engelhardt "Oversight?", name, entry->name); 894aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 895735f3d76ccd3a7deab13703d7c227c87c666a97bJan Engelhardt } 896269cbfd30aac18c1fd251be83430dabc60abee0cJan Engelhardt if (entry->type >= ARRAY_SIZE(xtopt_psize) || 897269cbfd30aac18c1fd251be83430dabc60abee0cJan Engelhardt xtopt_psize[entry->type] == 0) 898aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 899aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: entry type of option \"--%s\" cannot be " 900aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "combined with XTOPT_PUT\n", 901aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name); 90204bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt if (xtopt_psize[entry->type] != -1 && 90304bb988275ac76815a15788a7fc75ac78f3bb833Jan Engelhardt xtopt_psize[entry->type] != entry->size) 904aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(OTHER_PROBLEM, 905aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" points to a memory block " 906aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "of wrong size (expected %zu, got %zu)\n", 907aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, 908aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtopt_psize[entry->type], entry->size); 909aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 910aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 911aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 912aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 913aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Find an option entry by its id. 914aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 915aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic const struct xt_option_entry * 916aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_lookup(const struct xt_option_entry *entry, unsigned int id) 917aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 918aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (; entry->name != NULL; ++entry) 919aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id == id) 920aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return entry; 921aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return NULL; 922aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 923aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 924aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 925aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c: getopt id (i.e. with offset) 926aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw: struct ipt_entry or ip6t_entry 927aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 928aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the 929aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API. 930aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 931aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_tpcall(unsigned int c, char **argv, bool invert, 932aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xtables_target *t, void *fw) 933aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 934aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xt_option_call cb; 935aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 936aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (t->x6_parse == NULL) { 937aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (t->parse != NULL) 938aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->parse(c - t->option_offset, argv, invert, 939aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt &t->tflags, fw, &t->t); 940aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 941aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 942aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 943aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt c -= t->option_offset; 944aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.entry = xtables_option_lookup(t->x6_options, c); 945aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb.entry == NULL) 946aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_error(OTHER_PROBLEM, 947aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension does not know id %u\n", c); 948aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.arg = optarg; 949aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.invert = invert; 950aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.ext_name = t->name; 951aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.data = t->t->data; 952aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.xflags = t->tflags; 95333d180871bea281a448efd0c1a49517318162382Jan Engelhardt cb.target = &t->t; 95487a34d7aef2cba833f4f36536575dee304bbece5Jan Engelhardt cb.xt_entry = fw; 9552dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt cb.udata = t->udata; 956aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->x6_parse(&cb); 957aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt t->tflags = cb.xflags; 958aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 959aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 960aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 961aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @c: getopt id (i.e. with offset) 962aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @fw: struct ipt_entry or ip6t_entry 963aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 964aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Dispatch arguments to the appropriate parse function, based upon the 965aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * extension's choice of API. 966aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 967aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_option_mpcall(unsigned int c, char **argv, bool invert, 968aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xtables_match *m, void *fw) 969aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 970aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt struct xt_option_call cb; 971aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 972aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (m->x6_parse == NULL) { 973aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (m->parse != NULL) 974aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->parse(c - m->option_offset, argv, invert, 975aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt &m->mflags, fw, &m->m); 976aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 977aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 978aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 979aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt c -= m->option_offset; 980aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.entry = xtables_option_lookup(m->x6_options, c); 981aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (cb.entry == NULL) 982aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_error(OTHER_PROBLEM, 983aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "Extension does not know id %u\n", c); 984aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.arg = optarg; 985aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.invert = invert; 986aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.ext_name = m->name; 987aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.data = m->m->data; 988aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt cb.xflags = m->mflags; 98933d180871bea281a448efd0c1a49517318162382Jan Engelhardt cb.match = &m->m; 99087a34d7aef2cba833f4f36536575dee304bbece5Jan Engelhardt cb.xt_entry = fw; 9912dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt cb.udata = m->udata; 992aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->x6_parse(&cb); 993aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt m->mflags = cb.xflags; 994aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 995aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 996aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 997aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name: name of extension 998aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry: current option (from all ext's entries) being validated 999aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags: flags the extension has collected 1000aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @i: conflicting option (id) to test for 1001aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 1002aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtstatic void 1003aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtxtables_option_fcheck2(const char *name, const struct xt_option_entry *entry, 1004aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *other, 1005aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int xflags) 1006aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 1007aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int ef = 1 << entry->id, of = 1 << other->id; 1008aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 1009aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->also & of && !(xflags & of)) 1010aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 1011aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" also requires \"--%s\".\n", 1012aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, other->name); 1013aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 1014aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (!(entry->excl & of)) 1015aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Use of entry does not collide with other option, good. */ 1016aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 1017aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if ((xflags & (ef | of)) != (ef | of)) 1018aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* Conflicting options were not used. */ 1019aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt return; 1020aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 1021aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 1022aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" cannot be used together with \"--%s\".\n", 1023aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name, other->name); 1024aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 1025aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 1026aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt/** 1027aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @name: name of extension 1028aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @xflags: accumulated flags 1029aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * @entry: extension's option table 1030aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * 1031aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Check that all option constraints have been met. This effectively replaces 1032aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * ->final_check of the older API. 1033aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 1034aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtvoid xtables_options_fcheck(const char *name, unsigned int xflags, 1035aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *table) 1036aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt{ 1037aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt const struct xt_option_entry *entry, *other; 1038aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt unsigned int i; 1039aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 1040aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (entry = table; entry->name != NULL; ++entry) { 1041aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->flags & XTOPT_MAND && 1042aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt !(xflags & (1 << entry->id))) 1043aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 1044aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt "%s: option \"--%s\" must be specified\n", 1045aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt name, entry->name); 1046ab847dfe38529d2aa67cc8178a54d5b45af11cfaJan Engelhardt if (!(xflags & (1 << entry->id))) 1047ab847dfe38529d2aa67cc8178a54d5b45af11cfaJan Engelhardt /* Not required, not specified, thus skip. */ 1048ab847dfe38529d2aa67cc8178a54d5b45af11cfaJan Engelhardt continue; 1049aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt 1050aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) { 1051aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (entry->id == i) 1052aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt /* 1053aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * Avoid conflict with self. Multi-use check 1054aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt * was done earlier in xtables_option_parse. 1055aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt */ 1056aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 1057aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt other = xtables_option_lookup(table, i); 1058aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (other == NULL) 1059aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt continue; 1060aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_option_fcheck2(name, entry, other, xflags); 1061aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 1062aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt } 1063aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt} 10643af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 10653af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/** 10663af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the 10673af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API. 10683af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */ 10693af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_tfcall(struct xtables_target *t) 10703af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{ 10713af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (t->x6_fcheck != NULL) { 10723af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt struct xt_fcheck_call cb; 10733af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 10743af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.ext_name = t->name; 10753af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.data = t->t->data; 10763af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.xflags = t->tflags; 10772dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt cb.udata = t->udata; 10783af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt t->x6_fcheck(&cb); 10793af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } else if (t->final_check != NULL) { 10803af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt t->final_check(t->tflags); 10813af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } 10823af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (t->x6_options != NULL) 10833af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt xtables_options_fcheck(t->name, t->tflags, t->x6_options); 10843af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt} 10853af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 10863af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt/** 10873af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * Dispatch arguments to the appropriate final_check function, based upon the 10883af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt * extension's choice of API. 10893af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt */ 10903af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardtvoid xtables_option_mfcall(struct xtables_match *m) 10913af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt{ 10923af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (m->x6_fcheck != NULL) { 10933af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt struct xt_fcheck_call cb; 10943af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt 10953af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.ext_name = m->name; 10963af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.data = m->m->data; 10973af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt cb.xflags = m->mflags; 10982dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt cb.udata = m->udata; 10993af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt m->x6_fcheck(&cb); 11003af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } else if (m->final_check != NULL) { 11013af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt m->final_check(m->mflags); 11023af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt } 11033af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt if (m->x6_options != NULL) 11043af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt xtables_options_fcheck(m->name, m->mflags, m->x6_options); 11053af739b0e7c3b6dcc986645c57c982d0add5006bJan Engelhardt} 11062e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11072e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtstruct xtables_lmap *xtables_lmap_init(const char *file) 11082e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 11092e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this; 11102e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt char buf[512]; 11112e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt FILE *fp; 11122e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt char *cur, *nxt; 11132e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt int id; 11142e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11152e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt fp = fopen(file, "re"); 11162e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (fp == NULL) 11172e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 11182e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11192e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (fgets(buf, sizeof(buf), fp) != NULL) { 11202e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt cur = buf; 11212e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (isspace(*cur)) 11222e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++cur; 11232e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (*cur == '#' || *cur == '\n' || *cur == '\0') 11242e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 11252e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11262e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* iproute2 allows hex and dec format */ 11272e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt errno = 0; 11282e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10); 11292e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (nxt == cur || errno != 0) 11302e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 11312e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11322e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* same boundaries as in iproute2 */ 11332e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (id < 0 || id > 255) 11342e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 11352e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt cur = nxt; 11362e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11372e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (!isspace(*cur)) 11382e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 11392e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (isspace(*cur)) 11402e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++cur; 11412e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (*cur == '#' || *cur == '\n' || *cur == '\0') 11422e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 11432e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt nxt = cur; 11442e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt while (*nxt != '\0' && !isspace(*nxt)) 11452e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt ++nxt; 11462e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (nxt == cur) 11472e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt continue; 11482e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt *nxt = '\0'; 11492e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11502e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt /* found valid data */ 11512e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this = malloc(sizeof(*lmap_this)); 11522e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_this == NULL) { 11532e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt perror("malloc"); 11542e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt goto out; 11552e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 11562e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->id = id; 11572e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->name = strdup(cur); 11582e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_this->name == NULL) { 11592e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(lmap_this); 11602e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt goto out; 11612e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 11622e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_this->next = NULL; 11632e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11642e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (lmap_prev != NULL) 11652e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_prev->next = lmap_this; 11662e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt else 11672e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_head = lmap_this; 11682e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt lmap_prev = lmap_this; 11692e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 11702e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11712e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt fclose(fp); 11722e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return lmap_head; 11732e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt out: 1174e5152bf4ebd4f573ae1d0770044e2bff7ab66d5eThomas Jarosch fclose(fp); 11752e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt xtables_lmap_free(lmap_head); 11762e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 11772e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 11782e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11792e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtvoid xtables_lmap_free(struct xtables_lmap *head) 11802e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 11812e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt struct xtables_lmap *next; 11822e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11832e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = next) { 11842e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt next = head->next; 11852e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(head->name); 11862e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt free(head); 11872e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt } 11882e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 11892e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11902e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtint xtables_lmap_name2id(const struct xtables_lmap *head, const char *name) 11912e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 11922e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = head->next) 11932e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (strcmp(head->name, name) == 0) 11942e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return head->id; 11952e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return -1; 11962e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 11972e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt 11982e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardtconst char *xtables_lmap_id2name(const struct xtables_lmap *head, int id) 11992e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt{ 12002e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt for (; head != NULL; head = head->next) 12012e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt if (head->id == id) 12022e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return head->name; 12032e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt return NULL; 12042e0ec4fa0fb5162c441cd666f55fe76777e40d5eJan Engelhardt} 1205