libiptc.c revision 2a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bc
12a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson/* Library which manipulates firewall rules. Version $Revision: 1.54 $ */ 2e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 3e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Architecture of firewall rules is as follows: 4e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * 5e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Chains go INPUT, FORWARD, OUTPUT then user chains. 6e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Each user chain starts with an ERROR node. 7e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Every chain ends with an unconditional jump: a RETURN for user chains, 8e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * and a POLICY for built-ins. 9e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher */ 10e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 113ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte/* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See 123ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte * COPYING for details). 13aae69bed019826ddec93f761514652a93d871e49Harald Welte * (C) 2000-2004 by the Netfilter Core Team <coreteam@netfilter.org> 143ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte * 15fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte * 2003-Jun-20: Harald Welte <laforge@netfilter.org>: 163ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte * - Reimplementation of chain cache to use offsets instead of entries 17fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte * 2003-Jun-23: Harald Welte <laforge@netfilter.org>: 180113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * - performance optimization, sponsored by Astaro AG (http://www.astaro.com/) 19fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte * don't rebuild the chain cache after every operation, instead fix it 20fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte * up after a ruleset change. 21aae69bed019826ddec93f761514652a93d871e49Harald Welte * 2004-Aug-18: Harald Welte <laforge@netfilter.org>: 22aae69bed019826ddec93f761514652a93d871e49Harald Welte * - futher performance work: total reimplementation of libiptc. 23aae69bed019826ddec93f761514652a93d871e49Harald Welte * - libiptc now has a real internal (linked-list) represntation of the 24aae69bed019826ddec93f761514652a93d871e49Harald Welte * ruleset and a parser/compiler from/to this internal representation 25aae69bed019826ddec93f761514652a93d871e49Harald Welte * - again sponsored by Astaro AG (http://www.astaro.com/) 263ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte */ 2715920d160760535e51a57b3834eba45257cfa6d8Harald Welte#include <sys/types.h> 2815920d160760535e51a57b3834eba45257cfa6d8Harald Welte#include <sys/socket.h> 297cd002826d0f329620cb738bc4dc4760ef5e084aStephane Ouellette 30aae69bed019826ddec93f761514652a93d871e49Harald Welte#include "linux_list.h" 31aae69bed019826ddec93f761514652a93d871e49Harald Welte 32aae69bed019826ddec93f761514652a93d871e49Harald Welte//#define IPTC_DEBUG2 1 33aae69bed019826ddec93f761514652a93d871e49Harald Welte 34aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 35aae69bed019826ddec93f761514652a93d871e49Harald Welte#include <fcntl.h> 36aae69bed019826ddec93f761514652a93d871e49Harald Welte#define DEBUGP(x, args...) fprintf(stderr, "%s: " x, __FUNCTION__, ## args) 37aae69bed019826ddec93f761514652a93d871e49Harald Welte#define DEBUGP_C(x, args...) fprintf(stderr, x, ## args) 38aae69bed019826ddec93f761514652a93d871e49Harald Welte#else 39aae69bed019826ddec93f761514652a93d871e49Harald Welte#define DEBUGP(x, args...) 40aae69bed019826ddec93f761514652a93d871e49Harald Welte#define DEBUGP_C(x, args...) 41aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 42aae69bed019826ddec93f761514652a93d871e49Harald Welte 43e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#ifndef IPT_LIB_DIR 44e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#define IPT_LIB_DIR "/usr/local/lib/iptables" 45e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#endif 46e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 470113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte#ifndef __OPTIMIZE__ 480113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald WelteSTRUCT_ENTRY_TARGET * 490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald WelteGET_TARGET(STRUCT_ENTRY *e) 500113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return (void *)e + e->target_offset; 520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte#endif 540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 55e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int sockfd = -1; 56e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void *iptc_fn = NULL; 57e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 58e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic const char *hooknames[] 5979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell= { [HOOK_PRE_ROUTING] "PREROUTING", 6079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_LOCAL_IN] "INPUT", 6179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_FORWARD] "FORWARD", 6279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_LOCAL_OUT] "OUTPUT", 6310758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell [HOOK_POST_ROUTING] "POSTROUTING", 6410758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell#ifdef HOOK_DROPPING 6510758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell [HOOK_DROPPING] "DROPPING" 6610758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell#endif 67e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 68e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 69aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Convenience structures */ 70aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct ipt_error_target 71aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 72aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY_TARGET t; 73aae69bed019826ddec93f761514652a93d871e49Harald Welte char error[TABLE_MAXNAMELEN]; 74aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 75aae69bed019826ddec93f761514652a93d871e49Harald Welte 76aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct chain_head; 77aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct rule_head; 78aae69bed019826ddec93f761514652a93d871e49Harald Welte 79e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstruct counter_map 80e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 81e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher enum { 82e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_NOMAP, 83e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_NORMAL_MAP, 841cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte COUNTER_MAP_ZEROED, 851cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte COUNTER_MAP_SET 86e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } maptype; 87e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int mappos; 88e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 89e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 90aae69bed019826ddec93f761514652a93d871e49Harald Welteenum iptcc_rule_type { 91aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_STANDARD, /* standard target (ACCEPT, ...) */ 92aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_MODULE, /* extension module (SNAT, ...) */ 93aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_FALLTHROUGH, /* fallthrough rule */ 94aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_JUMP, /* jump to other chain */ 95aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 96aae69bed019826ddec93f761514652a93d871e49Harald Welte 97aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct rule_head 98e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 99aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head list; 100aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *chain; 101aae69bed019826ddec93f761514652a93d871e49Harald Welte struct counter_map counter_map; 102aae69bed019826ddec93f761514652a93d871e49Harald Welte 103aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index; /* index (needed for counter_map) */ 104aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset; /* offset in rule blob */ 105aae69bed019826ddec93f761514652a93d871e49Harald Welte 106aae69bed019826ddec93f761514652a93d871e49Harald Welte enum iptcc_rule_type type; 107aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *jump; /* jump target, if IPTCC_R_JUMP */ 108aae69bed019826ddec93f761514652a93d871e49Harald Welte 109aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int size; /* size of entry data */ 110aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY entry[0]; 111e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 112e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 113aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct chain_head 11430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 115aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head list; 11679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell char name[TABLE_MAXNAMELEN]; 117aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int hooknum; /* hook number+1 if builtin */ 118aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int references; /* how many jumps reference us */ 119aae69bed019826ddec93f761514652a93d871e49Harald Welte int verdict; /* verdict if builtin */ 120aae69bed019826ddec93f761514652a93d871e49Harald Welte 121aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS counters; /* per-chain counters */ 122aae69bed019826ddec93f761514652a93d871e49Harald Welte struct counter_map counter_map; 123aae69bed019826ddec93f761514652a93d871e49Harald Welte 124aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int num_rules; /* number of rules in list */ 125aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head rules; /* list of rules */ 126aae69bed019826ddec93f761514652a93d871e49Harald Welte 127aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index; /* index (needed for jump resolval) */ 128aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int head_offset; /* offset in rule blob */ 129aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int foot_index; /* index (needed for counter_map) */ 130aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int foot_offset; /* offset in rule blob */ 13130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell}; 13230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 13379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellSTRUCT_TC_HANDLE 134e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 135aae69bed019826ddec93f761514652a93d871e49Harald Welte int changed; /* Have changes been made? */ 136aae69bed019826ddec93f761514652a93d871e49Harald Welte 137aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head chains; 138aae69bed019826ddec93f761514652a93d871e49Harald Welte 139aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *chain_iterator_cur; 140aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *rule_iterator_cur; 141aae69bed019826ddec93f761514652a93d871e49Harald Welte 14279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 143aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_GET_ENTRIES *entries; 144aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 145e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 146aae69bed019826ddec93f761514652a93d871e49Harald Welte/* allocate a new chain head for the cache */ 147aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct chain_head *iptcc_alloc_chain_head(const char *name, int hooknum) 148aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 149aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = malloc(sizeof(*c)); 150aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) 151aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 152aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(c, 0, sizeof(*c)); 153aae69bed019826ddec93f761514652a93d871e49Harald Welte 154aae69bed019826ddec93f761514652a93d871e49Harald Welte strncpy(c->name, name, TABLE_MAXNAMELEN); 155aae69bed019826ddec93f761514652a93d871e49Harald Welte c->hooknum = hooknum; 156aae69bed019826ddec93f761514652a93d871e49Harald Welte INIT_LIST_HEAD(&c->rules); 157e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 158aae69bed019826ddec93f761514652a93d871e49Harald Welte return c; 159aae69bed019826ddec93f761514652a93d871e49Harald Welte} 16030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 161aae69bed019826ddec93f761514652a93d871e49Harald Welte/* allocate and initialize a new rule for the cache */ 162aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct rule_head *iptcc_alloc_rule(struct chain_head *c, unsigned int size) 163aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 164aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r = malloc(sizeof(*r)+size); 165aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!r) 166aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 167aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(r, 0, sizeof(*r)); 16830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 169aae69bed019826ddec93f761514652a93d871e49Harald Welte r->chain = c; 170aae69bed019826ddec93f761514652a93d871e49Harald Welte r->size = size; 171175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 172aae69bed019826ddec93f761514652a93d871e49Harald Welte return r; 173aae69bed019826ddec93f761514652a93d871e49Harald Welte} 174e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 175aae69bed019826ddec93f761514652a93d871e49Harald Welte/* notify us that the ruleset has been modified by the user */ 176175f64177743e5a417e98d483ef995bf7151f3bcRusty Russellstatic void 17779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellset_changed(TC_HANDLE_T h) 178175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell{ 179175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell h->changed = 1; 180175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell} 181175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 182380ba5f3074a16fbaa8869d9594962d58b5f8608Harald Welte#ifdef IPTC_DEBUG 18379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic void do_check(TC_HANDLE_T h, unsigned int line); 184849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell#define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0) 18530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#else 18630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#define CHECK(h) 18730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#endif 188e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 189aae69bed019826ddec93f761514652a93d871e49Harald Welte 190aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 191aae69bed019826ddec93f761514652a93d871e49Harald Welte * iptc blob utility functions (iptcb_*) 192aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 193aae69bed019826ddec93f761514652a93d871e49Harald Welte 194e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 195aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_get_number(const STRUCT_ENTRY *i, 19679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *seek, 197e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int *pos) 198e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 199e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (i == seek) 200e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 201e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*pos)++; 202e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 203e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 204e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 205aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int 206aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_get_entry_n(STRUCT_ENTRY *i, 207aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int number, 208aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int *pos, 209aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY **pe) 210aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 211aae69bed019826ddec93f761514652a93d871e49Harald Welte if (*pos == number) { 212aae69bed019826ddec93f761514652a93d871e49Harald Welte *pe = i; 213aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 214aae69bed019826ddec93f761514652a93d871e49Harald Welte } 215aae69bed019826ddec93f761514652a93d871e49Harald Welte (*pos)++; 216aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 217aae69bed019826ddec93f761514652a93d871e49Harald Welte} 218aae69bed019826ddec93f761514652a93d871e49Harald Welte 219aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline STRUCT_ENTRY * 220aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_get_entry(TC_HANDLE_T h, unsigned int offset) 221aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 222aae69bed019826ddec93f761514652a93d871e49Harald Welte return (STRUCT_ENTRY *)((char *)h->entries->entrytable + offset); 223aae69bed019826ddec93f761514652a93d871e49Harald Welte} 224aae69bed019826ddec93f761514652a93d871e49Harald Welte 225e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic unsigned int 226aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_entry2index(const TC_HANDLE_T h, const STRUCT_ENTRY *seek) 227e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 228e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int pos = 0; 229e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 230aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 231aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcb_get_number, seek, &pos) == 0) { 232a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson fprintf(stderr, "ERROR: offset %u not an entry!\n", 233aae69bed019826ddec93f761514652a93d871e49Harald Welte (unsigned int)((char *)seek - (char *)h->entries->entrytable)); 234e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 235e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 236e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return pos; 237e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 238e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 239aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline STRUCT_ENTRY * 240aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_offset2entry(TC_HANDLE_T h, unsigned int offset) 241e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 242aae69bed019826ddec93f761514652a93d871e49Harald Welte return (STRUCT_ENTRY *) ((void *)h->entries->entrytable+offset); 243aae69bed019826ddec93f761514652a93d871e49Harald Welte} 244aae69bed019826ddec93f761514652a93d871e49Harald Welte 245aae69bed019826ddec93f761514652a93d871e49Harald Welte 246aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline unsigned long 247aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_entry2offset(const TC_HANDLE_T h, const STRUCT_ENTRY *e) 248aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 249aae69bed019826ddec93f761514652a93d871e49Harald Welte return (void *)e - (void *)h->entries->entrytable; 250aae69bed019826ddec93f761514652a93d871e49Harald Welte} 251aae69bed019826ddec93f761514652a93d871e49Harald Welte 252aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline unsigned int 253aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_offset2index(const TC_HANDLE_T h, unsigned int offset) 254aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 255aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcb_entry2index(h, iptcb_offset2entry(h, offset)); 256aae69bed019826ddec93f761514652a93d871e49Harald Welte} 257aae69bed019826ddec93f761514652a93d871e49Harald Welte 258aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns 0 if not hook entry, else hooknumber + 1 */ 259aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline unsigned int 260aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_ent_is_hook_entry(STRUCT_ENTRY *e, TC_HANDLE_T h) 261aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 262aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int i; 263aae69bed019826ddec93f761514652a93d871e49Harald Welte 264aae69bed019826ddec93f761514652a93d871e49Harald Welte for (i = 0; i < NUMHOOKS; i++) { 265aae69bed019826ddec93f761514652a93d871e49Harald Welte if ((h->info.valid_hooks & (1 << i)) 266aae69bed019826ddec93f761514652a93d871e49Harald Welte && iptcb_get_entry(h, h->info.hook_entry[i]) == e) 267aae69bed019826ddec93f761514652a93d871e49Harald Welte return i+1; 268aae69bed019826ddec93f761514652a93d871e49Harald Welte } 269aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 270aae69bed019826ddec93f761514652a93d871e49Harald Welte} 271aae69bed019826ddec93f761514652a93d871e49Harald Welte 272aae69bed019826ddec93f761514652a93d871e49Harald Welte 273aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 274aae69bed019826ddec93f761514652a93d871e49Harald Welte * iptc cache utility functions (iptcc_*) 275aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 276aae69bed019826ddec93f761514652a93d871e49Harald Welte 277aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Is the given chain builtin (1) or user-defined (0) */ 278aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic unsigned int iptcc_is_builtin(struct chain_head *c) 279aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 280aae69bed019826ddec93f761514652a93d871e49Harald Welte return (c->hooknum ? 1 : 0); 281aae69bed019826ddec93f761514652a93d871e49Harald Welte} 282aae69bed019826ddec93f761514652a93d871e49Harald Welte 283aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Get a specific rule within a chain */ 284aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct rule_head *iptcc_get_rule_num(struct chain_head *c, 285aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int rulenum) 286aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 287aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 288aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int num = 0; 289aae69bed019826ddec93f761514652a93d871e49Harald Welte 290aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 291aae69bed019826ddec93f761514652a93d871e49Harald Welte num++; 292aae69bed019826ddec93f761514652a93d871e49Harald Welte if (num == rulenum) 293aae69bed019826ddec93f761514652a93d871e49Harald Welte return r; 294aae69bed019826ddec93f761514652a93d871e49Harald Welte } 295aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 296aae69bed019826ddec93f761514652a93d871e49Harald Welte} 297aae69bed019826ddec93f761514652a93d871e49Harald Welte 298aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns chain head if found, otherwise NULL. */ 299aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct chain_head * 300aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_find_chain_by_offset(TC_HANDLE_T handle, unsigned int offset) 301aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 302aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head *pos; 303aae69bed019826ddec93f761514652a93d871e49Harald Welte 304aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&handle->chains)) 305aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 306aae69bed019826ddec93f761514652a93d871e49Harald Welte 307aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each(pos, &handle->chains) { 308aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = list_entry(pos, struct chain_head, list); 309aae69bed019826ddec93f761514652a93d871e49Harald Welte if (offset >= c->head_offset && offset <= c->foot_offset) 310aae69bed019826ddec93f761514652a93d871e49Harald Welte return c; 311aae69bed019826ddec93f761514652a93d871e49Harald Welte } 312aae69bed019826ddec93f761514652a93d871e49Harald Welte 313aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 314aae69bed019826ddec93f761514652a93d871e49Harald Welte} 315aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns chain head if found, otherwise NULL. */ 316aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct chain_head * 317aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_find_label(const char *name, TC_HANDLE_T handle) 318aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 319aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head *pos; 320aae69bed019826ddec93f761514652a93d871e49Harald Welte 321aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&handle->chains)) 322aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 323aae69bed019826ddec93f761514652a93d871e49Harald Welte 324aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each(pos, &handle->chains) { 325aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = list_entry(pos, struct chain_head, list); 326aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!strcmp(c->name, name)) 327aae69bed019826ddec93f761514652a93d871e49Harald Welte return c; 328aae69bed019826ddec93f761514652a93d871e49Harald Welte } 329aae69bed019826ddec93f761514652a93d871e49Harald Welte 330aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 331aae69bed019826ddec93f761514652a93d871e49Harald Welte} 332aae69bed019826ddec93f761514652a93d871e49Harald Welte 333aae69bed019826ddec93f761514652a93d871e49Harald Welte/* called when rule is to be removed from cache */ 334aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void iptcc_delete_rule(struct rule_head *r) 335aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 336aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("deleting rule %p (offset %u)\n", r, r->offset); 337aae69bed019826ddec93f761514652a93d871e49Harald Welte /* clean up reference count of called chain */ 338aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type == IPTCC_R_JUMP 339aae69bed019826ddec93f761514652a93d871e49Harald Welte && r->jump) 340aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump->references--; 341aae69bed019826ddec93f761514652a93d871e49Harald Welte 342aae69bed019826ddec93f761514652a93d871e49Harald Welte list_del(&r->list); 343aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 344aae69bed019826ddec93f761514652a93d871e49Harald Welte} 345aae69bed019826ddec93f761514652a93d871e49Harald Welte 346aae69bed019826ddec93f761514652a93d871e49Harald Welte 347aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 348aae69bed019826ddec93f761514652a93d871e49Harald Welte * RULESET PARSER (blob -> cache) 349aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 350aae69bed019826ddec93f761514652a93d871e49Harald Welte 351aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int alphasort(const void *a, const void *b) 352aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 353aae69bed019826ddec93f761514652a93d871e49Harald Welte return strcmp(((struct chain_head *)a)->name, 354aae69bed019826ddec93f761514652a93d871e49Harald Welte ((struct chain_head *)b)->name); 355aae69bed019826ddec93f761514652a93d871e49Harald Welte} 356aae69bed019826ddec93f761514652a93d871e49Harald Welte 357aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Delete policy rule of previous chain, since cache doesn't contain 358aae69bed019826ddec93f761514652a93d871e49Harald Welte * chain policy rules. 359aae69bed019826ddec93f761514652a93d871e49Harald Welte * WARNING: This function has ugly design and relies on a lot of context, only 360aae69bed019826ddec93f761514652a93d871e49Harald Welte * to be called from specific places within the parser */ 361aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int __iptcc_p_del_policy(TC_HANDLE_T h, unsigned int num) 362aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 363aae69bed019826ddec93f761514652a93d871e49Harald Welte if (h->chain_iterator_cur) { 364aae69bed019826ddec93f761514652a93d871e49Harald Welte /* policy rule is last rule */ 365aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *pr = (struct rule_head *) 366aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->rules.prev; 367aae69bed019826ddec93f761514652a93d871e49Harald Welte 368aae69bed019826ddec93f761514652a93d871e49Harald Welte /* save verdict */ 369aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->verdict = 370aae69bed019826ddec93f761514652a93d871e49Harald Welte *(int *)GET_TARGET(pr->entry)->data; 371aae69bed019826ddec93f761514652a93d871e49Harald Welte 372aae69bed019826ddec93f761514652a93d871e49Harald Welte /* save counter and counter_map information */ 373aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->counter_map.maptype = 374aae69bed019826ddec93f761514652a93d871e49Harald Welte COUNTER_MAP_NORMAL_MAP; 375aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->counter_map.mappos = num-1; 376aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters, 377aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(h->chain_iterator_cur->counters)); 378aae69bed019826ddec93f761514652a93d871e49Harald Welte 379aae69bed019826ddec93f761514652a93d871e49Harald Welte /* foot_offset points to verdict rule */ 380aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->foot_index = num; 381aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->foot_offset = pr->offset; 382aae69bed019826ddec93f761514652a93d871e49Harald Welte 383aae69bed019826ddec93f761514652a93d871e49Harald Welte /* delete rule from cache */ 384aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(pr); 3858d1b38a064d146c77eb8fc951717663e1a713cfcMartin Josefsson h->chain_iterator_cur->num_rules--; 386aae69bed019826ddec93f761514652a93d871e49Harald Welte 387e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 388e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 389e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 390e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 391e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 392aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Another ugly helper function split out of cache_add_entry to make it less 393aae69bed019826ddec93f761514652a93d871e49Harald Welte * spaghetti code */ 394aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void __iptcc_p_add_chain(TC_HANDLE_T h, struct chain_head *c, 395aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset, unsigned int *num) 396e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 397aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_del_policy(h, *num); 398e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 399aae69bed019826ddec93f761514652a93d871e49Harald Welte c->head_offset = offset; 400aae69bed019826ddec93f761514652a93d871e49Harald Welte c->index = *num; 401e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 402aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&c->list, &h->chains); 403aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur = c; 404e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 405e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 406aae69bed019826ddec93f761514652a93d871e49Harald Welte/* main parser function: add an entry from the blob to the cache */ 407aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int cache_add_entry(STRUCT_ENTRY *e, 408aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T h, 409aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY **prev, 410aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int *num) 411e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 412aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int builtin; 413aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset = (char *)e - (char *)h->entries->entrytable; 414aae69bed019826ddec93f761514652a93d871e49Harald Welte 415aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("entering..."); 416aae69bed019826ddec93f761514652a93d871e49Harald Welte 417aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Last entry ("policy rule"). End it.*/ 418aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcb_entry2offset(h,e) + e->next_offset == h->entries->size) { 419aae69bed019826ddec93f761514652a93d871e49Harald Welte /* This is the ERROR node at the end of the chain */ 420aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u: end of table:\n", *num, offset); 421aae69bed019826ddec93f761514652a93d871e49Harald Welte 422aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_del_policy(h, *num); 423aae69bed019826ddec93f761514652a93d871e49Harald Welte 424aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur = NULL; 425aae69bed019826ddec93f761514652a93d871e49Harald Welte goto out_inc; 426aae69bed019826ddec93f761514652a93d871e49Harald Welte } 427aae69bed019826ddec93f761514652a93d871e49Harald Welte 428aae69bed019826ddec93f761514652a93d871e49Harald Welte /* We know this is the start of a new chain if it's an ERROR 429aae69bed019826ddec93f761514652a93d871e49Harald Welte * target, or a hook entry point */ 430aae69bed019826ddec93f761514652a93d871e49Harald Welte 431aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) { 432aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = 433aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0); 434aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset, 435aae69bed019826ddec93f761514652a93d871e49Harald Welte (char *)c->name, c); 436aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 437aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = -ENOMEM; 438aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 439aae69bed019826ddec93f761514652a93d871e49Harald Welte } 440aae69bed019826ddec93f761514652a93d871e49Harald Welte 441aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_add_chain(h, c, offset, num); 442aae69bed019826ddec93f761514652a93d871e49Harald Welte 443aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) { 444aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = 445aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_alloc_chain_head((char *)hooknames[builtin-1], 446aae69bed019826ddec93f761514652a93d871e49Harald Welte builtin); 447aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n", 448aae69bed019826ddec93f761514652a93d871e49Harald Welte *num, offset, c, &c->rules); 449aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 450aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = -ENOMEM; 451aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 452aae69bed019826ddec93f761514652a93d871e49Harald Welte } 453aae69bed019826ddec93f761514652a93d871e49Harald Welte 454aae69bed019826ddec93f761514652a93d871e49Harald Welte c->hooknum = builtin; 455aae69bed019826ddec93f761514652a93d871e49Harald Welte 456aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_add_chain(h, c, offset, num); 457aae69bed019826ddec93f761514652a93d871e49Harald Welte 458aae69bed019826ddec93f761514652a93d871e49Harald Welte /* FIXME: this is ugly. */ 459aae69bed019826ddec93f761514652a93d871e49Harald Welte goto new_rule; 460aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 461aae69bed019826ddec93f761514652a93d871e49Harald Welte /* has to be normal rule */ 462aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 463aae69bed019826ddec93f761514652a93d871e49Harald Weltenew_rule: 464aae69bed019826ddec93f761514652a93d871e49Harald Welte 465aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, 466aae69bed019826ddec93f761514652a93d871e49Harald Welte e->next_offset))) { 467aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 468aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 469aae69bed019826ddec93f761514652a93d871e49Harald Welte } 470aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r); 471aae69bed019826ddec93f761514652a93d871e49Harald Welte 472aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index = *num; 473aae69bed019826ddec93f761514652a93d871e49Harald Welte r->offset = offset; 474aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 475aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_NORMAL_MAP; 476aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos = r->index; 477aae69bed019826ddec93f761514652a93d871e49Harald Welte 478aae69bed019826ddec93f761514652a93d871e49Harald Welte /* handling of jumps, etc. */ 479aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET)) { 480aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 481aae69bed019826ddec93f761514652a93d871e49Harald Welte 482aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 483aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->target.u.target_size 484aae69bed019826ddec93f761514652a93d871e49Harald Welte != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 485aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EINVAL; 486aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 487aae69bed019826ddec93f761514652a93d871e49Harald Welte } 488aae69bed019826ddec93f761514652a93d871e49Harald Welte 489aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->verdict < 0) { 490aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("standard, verdict=%d\n", t->verdict); 491aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_STANDARD; 492aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (t->verdict == r->offset+e->next_offset) { 493aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("fallthrough\n"); 494aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_FALLTHROUGH; 495aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 496aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("jump, target=%u\n", t->verdict); 497aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_JUMP; 498aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Jump target fixup has to be deferred 499aae69bed019826ddec93f761514652a93d871e49Harald Welte * until second pass, since we migh not 500aae69bed019826ddec93f761514652a93d871e49Harald Welte * yet have parsed the target */ 501aae69bed019826ddec93f761514652a93d871e49Harald Welte } 50252c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson } else { 50352c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson DEBUGP_C("module, target=%s\n", GET_TARGET(e)->u.user.name); 50452c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson r->type = IPTCC_R_MODULE; 505aae69bed019826ddec93f761514652a93d871e49Harald Welte } 506aae69bed019826ddec93f761514652a93d871e49Harald Welte 507aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &h->chain_iterator_cur->rules); 5088d1b38a064d146c77eb8fc951717663e1a713cfcMartin Josefsson h->chain_iterator_cur->num_rules++; 509aae69bed019826ddec93f761514652a93d871e49Harald Welte } 510aae69bed019826ddec93f761514652a93d871e49Harald Welteout_inc: 511aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 512aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 513e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 514e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 515aae69bed019826ddec93f761514652a93d871e49Harald Welte 516aae69bed019826ddec93f761514652a93d871e49Harald Welte/* parse an iptables blob into it's pieces */ 517aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int parse_table(TC_HANDLE_T h) 518e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 519aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *prev; 520aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int num = 0; 521aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 522aae69bed019826ddec93f761514652a93d871e49Harald Welte 523aae69bed019826ddec93f761514652a93d871e49Harald Welte /* First pass: over ruleset blob */ 524aae69bed019826ddec93f761514652a93d871e49Harald Welte ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 525aae69bed019826ddec93f761514652a93d871e49Harald Welte cache_add_entry, h, &prev, &num); 526aae69bed019826ddec93f761514652a93d871e49Harald Welte 527aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Second pass: fixup parsed data from first pass */ 528aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 529aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 530aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 531aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 532aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 533aae69bed019826ddec93f761514652a93d871e49Harald Welte 534aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type != IPTCC_R_JUMP) 535aae69bed019826ddec93f761514652a93d871e49Harald Welte continue; 536aae69bed019826ddec93f761514652a93d871e49Harald Welte 537aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 538aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_chain_by_offset(h, t->verdict); 539aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) 540aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 541aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump = c; 542aae69bed019826ddec93f761514652a93d871e49Harald Welte c->references++; 543aae69bed019826ddec93f761514652a93d871e49Harald Welte } 544aae69bed019826ddec93f761514652a93d871e49Harald Welte } 545aae69bed019826ddec93f761514652a93d871e49Harald Welte 546aae69bed019826ddec93f761514652a93d871e49Harald Welte /* FIXME: sort chains */ 547aae69bed019826ddec93f761514652a93d871e49Harald Welte 548aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 5490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 5509e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 551aae69bed019826ddec93f761514652a93d871e49Harald Welte 552aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 553aae69bed019826ddec93f761514652a93d871e49Harald Welte * RULESET COMPILATION (cache -> blob) 554aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 555aae69bed019826ddec93f761514652a93d871e49Harald Welte 556aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Convenience structures */ 557aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_start{ 558aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY e; 559aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_error_target name; 560aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 561aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) + \ 562aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target))) 563aae69bed019826ddec93f761514652a93d871e49Harald Welte 564aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_foot { 565aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY e; 566aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET target; 567aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 568aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_FOOT_SIZE (sizeof(STRUCT_ENTRY) + \ 569aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(STRUCT_STANDARD_TARGET))) 570aae69bed019826ddec93f761514652a93d871e49Harald Welte 571aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_error { 572aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY entry; 573aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_error_target target; 574aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 575aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) + \ 576aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target))) 577aae69bed019826ddec93f761514652a93d871e49Harald Welte 578aae69bed019826ddec93f761514652a93d871e49Harald Welte 579aae69bed019826ddec93f761514652a93d871e49Harald Welte 580aae69bed019826ddec93f761514652a93d871e49Harald Welte/* compile rule from cache into blob */ 581aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int iptcc_compile_rule (TC_HANDLE_T h, STRUCT_REPLACE *repl, struct rule_head *r) 5820113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 583aae69bed019826ddec93f761514652a93d871e49Harald Welte /* handle jumps */ 584aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type == IPTCC_R_JUMP) { 585aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 586aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 587aae69bed019826ddec93f761514652a93d871e49Harald Welte /* memset for memcmp convenience on delete/replace */ 588aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 589aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(t->target.u.user.name, STANDARD_TARGET); 590aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Jumps can only happen to builtin chains, so we 591aae69bed019826ddec93f761514652a93d871e49Harald Welte * can safely assume that they always have a header */ 592aae69bed019826ddec93f761514652a93d871e49Harald Welte t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE; 593aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (r->type == IPTCC_R_FALLTHROUGH) { 594aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 595aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 596aae69bed019826ddec93f761514652a93d871e49Harald Welte t->verdict = r->offset + r->size; 597aae69bed019826ddec93f761514652a93d871e49Harald Welte } 598aae69bed019826ddec93f761514652a93d871e49Harald Welte 599aae69bed019826ddec93f761514652a93d871e49Harald Welte /* copy entry from cache to blob */ 600aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy((char *)repl->entries+r->offset, r->entry, r->size); 601aae69bed019826ddec93f761514652a93d871e49Harald Welte 602aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 603e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 604e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 605aae69bed019826ddec93f761514652a93d871e49Harald Welte/* compile chain from cache into blob */ 606aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain_head *c) 6073ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 608aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 609aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 610aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_start *head; 611aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_foot *foot; 612aae69bed019826ddec93f761514652a93d871e49Harald Welte 613aae69bed019826ddec93f761514652a93d871e49Harald Welte /* only user-defined chains have heaer */ 614aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 615aae69bed019826ddec93f761514652a93d871e49Harald Welte /* put chain header in place */ 616aae69bed019826ddec93f761514652a93d871e49Harald Welte head = (void *)repl->entries + c->head_offset; 617aae69bed019826ddec93f761514652a93d871e49Harald Welte head->e.target_offset = sizeof(STRUCT_ENTRY); 618aae69bed019826ddec93f761514652a93d871e49Harald Welte head->e.next_offset = IPTCB_CHAIN_START_SIZE; 619aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(head->name.t.u.user.name, ERROR_TARGET); 620aae69bed019826ddec93f761514652a93d871e49Harald Welte head->name.t.u.target_size = 621aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target)); 622aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(head->name.error, c->name); 623aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 624aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->hook_entry[c->hooknum-1] = c->head_offset; 625aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->underflow[c->hooknum-1] = c->foot_offset; 626aae69bed019826ddec93f761514652a93d871e49Harald Welte } 627aae69bed019826ddec93f761514652a93d871e49Harald Welte 628aae69bed019826ddec93f761514652a93d871e49Harald Welte /* iterate over rules */ 629aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 630aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_rule(h, repl, r); 631aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 632aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 633aae69bed019826ddec93f761514652a93d871e49Harald Welte } 634aae69bed019826ddec93f761514652a93d871e49Harald Welte 635aae69bed019826ddec93f761514652a93d871e49Harald Welte /* put chain footer in place */ 636aae69bed019826ddec93f761514652a93d871e49Harald Welte foot = (void *)repl->entries + c->foot_offset; 637aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->e.target_offset = sizeof(STRUCT_ENTRY); 638aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE; 639aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(foot->target.target.u.user.name, STANDARD_TARGET); 640aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.target.u.target_size = 641aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 642aae69bed019826ddec93f761514652a93d871e49Harald Welte /* builtin targets have verdict, others return */ 643aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_is_builtin(c)) 644aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.verdict = c->verdict; 645aae69bed019826ddec93f761514652a93d871e49Harald Welte else 646aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.verdict = RETURN; 647aae69bed019826ddec93f761514652a93d871e49Harald Welte /* set policy-counters */ 648aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS)); 649aae69bed019826ddec93f761514652a93d871e49Harald Welte 650aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 6513ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 6523ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 653aae69bed019826ddec93f761514652a93d871e49Harald Welte/* calculate offset and number for every rule in the cache */ 654aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_chain_offsets(TC_HANDLE_T h, struct chain_head *c, 655aae69bed019826ddec93f761514652a93d871e49Harald Welte int *offset, int *num) 6563ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 657aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 658aae69bed019826ddec93f761514652a93d871e49Harald Welte 659aae69bed019826ddec93f761514652a93d871e49Harald Welte c->head_offset = *offset; 660aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("%s: chain_head %u, offset=%u\n", c->name, *num, *offset); 661aae69bed019826ddec93f761514652a93d871e49Harald Welte 662aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 663aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Chain has header */ 664aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += sizeof(STRUCT_ENTRY) 665aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(struct ipt_error_target)); 666aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 667aae69bed019826ddec93f761514652a93d871e49Harald Welte } 668aae69bed019826ddec93f761514652a93d871e49Harald Welte 669aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 670aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("rule %u, offset=%u, index=%u\n", *num, *offset, *num); 671aae69bed019826ddec93f761514652a93d871e49Harald Welte r->offset = *offset; 672aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index = *num; 673aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += r->size; 674aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 675aae69bed019826ddec93f761514652a93d871e49Harald Welte } 676aae69bed019826ddec93f761514652a93d871e49Harald Welte 677aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num, 678aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset, *num); 679aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_offset = *offset; 680aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index = *num; 681aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += sizeof(STRUCT_ENTRY) 682aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 683aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 684aae69bed019826ddec93f761514652a93d871e49Harald Welte 685aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 6863ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 6873ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 688aae69bed019826ddec93f761514652a93d871e49Harald Welte/* put the pieces back together again */ 689aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_table_prep(TC_HANDLE_T h, unsigned int *size) 690aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 691aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 692aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset = 0, num = 0; 693aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret = 0; 6943ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 695aae69bed019826ddec93f761514652a93d871e49Harald Welte /* First pass: calculate offset for every rule */ 696aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 697aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_chain_offsets(h, c, &offset, &num); 698aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 699aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 700aae69bed019826ddec93f761514652a93d871e49Harald Welte } 701aae69bed019826ddec93f761514652a93d871e49Harald Welte 702aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Append one error rule at end of chain */ 703aae69bed019826ddec93f761514652a93d871e49Harald Welte num++; 704aae69bed019826ddec93f761514652a93d871e49Harald Welte offset += sizeof(STRUCT_ENTRY) 705aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(struct ipt_error_target)); 706aae69bed019826ddec93f761514652a93d871e49Harald Welte 707aae69bed019826ddec93f761514652a93d871e49Harald Welte /* ruleset size is now in offset */ 708aae69bed019826ddec93f761514652a93d871e49Harald Welte *size = offset; 709aae69bed019826ddec93f761514652a93d871e49Harald Welte return num; 710aae69bed019826ddec93f761514652a93d871e49Harald Welte} 711aae69bed019826ddec93f761514652a93d871e49Harald Welte 712aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE *repl) 7130113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 714aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 715aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_error *error; 7160113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 717aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Second pass: copy from cache to offsets, fill in jumps */ 718aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 719aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret = iptcc_compile_chain(h, repl, c); 720aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 721aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 7220113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 7230113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 724aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Append error rule at end of chain */ 725aae69bed019826ddec93f761514652a93d871e49Harald Welte error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE; 726aae69bed019826ddec93f761514652a93d871e49Harald Welte error->entry.target_offset = sizeof(STRUCT_ENTRY); 727aae69bed019826ddec93f761514652a93d871e49Harald Welte error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE; 728aae69bed019826ddec93f761514652a93d871e49Harald Welte error->target.t.u.user.target_size = 729aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target)); 730aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET); 731aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy((char *)&error->target.error, "ERROR"); 732aae69bed019826ddec93f761514652a93d871e49Harald Welte 733aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 7340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 735e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 736aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 737aae69bed019826ddec93f761514652a93d871e49Harald Welte * EXTERNAL API (operates on cache only) 738aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 739aae69bed019826ddec93f761514652a93d871e49Harald Welte 740e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Allocate handle of given size */ 74179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic TC_HANDLE_T 7420113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltealloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 743e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 744e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher size_t len; 74579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 746e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 747aae69bed019826ddec93f761514652a93d871e49Harald Welte len = sizeof(STRUCT_TC_HANDLE) + size; 748e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 749aae69bed019826ddec93f761514652a93d871e49Harald Welte h = malloc(sizeof(STRUCT_TC_HANDLE)); 750aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h) { 751e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 752e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 753e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 754aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(h, 0, sizeof(*h)); 755aae69bed019826ddec93f761514652a93d871e49Harald Welte INIT_LIST_HEAD(&h->chains); 756e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(h->info.name, tablename); 757aae69bed019826ddec93f761514652a93d871e49Harald Welte 7580371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size); 759aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h->entries) 760aae69bed019826ddec93f761514652a93d871e49Harald Welte goto out_free_handle; 761aae69bed019826ddec93f761514652a93d871e49Harald Welte 762aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(h->entries->name, tablename); 7630371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries->size = size; 764e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 765e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 766aae69bed019826ddec93f761514652a93d871e49Harald Welte 767aae69bed019826ddec93f761514652a93d871e49Harald Welteout_free_handle: 768aae69bed019826ddec93f761514652a93d871e49Harald Welte free(h); 769aae69bed019826ddec93f761514652a93d871e49Harald Welte 770aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 771e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 772e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 773aae69bed019826ddec93f761514652a93d871e49Harald Welte 77479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_HANDLE_T 77579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INIT(const char *tablename) 776e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 77779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 77879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 779e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int tmp; 780e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher socklen_t s; 781e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 78279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INIT; 783e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 784e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson if (sockfd != -1) { 785366454bc69f781fdafc3a30eb6dd77155ee4efb6Harald Welte close(sockfd); 786e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 787e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson } 788366454bc69f781fdafc3a30eb6dd77155ee4efb6Harald Welte 789841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson if (strlen(tablename) >= TABLE_MAXNAMELEN) { 790841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson errno = EINVAL; 791841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson return NULL; 792841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 793841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 79479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 795e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (sockfd < 0) 796e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 797e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 798e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher s = sizeof(info); 799841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 800e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(info.name, tablename); 80179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) 802e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 803e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 804aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n", 805aae69bed019826ddec93f761514652a93d871e49Harald Welte info.valid_hooks, info.num_entries, info.size); 806aae69bed019826ddec93f761514652a93d871e49Harald Welte 8070113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((h = alloc_handle(info.name, info.size, info.num_entries)) 808841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson == NULL) { 809841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson close(sockfd); 810e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 811e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 812841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 813e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 814e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Initialize current state */ 815e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->info = info; 8160113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 817aae69bed019826ddec93f761514652a93d871e49Harald Welte h->entries->size = h->info.size; 818e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 81979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 820e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 821aae69bed019826ddec93f761514652a93d871e49Harald Welte if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries, 822aae69bed019826ddec93f761514652a93d871e49Harald Welte &tmp) < 0) 823aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 824aae69bed019826ddec93f761514652a93d871e49Harald Welte 825aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 826aae69bed019826ddec93f761514652a93d871e49Harald Welte { 827aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_get_entries.blob", 828aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 829aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 830aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, h->entries, tmp); 831aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 832aae69bed019826ddec93f761514652a93d871e49Harald Welte } 833e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 834aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 835aae69bed019826ddec93f761514652a93d871e49Harald Welte 836aae69bed019826ddec93f761514652a93d871e49Harald Welte if (parse_table(h) < 0) 837aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 8387e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 839e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(h); 840e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 841aae69bed019826ddec93f761514652a93d871e49Harald Welteerror: 842aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_FREE(&h); 843aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 844e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 845e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 846841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefssonvoid 847841e4aed2349046eb2c0b1375139c06569a93bd0Martin JosefssonTC_FREE(TC_HANDLE_T *h) 848841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson{ 849aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c, *tmp; 850aae69bed019826ddec93f761514652a93d871e49Harald Welte 851841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson close(sockfd); 852e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 853aae69bed019826ddec93f761514652a93d871e49Harald Welte 854aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(c, tmp, &(*h)->chains, list) { 855aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *rtmp; 856aae69bed019826ddec93f761514652a93d871e49Harald Welte 857aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, rtmp, &c->rules, list) { 858aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 859aae69bed019826ddec93f761514652a93d871e49Harald Welte } 860aae69bed019826ddec93f761514652a93d871e49Harald Welte 861aae69bed019826ddec93f761514652a93d871e49Harald Welte free(c); 862aae69bed019826ddec93f761514652a93d871e49Harald Welte } 863aae69bed019826ddec93f761514652a93d871e49Harald Welte 864aae69bed019826ddec93f761514652a93d871e49Harald Welte free((*h)->entries); 865841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson free(*h); 866aae69bed019826ddec93f761514652a93d871e49Harald Welte 867841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson *h = NULL; 868841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson} 869841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 870e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 87179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellprint_match(const STRUCT_ENTRY_MATCH *m) 872e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 873228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell printf("Match name: `%s'\n", m->u.user.name); 874e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 875e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 876e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 87779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle); 87879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell 879e6869a8f59d779ff4d5a0984c86d80db7078496Marc Bouchervoid 88079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DUMP_ENTRIES(const TC_HANDLE_T handle) 881e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 882e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(handle); 883aae69bed019826ddec93f761514652a93d871e49Harald Welte#if 0 884e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("libiptc v%s. %u entries, %u bytes.\n", 88580fe35d6339b53a12ddaec41885613e4e37ed031Harald Welte IPTABLES_VERSION, 886aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->new_number, handle->entries->size); 887e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Table `%s'\n", handle->info.name); 888e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 88967088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_PRE_ROUTING], 89067088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_IN], 89167088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_FORWARD], 89267088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_OUT], 89367088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_POST_ROUTING]); 894e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 89567088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_PRE_ROUTING], 89667088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_IN], 89767088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_FORWARD], 89867088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_OUT], 89967088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_POST_ROUTING]); 900e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 901aae69bed019826ddec93f761514652a93d871e49Harald Welte ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size, 90279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell dump_entry, handle); 903aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 9040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 905e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 906e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Does this chain exist? */ 90779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle) 908e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 909aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_find_label(chain, handle) != NULL; 910e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 911e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 912aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void iptcc_chain_iterator_advance(TC_HANDLE_T handle) 913aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 914aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = handle->chain_iterator_cur; 915aae69bed019826ddec93f761514652a93d871e49Harald Welte 916aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->list.next == &handle->chains) 917aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->chain_iterator_cur = NULL; 918aae69bed019826ddec93f761514652a93d871e49Harald Welte else 919aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->chain_iterator_cur = 920aae69bed019826ddec93f761514652a93d871e49Harald Welte list_entry(c->list.next, struct chain_head, list); 921aae69bed019826ddec93f761514652a93d871e49Harald Welte} 922e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 92330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. */ 924e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 9258c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_CHAIN(TC_HANDLE_T *handle) 926e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 927aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = list_entry((*handle)->chains.next, 928aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head, list); 929aae69bed019826ddec93f761514652a93d871e49Harald Welte 930aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_CHAIN; 931aae69bed019826ddec93f761514652a93d871e49Harald Welte 932aae69bed019826ddec93f761514652a93d871e49Harald Welte 933aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&(*handle)->chains)) { 934aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no chains\n"); 9350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 936aae69bed019826ddec93f761514652a93d871e49Harald Welte } 9370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 938aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->chain_iterator_cur = c; 939aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 94030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 941aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 942aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 94330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 94430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 94530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. Returns NULL at end. */ 94630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellconst char * 94779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NEXT_CHAIN(TC_HANDLE_T *handle) 94830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 949aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = (*handle)->chain_iterator_cur; 950aae69bed019826ddec93f761514652a93d871e49Harald Welte 951aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_CHAIN; 95230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 953aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 954aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no more chains\n"); 95530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 956aae69bed019826ddec93f761514652a93d871e49Harald Welte } 95730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 958aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 959aae69bed019826ddec93f761514652a93d871e49Harald Welte 960aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 961aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 96230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 96330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 96430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Get first rule in the given chain: NULL for empty chain. */ 96579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 9668c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_RULE(const char *chain, TC_HANDLE_T *handle) 96730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 968aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 969aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 970aae69bed019826ddec93f761514652a93d871e49Harald Welte 971aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_RULE; 97230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 973aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("first rule(%s): ", chain); 974aae69bed019826ddec93f761514652a93d871e49Harald Welte 975aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 97630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!c) { 97730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell errno = ENOENT; 97830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 979e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 980e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 98130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Empty chain: single return/policy rule */ 982aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&c->rules)) { 983aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("no rules, returning NULL\n"); 98430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 985aae69bed019826ddec93f761514652a93d871e49Harald Welte } 986aae69bed019826ddec93f761514652a93d871e49Harald Welte 987aae69bed019826ddec93f761514652a93d871e49Harald Welte r = list_entry(c->rules.next, struct rule_head, list); 988aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = r; 989aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%p\n", r); 99030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 991aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 992e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 993e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 99430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Returns NULL when rules run out. */ 99579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 9968c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle) 99730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 998aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 999aae69bed019826ddec93f761514652a93d871e49Harald Welte 1000aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("rule_iterator_cur=%p...", (*handle)->rule_iterator_cur); 1001aae69bed019826ddec93f761514652a93d871e49Harald Welte 1002aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(*handle)->rule_iterator_cur) { 1003aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning NULL\n"); 100430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1005aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1006aae69bed019826ddec93f761514652a93d871e49Harald Welte 1007aae69bed019826ddec93f761514652a93d871e49Harald Welte r = list_entry((*handle)->rule_iterator_cur->list.next, 1008aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 100930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1010aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_RULE; 1011aae69bed019826ddec93f761514652a93d871e49Harald Welte 1012aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("next=%p, head=%p...", &r->list, 1013aae69bed019826ddec93f761514652a93d871e49Harald Welte &(*handle)->rule_iterator_cur->chain->rules); 1014aae69bed019826ddec93f761514652a93d871e49Harald Welte 1015aae69bed019826ddec93f761514652a93d871e49Harald Welte if (&r->list == &(*handle)->rule_iterator_cur->chain->rules) { 1016aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = NULL; 1017aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("finished, returning NULL\n"); 1018aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1019aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1020aae69bed019826ddec93f761514652a93d871e49Harald Welte 1021aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = r; 1022aae69bed019826ddec93f761514652a93d871e49Harald Welte 1023aae69bed019826ddec93f761514652a93d871e49Harald Welte /* NOTE: prev is without any influence ! */ 1024aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning rule %p\n", r); 1025aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 102630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 102730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1028e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* How many rules in this chain? */ 1029e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherunsigned int 103079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NUM_RULES(const char *chain, TC_HANDLE_T *handle) 1031e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1032aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1033aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NUM_RULES; 1034e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1035aae69bed019826ddec93f761514652a93d871e49Harald Welte 1036aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1037aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1038e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1039e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return (unsigned int)-1; 1040e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1041aae69bed019826ddec93f761514652a93d871e49Harald Welte 1042aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->num_rules; 1043e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1044e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 104579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY *TC_GET_RULE(const char *chain, 104679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int n, 104779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1048e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1049aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1050aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1051aae69bed019826ddec93f761514652a93d871e49Harald Welte 1052aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_RULE; 1053e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1054e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1055aae69bed019826ddec93f761514652a93d871e49Harald Welte 1056aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1057aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1058e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1059e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1060e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1061e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1062aae69bed019826ddec93f761514652a93d871e49Harald Welte r = iptcc_get_rule_num(c, n); 1063aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!r) 1064aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1065aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 1066e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1067e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1068aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 1069aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char *standard_target_map(int verdict) 1070e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1071aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (verdict) { 1072aae69bed019826ddec93f761514652a93d871e49Harald Welte case RETURN: 107379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_RETURN; 1074aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1075aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_ACCEPT-1: 107679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_ACCEPT; 1077aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1078aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_DROP-1: 1079aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_DROP; 1080aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1081aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_QUEUE-1: 1082aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_QUEUE; 1083aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1084aae69bed019826ddec93f761514652a93d871e49Harald Welte default: 1085aae69bed019826ddec93f761514652a93d871e49Harald Welte fprintf(stderr, "ERROR: %d not a valid target)\n", 1086aae69bed019826ddec93f761514652a93d871e49Harald Welte verdict); 1087aae69bed019826ddec93f761514652a93d871e49Harald Welte abort(); 1088aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1089e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1090aae69bed019826ddec93f761514652a93d871e49Harald Welte /* not reached */ 1091aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1092e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1093e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1094aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 1095aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char *TC_GET_TARGET(const STRUCT_ENTRY *ce, 1096aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T *handle) 1097e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1098aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 1099aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r = container_of(e, struct rule_head, entry); 1100e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1101aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_TARGET; 11020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1103aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(r->type) { 1104aae69bed019826ddec93f761514652a93d871e49Harald Welte int spos; 1105aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_FALLTHROUGH: 1106aae69bed019826ddec93f761514652a93d871e49Harald Welte return ""; 1107aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1108aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_JUMP: 1109aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name); 1110aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->jump->name; 1111aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1112aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_STANDARD: 1113aae69bed019826ddec93f761514652a93d871e49Harald Welte spos = *(int *)GET_TARGET(e)->data; 1114aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, spos=%d'\n", r, spos); 1115aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(spos); 1116aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1117aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_MODULE: 1118aae69bed019826ddec93f761514652a93d871e49Harald Welte return GET_TARGET(e)->u.user.name; 1119aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 11200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 1121aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1122aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1123aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Is this a built-in chain? Actually returns hook + 1. */ 1124aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1125aae69bed019826ddec93f761514652a93d871e49Harald WelteTC_BUILTIN(const char *chain, const TC_HANDLE_T handle) 1126aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1127aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1128aae69bed019826ddec93f761514652a93d871e49Harald Welte 1129aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_BUILTIN; 11300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1131aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, handle); 1132aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1133aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1134aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 11350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 11360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1137aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_is_builtin(c); 11380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 11390113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1140aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Get the policy of a given built-in chain */ 1141aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char * 1142aae69bed019826ddec93f761514652a93d871e49Harald WelteTC_GET_POLICY(const char *chain, 1143aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters, 1144aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T *handle) 11450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 1146aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 11470113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1148aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_POLICY; 1149fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte 1150aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("called for chain %s\n", chain); 11510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1152aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1153aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1154aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1155aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 11560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 11570113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1158aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) 1159aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 11600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1161aae69bed019826ddec93f761514652a93d871e49Harald Welte *counters = c->counters; 11620113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1163aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(c->verdict); 11640113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 1165e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1166e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1167aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_standard_map(struct rule_head *r, int verdict) 1168e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1169aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 117079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 1171e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 117279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1173e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 117467088e73ce7707229c56987868f112051defca5aRusty Russell if (t->target.u.target_size 11758c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1176e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1177e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1178e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1179e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset for memcmp convenience on delete/replace */ 118079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 118179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell strcpy(t->target.u.user.name, STANDARD_TARGET); 1182e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = verdict; 1183e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1184aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_STANDARD; 1185aae69bed019826ddec93f761514652a93d871e49Harald Welte 1186e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1187e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 11887e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1189e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1190aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_map_target(const TC_HANDLE_T handle, 1191aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r) 1192e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1193aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 11940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 1195e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1196e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's empty (=> fall through) */ 1197aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(t->u.user.name, "") == 0) { 1198aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_FALLTHROUGH; 1199aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1200aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1201e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's a standard target name... */ 120279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 1203aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_ACCEPT - 1); 120479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 1205aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_DROP - 1); 120667088e73ce7707229c56987868f112051defca5aRusty Russell else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 1207aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_QUEUE - 1); 120879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 1209aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, RETURN); 121079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (TC_BUILTIN(t->u.user.name, handle)) { 1211e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Can't jump to builtins. */ 1212e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1213e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1214e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 1215e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's an existing chain name. */ 1216aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1217aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("trying to find chain `%s': ", t->u.user.name); 1218aae69bed019826ddec93f761514652a93d871e49Harald Welte 1219aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(t->u.user.name, handle); 1220aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c) { 1221aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("found!\n"); 1222aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_JUMP; 1223aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump = c; 1224aae69bed019826ddec93f761514652a93d871e49Harald Welte c->references++; 1225aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1226aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1227aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("not found :(\n"); 1228e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1229e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1230e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Must be a module? If not, kernel will reject... */ 1231e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset to all 0 for your memcmp convenience. */ 1232228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell memset(t->u.user.name + strlen(t->u.user.name), 1233e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 0, 123479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell FUNCTION_MAXNAMELEN - strlen(t->u.user.name)); 1235e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1236aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(handle); 1237aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1238e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1239e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 12400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 1241e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 124279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 124379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 124479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 124579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1246e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1247aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1248eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson struct rule_head *r; 1249eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson struct list_head *prev; 1250e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 125179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INSERT_ENTRY; 1252aae69bed019826ddec93f761514652a93d871e49Harald Welte 1253aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1254e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1255e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1256e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1257e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1258eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson /* first rulenum index = 0 1259eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson first c->num_rules index = 1 */ 1260eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson if (rulenum > c->num_rules) { 1261e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1262e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1263e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1264e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1265eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson /* Try to get the rule we want to insert after. 1266eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson In case of no rules, insert after chain head. */ 1267eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson r = iptcc_get_rule_num(c, rulenum + 1); 1268eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson if (r) 1269eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson prev = &r->list; 1270eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson else 1271eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson prev = &c->rules; 1272eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson 1273aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1274aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1275aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1276aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1277aae69bed019826ddec93f761514652a93d871e49Harald Welte 1278aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1279aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1280aae69bed019826ddec93f761514652a93d871e49Harald Welte 1281aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 1282aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 12830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1284aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1285aae69bed019826ddec93f761514652a93d871e49Harald Welte 1286eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson list_add_tail(&r->list, prev); 1287aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1288aae69bed019826ddec93f761514652a93d871e49Harald Welte 1289aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1290e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1291aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1292e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1293e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1294e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 1295e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 129679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 129779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 129879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 129979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1300e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1301aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1302aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *old; 1303e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 130479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_REPLACE_ENTRY; 1305e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1306aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1307e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1308e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1309e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1310e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13118e795b0ad07174eed4172f8d7237b3abdd9d0e15Martin Josefsson if (!(old = iptcc_get_rule_num(c, rulenum + 1))) { 1312e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1313e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1314e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1315e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1316aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1317aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1318e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1319aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1320aae69bed019826ddec93f761514652a93d871e49Harald Welte 1321aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1322aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1323e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1324aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 1325aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 13260113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1327aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1328aae69bed019826ddec93f761514652a93d871e49Harald Welte 1329aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add(&r->list, &old->list); 1330aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(old); 13310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1332aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1333aae69bed019826ddec93f761514652a93d871e49Harald Welte 1334aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1335e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1336e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Append entry `fw' to chain `chain'. Equivalent to insert with 1338e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher rulenum = length of chain. */ 1339e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 134079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 134179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 134279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1343e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1344aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1345aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1346e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 134779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_APPEND_ENTRY; 1348aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1349aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to find chain `%s'\n", chain); 1350e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1351e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1352e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1353e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1354aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1355aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to allocate rule for chain `%s'\n", chain); 1356aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1357aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1358aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1359aae69bed019826ddec93f761514652a93d871e49Harald Welte 1360aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1361aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1362aae69bed019826ddec93f761514652a93d871e49Harald Welte 1363aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 1364aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to ma target of rule for chain `%s'\n", chain); 1365aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 13660113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1367aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1368aae69bed019826ddec93f761514652a93d871e49Harald Welte 1369aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &c->rules); 1370aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1371aae69bed019826ddec93f761514652a93d871e49Harald Welte 1372aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 13730113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1374aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1375e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1376e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1377e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 137879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellmatch_different(const STRUCT_ENTRY_MATCH *a, 1379edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *a_elems, 1380edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_elems, 1381edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned char **maskptr) 1382e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 138379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY_MATCH *b; 1384edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1385e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1386e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Offset of b is the same as a. */ 138730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell b = (void *)b_elems + ((unsigned char *)a - a_elems); 1388e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1389228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (a->u.match_size != b->u.match_size) 1390e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1391e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1392228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (strcmp(a->u.user.name, b->u.user.name) != 0) 1393e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1394e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 139573ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell *maskptr += ALIGN(sizeof(*a)); 1396edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 139773ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1398edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1399edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 1; 1400edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell *maskptr += i; 1401edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 0; 1402edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell} 1403edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 1404edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russellstatic inline int 1405edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russelltarget_different(const unsigned char *a_targdata, 1406edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_targdata, 1407edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int tdatasize, 1408edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *mask) 1409edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell{ 1410edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1411edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell for (i = 0; i < tdatasize; i++) 1412edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a_targdata[i] ^ b_targdata[i]) & mask[i]) != 0) 141390e712a00913fe2a2f885142439c392392dc08a8Rusty Russell return 1; 1414e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1415e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1416e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1417e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 141879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic int 141979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellis_same(const STRUCT_ENTRY *a, 142079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *b, 142179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask); 1422e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 14230113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Delete the first rule in `chain' which matches `fw'. */ 1424e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 142579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_ENTRY(const IPT_CHAINLABEL chain, 142679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *origfw, 142779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask, 142879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1429e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1430aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1431fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte struct rule_head *r; 14320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY *e, *fw; 1433e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 143479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_ENTRY; 1435aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1436e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1437e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1438e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1439e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 14400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte fw = malloc(origfw->next_offset); 14410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (fw == NULL) { 14420113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = ENOMEM; 14430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 14440113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 14450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1446fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte list_for_each_entry(r, &c->rules, list) { 14470113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 14480113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(fw, origfw, origfw->next_offset); 14490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1450fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte#if 0 14510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* FIXME: handle this in is_same --RR */ 14520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!map_target(*handle, fw, offset, &discard)) { 14530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte free(fw); 14540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 14550113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 14560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte#endif 1457fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 1458fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte e = r->entry; 1459fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 14600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (is_same(e, fw, matchmask)) { 1461fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte /* If we are about to delete the rule that is the 1462fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte * current iterator, move rule iterator back. next 1463fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte * pointer will then point to real next node */ 1464fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte if (r == (*handle)->rule_iterator_cur) { 1465fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte (*handle)->rule_iterator_cur = 1466fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte list_entry((*handle)->rule_iterator_cur->list.prev, 1467fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte struct rule_head, list); 1468fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte } 1469fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 1470fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte c->num_rules--; 1471fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte iptcc_delete_rule(r); 14722a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson 14732a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson set_changed(*handle); 1474fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte return 1; 1475e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1476e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1477e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 14780113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte free(fw); 1479e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1480e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 14817e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell} 1482aae69bed019826ddec93f761514652a93d871e49Harald Welte 1483e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1484e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Delete the rule in position `rulenum' in `chain'. */ 1485e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 148679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 148779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 148879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1489e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1490aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1491aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1492e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 149379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_NUM_ENTRY; 1494aae69bed019826ddec93f761514652a93d871e49Harald Welte 1495aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1496e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1497e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1498e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1499e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 15008e795b0ad07174eed4172f8d7237b3abdd9d0e15Martin Josefsson if (!(r = iptcc_get_rule_num(c, rulenum + 1))) { 1501e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1502e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1503e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1504e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1505aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the rule that is the current 1506aae69bed019826ddec93f761514652a93d871e49Harald Welte * iterator, move rule iterator back. next pointer will then 1507aae69bed019826ddec93f761514652a93d871e49Harald Welte * point to real next node */ 1508aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r == (*handle)->rule_iterator_cur) { 1509aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = 1510aae69bed019826ddec93f761514652a93d871e49Harald Welte list_entry((*handle)->rule_iterator_cur->list.prev, 1511aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 15120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 1513e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1514aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules--; 1515aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 1516aae69bed019826ddec93f761514652a93d871e49Harald Welte 15172a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson set_changed(*handle); 15182a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson 1519aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1520e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1521e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1522e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Check the packet `fw' on chain `chain'. Returns the verdict, or 1523e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher NULL and sets errno. */ 1524e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 152579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CHECK_PACKET(const IPT_CHAINLABEL chain, 152679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *entry, 152779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1528e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1529e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOSYS; 1530e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1531e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1532e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1533e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Flushes the entries in the given chain (ie. empties chain). */ 1534e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 153579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1536e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1537aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1538aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *tmp; 1539e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 15400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte iptc_fn = TC_FLUSH_ENTRIES; 1541aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1542e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1543e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1544e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1545e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1546aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, tmp, &c->rules, list) { 1547aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 1548aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1549aae69bed019826ddec93f761514652a93d871e49Harald Welte 1550aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules = 0; 1551aae69bed019826ddec93f761514652a93d871e49Harald Welte 1552aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1553aae69bed019826ddec93f761514652a93d871e49Harald Welte 1554aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1555e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1556e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1557e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Zeroes the counters in a chain. */ 1558e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 155979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1560e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1561aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1562aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 15637e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1564aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1565e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1566e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1567e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1568e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1569aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 1570aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 1571aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 1572e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1573aae69bed019826ddec93f761514652a93d871e49Harald Welte 1574175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1575e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1576e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1577e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1578e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 15791cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteSTRUCT_COUNTERS * 15801cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_READ_COUNTER(const IPT_CHAINLABEL chain, 15811cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 15821cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 15831cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1584aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1585aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 15861cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 15871cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_READ_COUNTER; 15881cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 15891cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1590aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 15911cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 15921cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return NULL; 15931cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 15941cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1595aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 15960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 15970113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 15980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 15990113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1600aae69bed019826ddec93f761514652a93d871e49Harald Welte return &r->entry[0].counters; 16011cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 16021cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16031cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 16041cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 16051cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 16061cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 16071cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1608aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1609aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 16101cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16111cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_ZERO_COUNTER; 16121cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 16131cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1614aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 16151cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 16161cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 16171cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 16181cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1619aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 16200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 16210113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 16220113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 16230113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1624aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 1625aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 16261cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16271cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 16281cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16291cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 16301cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 16311cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16321cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 16331cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_SET_COUNTER(const IPT_CHAINLABEL chain, 16341cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 16351cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 16361cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 16371cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1638aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1639aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 16401cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 16411cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16421cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_SET_COUNTER; 16431cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 16441cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1645aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 16461cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 16471cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 16481cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 16490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1650aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 16510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 16520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 16530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 16540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1655aae69bed019826ddec93f761514652a93d871e49Harald Welte e = r->entry; 1656aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 16570113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 16580113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 16591cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16601cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 16611cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16621cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 16631cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 16641cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1665e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Creates a new chain. */ 1666e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* To create a chain, create two rules: error node and unconditional 1667e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * return. */ 1668e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 166979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1670e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1671aae69bed019826ddec93f761514652a93d871e49Harald Welte static struct chain_head *c; 1672e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 167379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_CREATE_CHAIN; 1674e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1675e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* find_label doesn't cover built-in targets: DROP, ACCEPT, 1676e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher QUEUE, RETURN. */ 1677aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_find_label(chain, *handle) 167879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_DROP) == 0 167979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_ACCEPT) == 0 168067088e73ce7707229c56987868f112051defca5aRusty Russell || strcmp(chain, LABEL_QUEUE) == 0 168179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_RETURN) == 0) { 1682aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain `%s' already exists\n", chain); 1683e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1684e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1685e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1686e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 168779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 1688aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain name `%s' too long\n", chain); 1689e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1690e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1691e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1692e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1693aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_alloc_chain_head(chain, 0); 1694aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1695aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Cannot allocate memory for chain `%s'\n", chain); 1696aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1697aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1698e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1699aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1700e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1701aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Creating chain `%s'\n", chain); 1702aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&c->list, &(*handle)->chains); 1703e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1704aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1705e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1706aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1707e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1708e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1709e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get the number of references to this chain. */ 1710e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 171179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 171279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1713e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1714aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1715e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1716aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1717e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1718e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1719e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1720e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1721aae69bed019826ddec93f761514652a93d871e49Harald Welte *ref = c->references; 1722aae69bed019826ddec93f761514652a93d871e49Harald Welte 1723e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1724e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1725e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1726e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Deletes a chain. */ 1727e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 172879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1729e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1730e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int references; 1731aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 17327e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 173379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_CHAIN; 1734e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1735aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1736aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 1737aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1738aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1739aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1740aae69bed019826ddec93f761514652a93d871e49Harald Welte 174179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (TC_BUILTIN(chain, *handle)) { 1742aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot remove builtin chain `%s'\n", chain); 1743e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1744e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1745e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1746e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1747aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!TC_GET_REFERENCES(&references, chain, handle)) { 1748aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot get references on chain `%s'\n", chain); 1749e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1750e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1751e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1752aae69bed019826ddec93f761514652a93d871e49Harald Welte if (references > 0) { 1753aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' still has references\n", chain); 1754aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EMLINK; 1755e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1756e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1757e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1758aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->num_rules) { 1759aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' is not empty\n", chain); 1760e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOTEMPTY; 1761e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1762e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1763e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1764aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the chain that is the current 1765aae69bed019826ddec93f761514652a93d871e49Harald Welte * iterator, move chain iterator firward. */ 1766aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c == (*handle)->chain_iterator_cur) 1767aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 1768aae69bed019826ddec93f761514652a93d871e49Harald Welte 1769aae69bed019826ddec93f761514652a93d871e49Harald Welte list_del(&c->list); 1770aae69bed019826ddec93f761514652a93d871e49Harald Welte free(c); 17710113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1772aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' deleted\n", chain); 17730113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1774aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1775aae69bed019826ddec93f761514652a93d871e49Harald Welte 1776aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1777e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1778e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1779e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Renames a chain. */ 178079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 178179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL newname, 178279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1783e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1784aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 178579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_RENAME_CHAIN; 1786e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 17871de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte /* find_label doesn't cover built-in targets: DROP, ACCEPT, 17881de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte QUEUE, RETURN. */ 1789aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_find_label(newname, *handle) 179079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_DROP) == 0 179179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_ACCEPT) == 0 17921de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte || strcmp(newname, LABEL_QUEUE) == 0 179379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_RETURN) == 0) { 1794e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1795e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1796e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1797e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1798aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(oldname, *handle)) 179979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || TC_BUILTIN(oldname, *handle)) { 1800e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1801e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1802e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1803e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 180479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 1805e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1806e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1807e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1808e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1809aae69bed019826ddec93f761514652a93d871e49Harald Welte strncpy(c->name, newname, sizeof(IPT_CHAINLABEL)); 1810aae69bed019826ddec93f761514652a93d871e49Harald Welte 18110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte set_changed(*handle); 18120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1813e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1814e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1815e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1816e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Sets the policy on a built-in chain. */ 1817e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 181879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_SET_POLICY(const IPT_CHAINLABEL chain, 181979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL policy, 18201cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 182179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1822e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1823aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1824e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 182579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_SET_POLICY; 1826aae69bed019826ddec93f761514652a93d871e49Harald Welte 1827aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1828aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 1829c8264991454b5e77279830736f80ea3153b6f814Marc Boucher errno = ENOENT; 1830e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1831aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1832e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1833aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 1834aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain); 1835aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 18369e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte return 0; 18379e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte } 18389e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 183979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(policy, LABEL_ACCEPT) == 0) 1840aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_ACCEPT - 1; 184179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(policy, LABEL_DROP) == 0) 1842aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_DROP - 1; 1843e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else { 1844e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1845e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1846e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 18471cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 18481cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (counters) { 18491cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte /* set byte and packet counters */ 1850aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS)); 1851aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_SET; 18521cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } else { 1853aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_NOMAP; 18541cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 18551cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1856175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1857e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1858e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1859e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1860e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1861e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Without this, on gcc 2.7.2.3, we get: 186279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell libiptc.c: In function `TC_COMMIT': 1863e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher libiptc.c:833: fixed or forbidden register was spilled. 1864e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher This may be due to a compiler bug or to impossible asm 1865e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher statements or clauses. 1866e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher*/ 1867e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 186879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellsubtract_counters(STRUCT_COUNTERS *answer, 186979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *a, 187079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *b) 1871e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1872e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->pcnt = a->pcnt - b->pcnt; 1873e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->bcnt = a->bcnt - b->bcnt; 1874e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1875e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1876aae69bed019826ddec93f761514652a93d871e49Harald Welte 1877aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, 1878aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index) 1879aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1880aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->counters[index] = ((STRUCT_COUNTERS) { 0, 0}); 1881aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NOMAP => zero\n"); 1882aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1883aae69bed019826ddec93f761514652a93d871e49Harald Welte 1884aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters, 1885aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_REPLACE *repl, 1886aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 1887aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int mappos) 1888aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1889aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 1890aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 1891aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 1892aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: X + Y + Z. 1893aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in X + Y 1894aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in replacement read. 1895aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 1896aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->counters[index] = repl->counters[mappos]; 1897aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos); 1898aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1899aae69bed019826ddec93f761514652a93d871e49Harald Welte 1900aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters, 1901aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_REPLACE *repl, 1902aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 1903aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int mappos, 1904aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters) 1905aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1906aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 1907aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 1908aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 1909aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: Y + Z. 1910aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in Y. 1911aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in (replacement read - original read). 1912aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 1913aae69bed019826ddec93f761514652a93d871e49Harald Welte subtract_counters(&newcounters->counters[index], 1914aae69bed019826ddec93f761514652a93d871e49Harald Welte &repl->counters[mappos], 1915aae69bed019826ddec93f761514652a93d871e49Harald Welte counters); 1916aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("ZEROED => mappos %u\n", mappos); 1917aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1918aae69bed019826ddec93f761514652a93d871e49Harald Welte 1919aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_set(STRUCT_COUNTERS_INFO *newcounters, 1920aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 1921aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters) 1922aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1923aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Want to set counter (iptables-restore) */ 1924aae69bed019826ddec93f761514652a93d871e49Harald Welte 1925aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&newcounters->counters[index], counters, 1926aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(STRUCT_COUNTERS)); 1927aae69bed019826ddec93f761514652a93d871e49Harald Welte 1928aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("SET\n"); 1929aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1930aae69bed019826ddec93f761514652a93d871e49Harald Welte 1931aae69bed019826ddec93f761514652a93d871e49Harald Welte 1932e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 193379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_COMMIT(TC_HANDLE_T *handle) 1934e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1935e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Replace, then map back the counters. */ 193679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_REPLACE *repl; 193779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_COUNTERS_INFO *newcounters; 1938aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1939aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 1940841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson size_t counterlen; 1941aae69bed019826ddec93f761514652a93d871e49Harald Welte int new_number; 1942aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int new_size; 1943e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1944e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1945841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 1946e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#if 0 194754c307e0ff401f40a6fe382af4ae5bff0f5b40baRusty Russell TC_DUMP_ENTRIES(*handle); 1948e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#endif 1949e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1950e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Don't commit if nothing changed. */ 1951e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!(*handle)->changed) 1952e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher goto finished; 1953e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1954aae69bed019826ddec93f761514652a93d871e49Harald Welte new_number = iptcc_compile_table_prep(*handle, &new_size); 1955aae69bed019826ddec93f761514652a93d871e49Harald Welte if (new_number < 0) { 1956aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1957aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1958aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1959aae69bed019826ddec93f761514652a93d871e49Harald Welte 1960aae69bed019826ddec93f761514652a93d871e49Harald Welte repl = malloc(sizeof(*repl) + new_size); 1961e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl) { 1962e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1963e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1964e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1965aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(repl, 0, sizeof(*repl)); 1966aae69bed019826ddec93f761514652a93d871e49Harald Welte 1967aae69bed019826ddec93f761514652a93d871e49Harald Welte counterlen = sizeof(STRUCT_COUNTERS_INFO) 1968aae69bed019826ddec93f761514652a93d871e49Harald Welte + sizeof(STRUCT_COUNTERS) * new_number; 1969e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1970e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the old counters we will get from kernel */ 197179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell repl->counters = malloc(sizeof(STRUCT_COUNTERS) 1972e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * (*handle)->info.num_entries); 1973e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl->counters) { 1974e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1975e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1976e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1977e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1978e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the counters we're going to put back, later. */ 1979e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters = malloc(counterlen); 1980e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!newcounters) { 1981e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 1982e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1983e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1984e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1985e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1986aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(newcounters, 0, counterlen); 1987e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1988e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(repl->name, (*handle)->info.name); 1989aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries = new_number; 1990aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->size = new_size; 1991aae69bed019826ddec93f761514652a93d871e49Harald Welte 1992e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->num_counters = (*handle)->info.num_entries; 1993e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->valid_hooks = (*handle)->info.valid_hooks; 1994aae69bed019826ddec93f761514652a93d871e49Harald Welte 1995aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("num_entries=%u, size=%u, num_counters=%u\n", 1996aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries, repl->size, repl->num_counters); 1997aae69bed019826ddec93f761514652a93d871e49Harald Welte 1998aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_table(*handle, repl); 1999aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) { 2000aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ret; 2001aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl->counters); 2002aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl); 2003aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 2004aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2005aae69bed019826ddec93f761514652a93d871e49Harald Welte 2006aae69bed019826ddec93f761514652a93d871e49Harald Welte 2007aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 2008aae69bed019826ddec93f761514652a93d871e49Harald Welte { 2009aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_set_replace.blob", 2010aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 2011aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 2012aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, repl, sizeof(*repl) + repl->size); 2013aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 2014aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2015aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2016aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2017e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 201879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 2019aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(*repl) + repl->size) < 0) { 2020e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2021e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2022e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2023e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2024e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2025e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2026e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Put counters back. */ 2027e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(newcounters->name, (*handle)->info.name); 2028aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->num_counters = new_number; 2029aae69bed019826ddec93f761514652a93d871e49Harald Welte 2030aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &(*handle)->chains, list) { 2031aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 2032aae69bed019826ddec93f761514652a93d871e49Harald Welte 2033aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Builtin chains have their own counters */ 2034aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_is_builtin(c)) { 2035aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for chain-index %u: ", c->foot_index); 2036aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(c->counter_map.maptype) { 2037aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2038aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, c->foot_index); 2039aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2040aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2041aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2042aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index, 2043aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos); 2044aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2045aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2046aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2047aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index, 2048aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos, 2049aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2050aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2051aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2052aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, c->foot_index, 2053aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2054aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2055aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2056aae69bed019826ddec93f761514652a93d871e49Harald Welte } 20571cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2058aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 2059aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for index %u: ", r->index); 2060aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (r->counter_map.maptype) { 2061aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2062aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, r->index); 2063aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2064aae69bed019826ddec93f761514652a93d871e49Harald Welte 2065aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2066aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2067aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index, 2068aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos); 2069aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2070aae69bed019826ddec93f761514652a93d871e49Harald Welte 2071aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2072aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2073aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index, 2074aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos, 2075aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2076aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2077aae69bed019826ddec93f761514652a93d871e49Harald Welte 2078aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2079aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, r->index, 2080aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2081aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2082aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2083e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2084e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 208562527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell 2086aae69bed019826ddec93f761514652a93d871e49Harald Welte 208762527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell#ifdef KERNEL_64_USERSPACE_32 208862527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell { 208962527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell /* Kernel will think that pointer should be 64-bits, and get 209062527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell padding. So we accomodate here (assumption: alignment of 209162527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell `counters' is on 64-bit boundary). */ 209262527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell u_int64_t *kernptr = (u_int64_t *)&newcounters->counters; 209362527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell if ((unsigned long)&newcounters->counters % 8 != 0) { 209462527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell fprintf(stderr, 209562527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell "counters alignment incorrect! Mail rusty!\n"); 209662527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell abort(); 209762527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell } 209862527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell *kernptr = newcounters->counters; 209954c307e0ff401f40a6fe382af4ae5bff0f5b40baRusty Russell } 210062527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell#endif /* KERNEL_64_USERSPACE_32 */ 2101e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2102aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 2103aae69bed019826ddec93f761514652a93d871e49Harald Welte { 2104aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_set_add_counters.blob", 2105aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 2106aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 2107aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, newcounters, counterlen); 2108aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 2109aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2110aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2111aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2112aae69bed019826ddec93f761514652a93d871e49Harald Welte 211379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 211479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell newcounters, counterlen) < 0) { 2115e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2116e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2117e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2118e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2119e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2120e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2121e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2122e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2123e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2124e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2125e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher finished: 2126841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson TC_FREE(handle); 2127e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2128e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2129e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2130e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get raw socket. */ 2131e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 213279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_RAW_SOCKET() 2133e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2134e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return sockfd; 2135e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2136e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2137e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Translates errno numbers into more human-readable form than strerror. */ 2138e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 213979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_STRERROR(int err) 2140e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2141e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 2142e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct table_struct { 2143e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher void *fn; 2144e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int err; 2145e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char *message; 2146e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } table [] = 21474ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 214879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INIT, EINVAL, "Module is wrong version" }, 21494ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_INIT, ENOENT, 21504ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Table does not exist (do you need to insmod?)" }, 215179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 215279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 215379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EMLINK, 2154e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher "Can't delete chain with references left" }, 215579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 215679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 215779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 215879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 21591cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 21601cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 216179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 216279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 2163e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* EINVAL for CHECK probably means bad interface. */ 216479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CHECK_PACKET, EINVAL, 2165c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad arguments (does that interface exist?)" }, 21664ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_CHECK_PACKET, ENOSYS, 21674ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Checking will most likely never get implemented" }, 2168e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* ENOENT for DELETE probably means no matching rule */ 216979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_ENTRY, ENOENT, 2170c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad rule (does a matching rule exist in that chain?)" }, 217179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, ENOENT, 2172c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad built-in chain name" }, 217379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, EINVAL, 2174c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad policy name" }, 21754ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte 21764ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, 0, "Incompatible with this kernel" }, 21774ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 21784ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 21794ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOMEM, "Memory allocation problem" }, 21804ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOENT, "No chain/target/match by that name" }, 2181e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher }; 2182e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2183e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 2184e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((!table[i].fn || table[i].fn == iptc_fn) 2185e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && table[i].err == err) 2186e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return table[i].message; 2187e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2188e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2189e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return strerror(err); 2190e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2191