libiptc.c revision 52c380208a87191a8c25608d2c501c0dc32aa9ad
152c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson/* Library which manipulates firewall rules. Version $Revision: 1.50 $ */ 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); 385aae69bed019826ddec93f761514652a93d871e49Harald Welte 386e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 387e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 388e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 389e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 390e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 391aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Another ugly helper function split out of cache_add_entry to make it less 392aae69bed019826ddec93f761514652a93d871e49Harald Welte * spaghetti code */ 393aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void __iptcc_p_add_chain(TC_HANDLE_T h, struct chain_head *c, 394aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset, unsigned int *num) 395e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 396aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_del_policy(h, *num); 397e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 398aae69bed019826ddec93f761514652a93d871e49Harald Welte c->head_offset = offset; 399aae69bed019826ddec93f761514652a93d871e49Harald Welte c->index = *num; 400e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 401aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&c->list, &h->chains); 402aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur = c; 403e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 404e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 405aae69bed019826ddec93f761514652a93d871e49Harald Welte/* main parser function: add an entry from the blob to the cache */ 406aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int cache_add_entry(STRUCT_ENTRY *e, 407aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T h, 408aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY **prev, 409aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int *num) 410e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 411aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int builtin; 412aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset = (char *)e - (char *)h->entries->entrytable; 413aae69bed019826ddec93f761514652a93d871e49Harald Welte 414aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("entering..."); 415aae69bed019826ddec93f761514652a93d871e49Harald Welte 416aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Last entry ("policy rule"). End it.*/ 417aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcb_entry2offset(h,e) + e->next_offset == h->entries->size) { 418aae69bed019826ddec93f761514652a93d871e49Harald Welte /* This is the ERROR node at the end of the chain */ 419aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u: end of table:\n", *num, offset); 420aae69bed019826ddec93f761514652a93d871e49Harald Welte 421aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_del_policy(h, *num); 422aae69bed019826ddec93f761514652a93d871e49Harald Welte 423aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur = NULL; 424aae69bed019826ddec93f761514652a93d871e49Harald Welte goto out_inc; 425aae69bed019826ddec93f761514652a93d871e49Harald Welte } 426aae69bed019826ddec93f761514652a93d871e49Harald Welte 427aae69bed019826ddec93f761514652a93d871e49Harald Welte /* We know this is the start of a new chain if it's an ERROR 428aae69bed019826ddec93f761514652a93d871e49Harald Welte * target, or a hook entry point */ 429aae69bed019826ddec93f761514652a93d871e49Harald Welte 430aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) { 431aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = 432aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0); 433aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset, 434aae69bed019826ddec93f761514652a93d871e49Harald Welte (char *)c->name, c); 435aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 436aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = -ENOMEM; 437aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 438aae69bed019826ddec93f761514652a93d871e49Harald Welte } 439aae69bed019826ddec93f761514652a93d871e49Harald Welte 440aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_add_chain(h, c, offset, num); 441aae69bed019826ddec93f761514652a93d871e49Harald Welte 442aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) { 443aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = 444aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_alloc_chain_head((char *)hooknames[builtin-1], 445aae69bed019826ddec93f761514652a93d871e49Harald Welte builtin); 446aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n", 447aae69bed019826ddec93f761514652a93d871e49Harald Welte *num, offset, c, &c->rules); 448aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 449aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = -ENOMEM; 450aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 451aae69bed019826ddec93f761514652a93d871e49Harald Welte } 452aae69bed019826ddec93f761514652a93d871e49Harald Welte 453aae69bed019826ddec93f761514652a93d871e49Harald Welte c->hooknum = builtin; 454aae69bed019826ddec93f761514652a93d871e49Harald Welte 455aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_add_chain(h, c, offset, num); 456aae69bed019826ddec93f761514652a93d871e49Harald Welte 457aae69bed019826ddec93f761514652a93d871e49Harald Welte /* FIXME: this is ugly. */ 458aae69bed019826ddec93f761514652a93d871e49Harald Welte goto new_rule; 459aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 460aae69bed019826ddec93f761514652a93d871e49Harald Welte /* has to be normal rule */ 461aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 462aae69bed019826ddec93f761514652a93d871e49Harald Weltenew_rule: 463aae69bed019826ddec93f761514652a93d871e49Harald Welte 464aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, 465aae69bed019826ddec93f761514652a93d871e49Harald Welte e->next_offset))) { 466aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 467aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 468aae69bed019826ddec93f761514652a93d871e49Harald Welte } 469aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r); 470aae69bed019826ddec93f761514652a93d871e49Harald Welte 471aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index = *num; 472aae69bed019826ddec93f761514652a93d871e49Harald Welte r->offset = offset; 473aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 474aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_NORMAL_MAP; 475aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos = r->index; 476aae69bed019826ddec93f761514652a93d871e49Harald Welte 477aae69bed019826ddec93f761514652a93d871e49Harald Welte /* handling of jumps, etc. */ 478aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET)) { 479aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 480aae69bed019826ddec93f761514652a93d871e49Harald Welte 481aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 482aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->target.u.target_size 483aae69bed019826ddec93f761514652a93d871e49Harald Welte != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 484aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EINVAL; 485aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 486aae69bed019826ddec93f761514652a93d871e49Harald Welte } 487aae69bed019826ddec93f761514652a93d871e49Harald Welte 488aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->verdict < 0) { 489aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("standard, verdict=%d\n", t->verdict); 490aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_STANDARD; 491aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (t->verdict == r->offset+e->next_offset) { 492aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("fallthrough\n"); 493aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_FALLTHROUGH; 494aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 495aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("jump, target=%u\n", t->verdict); 496aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_JUMP; 497aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Jump target fixup has to be deferred 498aae69bed019826ddec93f761514652a93d871e49Harald Welte * until second pass, since we migh not 499aae69bed019826ddec93f761514652a93d871e49Harald Welte * yet have parsed the target */ 500aae69bed019826ddec93f761514652a93d871e49Harald Welte } 50152c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson } else { 50252c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson DEBUGP_C("module, target=%s\n", GET_TARGET(e)->u.user.name); 50352c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson r->type = IPTCC_R_MODULE; 504aae69bed019826ddec93f761514652a93d871e49Harald Welte } 505aae69bed019826ddec93f761514652a93d871e49Harald Welte 506aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &h->chain_iterator_cur->rules); 507aae69bed019826ddec93f761514652a93d871e49Harald Welte } 508aae69bed019826ddec93f761514652a93d871e49Harald Welteout_inc: 509aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 510aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 511e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 512e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 513aae69bed019826ddec93f761514652a93d871e49Harald Welte 514aae69bed019826ddec93f761514652a93d871e49Harald Welte/* parse an iptables blob into it's pieces */ 515aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int parse_table(TC_HANDLE_T h) 516e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 517aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *prev; 518aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int num = 0; 519aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 520aae69bed019826ddec93f761514652a93d871e49Harald Welte 521aae69bed019826ddec93f761514652a93d871e49Harald Welte /* First pass: over ruleset blob */ 522aae69bed019826ddec93f761514652a93d871e49Harald Welte ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 523aae69bed019826ddec93f761514652a93d871e49Harald Welte cache_add_entry, h, &prev, &num); 524aae69bed019826ddec93f761514652a93d871e49Harald Welte 525aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Second pass: fixup parsed data from first pass */ 526aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 527aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 528aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 529aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 530aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 531aae69bed019826ddec93f761514652a93d871e49Harald Welte 532aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type != IPTCC_R_JUMP) 533aae69bed019826ddec93f761514652a93d871e49Harald Welte continue; 534aae69bed019826ddec93f761514652a93d871e49Harald Welte 535aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 536aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_chain_by_offset(h, t->verdict); 537aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) 538aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 539aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump = c; 540aae69bed019826ddec93f761514652a93d871e49Harald Welte c->references++; 541aae69bed019826ddec93f761514652a93d871e49Harald Welte } 542aae69bed019826ddec93f761514652a93d871e49Harald Welte } 543aae69bed019826ddec93f761514652a93d871e49Harald Welte 544aae69bed019826ddec93f761514652a93d871e49Harald Welte /* FIXME: sort chains */ 545aae69bed019826ddec93f761514652a93d871e49Harald Welte 546aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 5470113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 5489e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 549aae69bed019826ddec93f761514652a93d871e49Harald Welte 550aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 551aae69bed019826ddec93f761514652a93d871e49Harald Welte * RULESET COMPILATION (cache -> blob) 552aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 553aae69bed019826ddec93f761514652a93d871e49Harald Welte 554aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Convenience structures */ 555aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_start{ 556aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY e; 557aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_error_target name; 558aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 559aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) + \ 560aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target))) 561aae69bed019826ddec93f761514652a93d871e49Harald Welte 562aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_foot { 563aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY e; 564aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET target; 565aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 566aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_FOOT_SIZE (sizeof(STRUCT_ENTRY) + \ 567aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(STRUCT_STANDARD_TARGET))) 568aae69bed019826ddec93f761514652a93d871e49Harald Welte 569aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_error { 570aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY entry; 571aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_error_target target; 572aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 573aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) + \ 574aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target))) 575aae69bed019826ddec93f761514652a93d871e49Harald Welte 576aae69bed019826ddec93f761514652a93d871e49Harald Welte 577aae69bed019826ddec93f761514652a93d871e49Harald Welte 578aae69bed019826ddec93f761514652a93d871e49Harald Welte/* compile rule from cache into blob */ 579aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int iptcc_compile_rule (TC_HANDLE_T h, STRUCT_REPLACE *repl, struct rule_head *r) 5800113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 581aae69bed019826ddec93f761514652a93d871e49Harald Welte /* handle jumps */ 582aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type == IPTCC_R_JUMP) { 583aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 584aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 585aae69bed019826ddec93f761514652a93d871e49Harald Welte /* memset for memcmp convenience on delete/replace */ 586aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 587aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(t->target.u.user.name, STANDARD_TARGET); 588aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Jumps can only happen to builtin chains, so we 589aae69bed019826ddec93f761514652a93d871e49Harald Welte * can safely assume that they always have a header */ 590aae69bed019826ddec93f761514652a93d871e49Harald Welte t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE; 591aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (r->type == IPTCC_R_FALLTHROUGH) { 592aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 593aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 594aae69bed019826ddec93f761514652a93d871e49Harald Welte t->verdict = r->offset + r->size; 595aae69bed019826ddec93f761514652a93d871e49Harald Welte } 596aae69bed019826ddec93f761514652a93d871e49Harald Welte 597aae69bed019826ddec93f761514652a93d871e49Harald Welte /* copy entry from cache to blob */ 598aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy((char *)repl->entries+r->offset, r->entry, r->size); 599aae69bed019826ddec93f761514652a93d871e49Harald Welte 600aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 601e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 602e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 603aae69bed019826ddec93f761514652a93d871e49Harald Welte/* compile chain from cache into blob */ 604aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain_head *c) 6053ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 606aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 607aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 608aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_start *head; 609aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_foot *foot; 610aae69bed019826ddec93f761514652a93d871e49Harald Welte 611aae69bed019826ddec93f761514652a93d871e49Harald Welte /* only user-defined chains have heaer */ 612aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 613aae69bed019826ddec93f761514652a93d871e49Harald Welte /* put chain header in place */ 614aae69bed019826ddec93f761514652a93d871e49Harald Welte head = (void *)repl->entries + c->head_offset; 615aae69bed019826ddec93f761514652a93d871e49Harald Welte head->e.target_offset = sizeof(STRUCT_ENTRY); 616aae69bed019826ddec93f761514652a93d871e49Harald Welte head->e.next_offset = IPTCB_CHAIN_START_SIZE; 617aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(head->name.t.u.user.name, ERROR_TARGET); 618aae69bed019826ddec93f761514652a93d871e49Harald Welte head->name.t.u.target_size = 619aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target)); 620aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(head->name.error, c->name); 621aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 622aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->hook_entry[c->hooknum-1] = c->head_offset; 623aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->underflow[c->hooknum-1] = c->foot_offset; 624aae69bed019826ddec93f761514652a93d871e49Harald Welte } 625aae69bed019826ddec93f761514652a93d871e49Harald Welte 626aae69bed019826ddec93f761514652a93d871e49Harald Welte /* iterate over rules */ 627aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 628aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_rule(h, repl, r); 629aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 630aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 631aae69bed019826ddec93f761514652a93d871e49Harald Welte } 632aae69bed019826ddec93f761514652a93d871e49Harald Welte 633aae69bed019826ddec93f761514652a93d871e49Harald Welte /* put chain footer in place */ 634aae69bed019826ddec93f761514652a93d871e49Harald Welte foot = (void *)repl->entries + c->foot_offset; 635aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->e.target_offset = sizeof(STRUCT_ENTRY); 636aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE; 637aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(foot->target.target.u.user.name, STANDARD_TARGET); 638aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.target.u.target_size = 639aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 640aae69bed019826ddec93f761514652a93d871e49Harald Welte /* builtin targets have verdict, others return */ 641aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_is_builtin(c)) 642aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.verdict = c->verdict; 643aae69bed019826ddec93f761514652a93d871e49Harald Welte else 644aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.verdict = RETURN; 645aae69bed019826ddec93f761514652a93d871e49Harald Welte /* set policy-counters */ 646aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS)); 647aae69bed019826ddec93f761514652a93d871e49Harald Welte 648aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 6493ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 6503ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 651aae69bed019826ddec93f761514652a93d871e49Harald Welte/* calculate offset and number for every rule in the cache */ 652aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_chain_offsets(TC_HANDLE_T h, struct chain_head *c, 653aae69bed019826ddec93f761514652a93d871e49Harald Welte int *offset, int *num) 6543ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 655aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 656aae69bed019826ddec93f761514652a93d871e49Harald Welte 657aae69bed019826ddec93f761514652a93d871e49Harald Welte c->head_offset = *offset; 658aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("%s: chain_head %u, offset=%u\n", c->name, *num, *offset); 659aae69bed019826ddec93f761514652a93d871e49Harald Welte 660aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 661aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Chain has header */ 662aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += sizeof(STRUCT_ENTRY) 663aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(struct ipt_error_target)); 664aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 665aae69bed019826ddec93f761514652a93d871e49Harald Welte } 666aae69bed019826ddec93f761514652a93d871e49Harald Welte 667aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 668aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("rule %u, offset=%u, index=%u\n", *num, *offset, *num); 669aae69bed019826ddec93f761514652a93d871e49Harald Welte r->offset = *offset; 670aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index = *num; 671aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += r->size; 672aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 673aae69bed019826ddec93f761514652a93d871e49Harald Welte } 674aae69bed019826ddec93f761514652a93d871e49Harald Welte 675aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num, 676aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset, *num); 677aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_offset = *offset; 678aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index = *num; 679aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += sizeof(STRUCT_ENTRY) 680aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 681aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 682aae69bed019826ddec93f761514652a93d871e49Harald Welte 683aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 6843ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 6853ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 686aae69bed019826ddec93f761514652a93d871e49Harald Welte/* put the pieces back together again */ 687aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_table_prep(TC_HANDLE_T h, unsigned int *size) 688aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 689aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 690aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset = 0, num = 0; 691aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret = 0; 6923ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 693aae69bed019826ddec93f761514652a93d871e49Harald Welte /* First pass: calculate offset for every rule */ 694aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 695aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_chain_offsets(h, c, &offset, &num); 696aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 697aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 698aae69bed019826ddec93f761514652a93d871e49Harald Welte } 699aae69bed019826ddec93f761514652a93d871e49Harald Welte 700aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Append one error rule at end of chain */ 701aae69bed019826ddec93f761514652a93d871e49Harald Welte num++; 702aae69bed019826ddec93f761514652a93d871e49Harald Welte offset += sizeof(STRUCT_ENTRY) 703aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(struct ipt_error_target)); 704aae69bed019826ddec93f761514652a93d871e49Harald Welte 705aae69bed019826ddec93f761514652a93d871e49Harald Welte /* ruleset size is now in offset */ 706aae69bed019826ddec93f761514652a93d871e49Harald Welte *size = offset; 707aae69bed019826ddec93f761514652a93d871e49Harald Welte return num; 708aae69bed019826ddec93f761514652a93d871e49Harald Welte} 709aae69bed019826ddec93f761514652a93d871e49Harald Welte 710aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE *repl) 7110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 712aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 713aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_error *error; 7140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 715aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Second pass: copy from cache to offsets, fill in jumps */ 716aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 717aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret = iptcc_compile_chain(h, repl, c); 718aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 719aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 7200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 7210113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 722aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Append error rule at end of chain */ 723aae69bed019826ddec93f761514652a93d871e49Harald Welte error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE; 724aae69bed019826ddec93f761514652a93d871e49Harald Welte error->entry.target_offset = sizeof(STRUCT_ENTRY); 725aae69bed019826ddec93f761514652a93d871e49Harald Welte error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE; 726aae69bed019826ddec93f761514652a93d871e49Harald Welte error->target.t.u.user.target_size = 727aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target)); 728aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET); 729aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy((char *)&error->target.error, "ERROR"); 730aae69bed019826ddec93f761514652a93d871e49Harald Welte 731aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 7320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 733e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 734aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 735aae69bed019826ddec93f761514652a93d871e49Harald Welte * EXTERNAL API (operates on cache only) 736aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 737aae69bed019826ddec93f761514652a93d871e49Harald Welte 738e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Allocate handle of given size */ 73979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic TC_HANDLE_T 7400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltealloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 741e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 742e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher size_t len; 74379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 744e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 745aae69bed019826ddec93f761514652a93d871e49Harald Welte len = sizeof(STRUCT_TC_HANDLE) + size; 746e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 747aae69bed019826ddec93f761514652a93d871e49Harald Welte h = malloc(sizeof(STRUCT_TC_HANDLE)); 748aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h) { 749e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 750e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 751e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 752aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(h, 0, sizeof(*h)); 753aae69bed019826ddec93f761514652a93d871e49Harald Welte INIT_LIST_HEAD(&h->chains); 754e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(h->info.name, tablename); 755aae69bed019826ddec93f761514652a93d871e49Harald Welte 7560371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size); 757aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h->entries) 758aae69bed019826ddec93f761514652a93d871e49Harald Welte goto out_free_handle; 759aae69bed019826ddec93f761514652a93d871e49Harald Welte 760aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(h->entries->name, tablename); 7610371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries->size = size; 762e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 763e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 764aae69bed019826ddec93f761514652a93d871e49Harald Welte 765aae69bed019826ddec93f761514652a93d871e49Harald Welteout_free_handle: 766aae69bed019826ddec93f761514652a93d871e49Harald Welte free(h); 767aae69bed019826ddec93f761514652a93d871e49Harald Welte 768aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 769e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 770e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 771aae69bed019826ddec93f761514652a93d871e49Harald Welte 77279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_HANDLE_T 77379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INIT(const char *tablename) 774e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 77579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 77679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 777e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int tmp; 778e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher socklen_t s; 779e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 78079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INIT; 781e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 782e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson if (sockfd != -1) { 783366454bc69f781fdafc3a30eb6dd77155ee4efb6Harald Welte close(sockfd); 784e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 785e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson } 786366454bc69f781fdafc3a30eb6dd77155ee4efb6Harald Welte 787841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson if (strlen(tablename) >= TABLE_MAXNAMELEN) { 788841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson errno = EINVAL; 789841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson return NULL; 790841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 791841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 79279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 793e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (sockfd < 0) 794e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 795e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 796e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher s = sizeof(info); 797841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 798e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(info.name, tablename); 79979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) 800e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 801e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 802aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n", 803aae69bed019826ddec93f761514652a93d871e49Harald Welte info.valid_hooks, info.num_entries, info.size); 804aae69bed019826ddec93f761514652a93d871e49Harald Welte 8050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((h = alloc_handle(info.name, info.size, info.num_entries)) 806841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson == NULL) { 807841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson close(sockfd); 808e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 809e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 810841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 811e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 812e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Initialize current state */ 813e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->info = info; 8140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 815aae69bed019826ddec93f761514652a93d871e49Harald Welte h->entries->size = h->info.size; 816e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 81779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 818e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 819aae69bed019826ddec93f761514652a93d871e49Harald Welte if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries, 820aae69bed019826ddec93f761514652a93d871e49Harald Welte &tmp) < 0) 821aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 822aae69bed019826ddec93f761514652a93d871e49Harald Welte 823aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 824aae69bed019826ddec93f761514652a93d871e49Harald Welte { 825aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_get_entries.blob", 826aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 827aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 828aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, h->entries, tmp); 829aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 830aae69bed019826ddec93f761514652a93d871e49Harald Welte } 831e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 832aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 833aae69bed019826ddec93f761514652a93d871e49Harald Welte 834aae69bed019826ddec93f761514652a93d871e49Harald Welte if (parse_table(h) < 0) 835aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 8367e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 837e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(h); 838e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 839aae69bed019826ddec93f761514652a93d871e49Harald Welteerror: 840aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_FREE(&h); 841aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 842e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 843e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 844841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefssonvoid 845841e4aed2349046eb2c0b1375139c06569a93bd0Martin JosefssonTC_FREE(TC_HANDLE_T *h) 846841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson{ 847aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c, *tmp; 848aae69bed019826ddec93f761514652a93d871e49Harald Welte 849841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson close(sockfd); 850e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 851aae69bed019826ddec93f761514652a93d871e49Harald Welte 852aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(c, tmp, &(*h)->chains, list) { 853aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *rtmp; 854aae69bed019826ddec93f761514652a93d871e49Harald Welte 855aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, rtmp, &c->rules, list) { 856aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 857aae69bed019826ddec93f761514652a93d871e49Harald Welte } 858aae69bed019826ddec93f761514652a93d871e49Harald Welte 859aae69bed019826ddec93f761514652a93d871e49Harald Welte free(c); 860aae69bed019826ddec93f761514652a93d871e49Harald Welte } 861aae69bed019826ddec93f761514652a93d871e49Harald Welte 862aae69bed019826ddec93f761514652a93d871e49Harald Welte free((*h)->entries); 863841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson free(*h); 864aae69bed019826ddec93f761514652a93d871e49Harald Welte 865841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson *h = NULL; 866841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson} 867841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 868e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 86979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellprint_match(const STRUCT_ENTRY_MATCH *m) 870e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 871228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell printf("Match name: `%s'\n", m->u.user.name); 872e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 873e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 874e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 87579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle); 87679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell 877e6869a8f59d779ff4d5a0984c86d80db7078496Marc Bouchervoid 87879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DUMP_ENTRIES(const TC_HANDLE_T handle) 879e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 880e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(handle); 881aae69bed019826ddec93f761514652a93d871e49Harald Welte#if 0 882e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("libiptc v%s. %u entries, %u bytes.\n", 88380fe35d6339b53a12ddaec41885613e4e37ed031Harald Welte IPTABLES_VERSION, 884aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->new_number, handle->entries->size); 885e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Table `%s'\n", handle->info.name); 886e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 88767088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_PRE_ROUTING], 88867088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_IN], 88967088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_FORWARD], 89067088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_OUT], 89167088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_POST_ROUTING]); 892e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 89367088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_PRE_ROUTING], 89467088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_IN], 89567088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_FORWARD], 89667088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_OUT], 89767088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_POST_ROUTING]); 898e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 899aae69bed019826ddec93f761514652a93d871e49Harald Welte ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size, 90079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell dump_entry, handle); 901aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 9020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 903e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 904e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Does this chain exist? */ 90579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle) 906e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 907aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_find_label(chain, handle) != NULL; 908e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 909e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 910aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void iptcc_chain_iterator_advance(TC_HANDLE_T handle) 911aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 912aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = handle->chain_iterator_cur; 913aae69bed019826ddec93f761514652a93d871e49Harald Welte 914aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->list.next == &handle->chains) 915aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->chain_iterator_cur = NULL; 916aae69bed019826ddec93f761514652a93d871e49Harald Welte else 917aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->chain_iterator_cur = 918aae69bed019826ddec93f761514652a93d871e49Harald Welte list_entry(c->list.next, struct chain_head, list); 919aae69bed019826ddec93f761514652a93d871e49Harald Welte} 920e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 92130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. */ 922e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 9238c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_CHAIN(TC_HANDLE_T *handle) 924e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 925aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = list_entry((*handle)->chains.next, 926aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head, list); 927aae69bed019826ddec93f761514652a93d871e49Harald Welte 928aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_CHAIN; 929aae69bed019826ddec93f761514652a93d871e49Harald Welte 930aae69bed019826ddec93f761514652a93d871e49Harald Welte 931aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&(*handle)->chains)) { 932aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no chains\n"); 9330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 934aae69bed019826ddec93f761514652a93d871e49Harald Welte } 9350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 936aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->chain_iterator_cur = c; 937aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 93830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 939aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 940aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 94130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 94230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 94330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. Returns NULL at end. */ 94430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellconst char * 94579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NEXT_CHAIN(TC_HANDLE_T *handle) 94630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 947aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = (*handle)->chain_iterator_cur; 948aae69bed019826ddec93f761514652a93d871e49Harald Welte 949aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_CHAIN; 95030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 951aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 952aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no more chains\n"); 95330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 954aae69bed019826ddec93f761514652a93d871e49Harald Welte } 95530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 956aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 957aae69bed019826ddec93f761514652a93d871e49Harald Welte 958aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 959aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 96030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 96130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 96230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Get first rule in the given chain: NULL for empty chain. */ 96379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 9648c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_RULE(const char *chain, TC_HANDLE_T *handle) 96530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 966aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 967aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 968aae69bed019826ddec93f761514652a93d871e49Harald Welte 969aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_RULE; 97030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 971aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("first rule(%s): ", chain); 972aae69bed019826ddec93f761514652a93d871e49Harald Welte 973aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 97430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!c) { 97530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell errno = ENOENT; 97630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 977e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 978e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 97930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Empty chain: single return/policy rule */ 980aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&c->rules)) { 981aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("no rules, returning NULL\n"); 98230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 983aae69bed019826ddec93f761514652a93d871e49Harald Welte } 984aae69bed019826ddec93f761514652a93d871e49Harald Welte 985aae69bed019826ddec93f761514652a93d871e49Harald Welte r = list_entry(c->rules.next, struct rule_head, list); 986aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = r; 987aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%p\n", r); 98830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 989aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 990e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 991e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 99230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Returns NULL when rules run out. */ 99379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 9948c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle) 99530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 996aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 997aae69bed019826ddec93f761514652a93d871e49Harald Welte 998aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("rule_iterator_cur=%p...", (*handle)->rule_iterator_cur); 999aae69bed019826ddec93f761514652a93d871e49Harald Welte 1000aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(*handle)->rule_iterator_cur) { 1001aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning NULL\n"); 100230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1003aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1004aae69bed019826ddec93f761514652a93d871e49Harald Welte 1005aae69bed019826ddec93f761514652a93d871e49Harald Welte r = list_entry((*handle)->rule_iterator_cur->list.next, 1006aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 100730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1008aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_RULE; 1009aae69bed019826ddec93f761514652a93d871e49Harald Welte 1010aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("next=%p, head=%p...", &r->list, 1011aae69bed019826ddec93f761514652a93d871e49Harald Welte &(*handle)->rule_iterator_cur->chain->rules); 1012aae69bed019826ddec93f761514652a93d871e49Harald Welte 1013aae69bed019826ddec93f761514652a93d871e49Harald Welte if (&r->list == &(*handle)->rule_iterator_cur->chain->rules) { 1014aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = NULL; 1015aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("finished, returning NULL\n"); 1016aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1017aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1018aae69bed019826ddec93f761514652a93d871e49Harald Welte 1019aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = r; 1020aae69bed019826ddec93f761514652a93d871e49Harald Welte 1021aae69bed019826ddec93f761514652a93d871e49Harald Welte /* NOTE: prev is without any influence ! */ 1022aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning rule %p\n", r); 1023aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 102430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 102530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1026e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* How many rules in this chain? */ 1027e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherunsigned int 102879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NUM_RULES(const char *chain, TC_HANDLE_T *handle) 1029e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1030aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1031aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NUM_RULES; 1032e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1033aae69bed019826ddec93f761514652a93d871e49Harald Welte 1034aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1035aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1036e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1037e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return (unsigned int)-1; 1038e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1039aae69bed019826ddec93f761514652a93d871e49Harald Welte 1040aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->num_rules; 1041e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1042e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 104379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY *TC_GET_RULE(const char *chain, 104479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int n, 104579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1046e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1047aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1048aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1049aae69bed019826ddec93f761514652a93d871e49Harald Welte 1050aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_RULE; 1051e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1052e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1053aae69bed019826ddec93f761514652a93d871e49Harald Welte 1054aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1055aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1056e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1057e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1058e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1059e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1060aae69bed019826ddec93f761514652a93d871e49Harald Welte r = iptcc_get_rule_num(c, n); 1061aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!r) 1062aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1063aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 1064e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1065e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1066aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 1067aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char *standard_target_map(int verdict) 1068e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1069aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (verdict) { 1070aae69bed019826ddec93f761514652a93d871e49Harald Welte case RETURN: 107179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_RETURN; 1072aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1073aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_ACCEPT-1: 107479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_ACCEPT; 1075aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1076aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_DROP-1: 1077aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_DROP; 1078aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1079aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_QUEUE-1: 1080aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_QUEUE; 1081aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1082aae69bed019826ddec93f761514652a93d871e49Harald Welte default: 1083aae69bed019826ddec93f761514652a93d871e49Harald Welte fprintf(stderr, "ERROR: %d not a valid target)\n", 1084aae69bed019826ddec93f761514652a93d871e49Harald Welte verdict); 1085aae69bed019826ddec93f761514652a93d871e49Harald Welte abort(); 1086aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1087e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1088aae69bed019826ddec93f761514652a93d871e49Harald Welte /* not reached */ 1089aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1090e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1091e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1092aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 1093aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char *TC_GET_TARGET(const STRUCT_ENTRY *ce, 1094aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T *handle) 1095e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1096aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 1097aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r = container_of(e, struct rule_head, entry); 1098e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1099aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_TARGET; 11000113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1101aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(r->type) { 1102aae69bed019826ddec93f761514652a93d871e49Harald Welte int spos; 1103aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_FALLTHROUGH: 1104aae69bed019826ddec93f761514652a93d871e49Harald Welte return ""; 1105aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1106aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_JUMP: 1107aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name); 1108aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->jump->name; 1109aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1110aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_STANDARD: 1111aae69bed019826ddec93f761514652a93d871e49Harald Welte spos = *(int *)GET_TARGET(e)->data; 1112aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, spos=%d'\n", r, spos); 1113aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(spos); 1114aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1115aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_MODULE: 1116aae69bed019826ddec93f761514652a93d871e49Harald Welte return GET_TARGET(e)->u.user.name; 1117aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 11180113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 1119aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1120aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1121aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Is this a built-in chain? Actually returns hook + 1. */ 1122aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1123aae69bed019826ddec93f761514652a93d871e49Harald WelteTC_BUILTIN(const char *chain, const TC_HANDLE_T handle) 1124aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1125aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1126aae69bed019826ddec93f761514652a93d871e49Harald Welte 1127aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_BUILTIN; 11280113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1129aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, handle); 1130aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1131aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1132aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 11330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 11340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1135aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_is_builtin(c); 11360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 11370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1138aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Get the policy of a given built-in chain */ 1139aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char * 1140aae69bed019826ddec93f761514652a93d871e49Harald WelteTC_GET_POLICY(const char *chain, 1141aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters, 1142aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T *handle) 11430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 1144aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 11450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1146aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_POLICY; 1147fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte 1148aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("called for chain %s\n", chain); 11490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1150aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1151aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1152aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1153aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 11540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 11550113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1156aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) 1157aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 11580113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1159aae69bed019826ddec93f761514652a93d871e49Harald Welte *counters = c->counters; 11600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1161aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(c->verdict); 11620113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 1163e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1164e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1165aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_standard_map(struct rule_head *r, int verdict) 1166e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1167aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 116879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 1169e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 117079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1171e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 117267088e73ce7707229c56987868f112051defca5aRusty Russell if (t->target.u.target_size 11738c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1174e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1175e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1176e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1177e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset for memcmp convenience on delete/replace */ 117879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 117979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell strcpy(t->target.u.user.name, STANDARD_TARGET); 1180e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = verdict; 1181e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1182aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_STANDARD; 1183aae69bed019826ddec93f761514652a93d871e49Harald Welte 1184e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1185e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 11867e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1187e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1188aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_map_target(const TC_HANDLE_T handle, 1189aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r) 1190e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1191aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 11920113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 1193e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1194e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's empty (=> fall through) */ 1195aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(t->u.user.name, "") == 0) { 1196aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_FALLTHROUGH; 1197aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1198aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1199e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's a standard target name... */ 120079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 1201aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_ACCEPT - 1); 120279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 1203aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_DROP - 1); 120467088e73ce7707229c56987868f112051defca5aRusty Russell else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 1205aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_QUEUE - 1); 120679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 1207aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, RETURN); 120879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (TC_BUILTIN(t->u.user.name, handle)) { 1209e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Can't jump to builtins. */ 1210e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1211e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1212e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 1213e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's an existing chain name. */ 1214aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1215aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("trying to find chain `%s': ", t->u.user.name); 1216aae69bed019826ddec93f761514652a93d871e49Harald Welte 1217aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(t->u.user.name, handle); 1218aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c) { 1219aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("found!\n"); 1220aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_JUMP; 1221aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump = c; 1222aae69bed019826ddec93f761514652a93d871e49Harald Welte c->references++; 1223aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1224aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1225aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("not found :(\n"); 1226e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1227e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1228e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Must be a module? If not, kernel will reject... */ 1229e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset to all 0 for your memcmp convenience. */ 1230228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell memset(t->u.user.name + strlen(t->u.user.name), 1231e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 0, 123279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell FUNCTION_MAXNAMELEN - strlen(t->u.user.name)); 1233e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1234aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(handle); 1235aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1236e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1237e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 12380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 1239e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 124079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 124179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 124279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 124379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1244e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1245aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1246aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *prev; 1247e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 124879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INSERT_ENTRY; 1249aae69bed019826ddec93f761514652a93d871e49Harald Welte 1250aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1251e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1252e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1253e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1254e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1255aae69bed019826ddec93f761514652a93d871e49Harald Welte prev = iptcc_get_rule_num(c, rulenum); 1256aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!prev) { 1257e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1258e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1259e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1260e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1261aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1262aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1263aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1264aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1265aae69bed019826ddec93f761514652a93d871e49Harald Welte 1266aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1267aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1268aae69bed019826ddec93f761514652a93d871e49Harald Welte 1269aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 1270aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 12710113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1272aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1273aae69bed019826ddec93f761514652a93d871e49Harald Welte 1274aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &prev->list); 1275aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1276aae69bed019826ddec93f761514652a93d871e49Harald Welte 1277aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1278e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1279aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1280e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1281e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1282e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 1283e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 128479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 128579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 128679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 128779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1288e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1289aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1290aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *old; 1291e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 129279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_REPLACE_ENTRY; 1293e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1294aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1295e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1296e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1297e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1298e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1299aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(old = iptcc_get_rule_num(c, rulenum))) { 1300e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1301e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1302e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1303e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1304aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1305aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1306e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1307aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1308aae69bed019826ddec93f761514652a93d871e49Harald Welte 1309aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1310aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1311e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1312aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 1313aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 13140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1315aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1316aae69bed019826ddec93f761514652a93d871e49Harald Welte 1317aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add(&r->list, &old->list); 1318aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(old); 13190113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1320aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1321aae69bed019826ddec93f761514652a93d871e49Harald Welte 1322aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1323e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1324e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13250113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Append entry `fw' to chain `chain'. Equivalent to insert with 1326e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher rulenum = length of chain. */ 1327e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 132879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 132979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 133079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1331e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1332aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1333aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1334e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 133579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_APPEND_ENTRY; 1336aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1337aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to find chain `%s'\n", chain); 1338e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1339e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1340e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1341e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1342aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1343aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to allocate rule for chain `%s'\n", chain); 1344aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1345aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1346aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1347aae69bed019826ddec93f761514652a93d871e49Harald Welte 1348aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1349aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1350aae69bed019826ddec93f761514652a93d871e49Harald Welte 1351aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 1352aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to ma target of rule for chain `%s'\n", chain); 1353aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 13540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1355aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1356aae69bed019826ddec93f761514652a93d871e49Harald Welte 1357aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &c->rules); 1358aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1359aae69bed019826ddec93f761514652a93d871e49Harald Welte 1360aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 13610113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1362aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1363e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1364e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1365e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 136679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellmatch_different(const STRUCT_ENTRY_MATCH *a, 1367edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *a_elems, 1368edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_elems, 1369edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned char **maskptr) 1370e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 137179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY_MATCH *b; 1372edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1373e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1374e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Offset of b is the same as a. */ 137530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell b = (void *)b_elems + ((unsigned char *)a - a_elems); 1376e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1377228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (a->u.match_size != b->u.match_size) 1378e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1379e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1380228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (strcmp(a->u.user.name, b->u.user.name) != 0) 1381e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1382e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 138373ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell *maskptr += ALIGN(sizeof(*a)); 1384edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 138573ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1386edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1387edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 1; 1388edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell *maskptr += i; 1389edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 0; 1390edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell} 1391edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 1392edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russellstatic inline int 1393edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russelltarget_different(const unsigned char *a_targdata, 1394edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_targdata, 1395edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int tdatasize, 1396edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *mask) 1397edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell{ 1398edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1399edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell for (i = 0; i < tdatasize; i++) 1400edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a_targdata[i] ^ b_targdata[i]) & mask[i]) != 0) 140190e712a00913fe2a2f885142439c392392dc08a8Rusty Russell return 1; 1402e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1403e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1404e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1405e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 140679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic int 140779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellis_same(const STRUCT_ENTRY *a, 140879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *b, 140979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask); 1410e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 14110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Delete the first rule in `chain' which matches `fw'. */ 1412e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 141379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_ENTRY(const IPT_CHAINLABEL chain, 141479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *origfw, 141579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask, 141679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1417e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1418aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1419fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte struct rule_head *r; 14200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY *e, *fw; 1421e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 142279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_ENTRY; 1423aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1424e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1425e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1426e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1427e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 14280113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte fw = malloc(origfw->next_offset); 14290113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (fw == NULL) { 14300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = ENOMEM; 14310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 14320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 14330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1434fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte list_for_each_entry(r, &c->rules, list) { 14350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 14360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(fw, origfw, origfw->next_offset); 14370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1438fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte#if 0 14390113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* FIXME: handle this in is_same --RR */ 14400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!map_target(*handle, fw, offset, &discard)) { 14410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte free(fw); 14420113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 14430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 14440113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte#endif 1445fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 1446fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte e = r->entry; 1447fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 14480113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (is_same(e, fw, matchmask)) { 1449fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte /* If we are about to delete the rule that is the 1450fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte * current iterator, move rule iterator back. next 1451fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte * pointer will then point to real next node */ 1452fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte if (r == (*handle)->rule_iterator_cur) { 1453fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte (*handle)->rule_iterator_cur = 1454fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte list_entry((*handle)->rule_iterator_cur->list.prev, 1455fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte struct rule_head, list); 1456fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte } 1457fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 1458fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte c->num_rules--; 1459fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte iptcc_delete_rule(r); 1460fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte return 1; 1461e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1462e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1463e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 14640113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte free(fw); 1465e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1466e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 14677e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell} 1468aae69bed019826ddec93f761514652a93d871e49Harald Welte 1469e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1470e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Delete the rule in position `rulenum' in `chain'. */ 1471e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 147279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 147379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 147479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1475e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1476aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1477aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1478e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 147979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_NUM_ENTRY; 1480aae69bed019826ddec93f761514652a93d871e49Harald Welte 1481aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1482e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1483e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1484e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1485e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1486aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 1487e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1488e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1489e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1490e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1491aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the rule that is the current 1492aae69bed019826ddec93f761514652a93d871e49Harald Welte * iterator, move rule iterator back. next pointer will then 1493aae69bed019826ddec93f761514652a93d871e49Harald Welte * point to real next node */ 1494aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r == (*handle)->rule_iterator_cur) { 1495aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = 1496aae69bed019826ddec93f761514652a93d871e49Harald Welte list_entry((*handle)->rule_iterator_cur->list.prev, 1497aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 14980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 1499e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1500aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules--; 1501aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 1502aae69bed019826ddec93f761514652a93d871e49Harald Welte 1503aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1504e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1505e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1506e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Check the packet `fw' on chain `chain'. Returns the verdict, or 1507e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher NULL and sets errno. */ 1508e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 150979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CHECK_PACKET(const IPT_CHAINLABEL chain, 151079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *entry, 151179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1512e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1513e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOSYS; 1514e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1515e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1516e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1517e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Flushes the entries in the given chain (ie. empties chain). */ 1518e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 151979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1520e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1521aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1522aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *tmp; 1523e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 15240113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte iptc_fn = TC_FLUSH_ENTRIES; 1525aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1526e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1527e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1528e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1529e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1530aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, tmp, &c->rules, list) { 1531aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 1532aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1533aae69bed019826ddec93f761514652a93d871e49Harald Welte 1534aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules = 0; 1535aae69bed019826ddec93f761514652a93d871e49Harald Welte 1536aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1537aae69bed019826ddec93f761514652a93d871e49Harald Welte 1538aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1539e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1540e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1541e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Zeroes the counters in a chain. */ 1542e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 154379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1544e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1545aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1546aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 15477e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1548aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1549e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1550e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1551e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1552e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1553aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 1554aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 1555aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 1556e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1557aae69bed019826ddec93f761514652a93d871e49Harald Welte 1558175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1559e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1560e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1561e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1562e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 15631cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteSTRUCT_COUNTERS * 15641cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_READ_COUNTER(const IPT_CHAINLABEL chain, 15651cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 15661cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 15671cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1568aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1569aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 15701cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 15711cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_READ_COUNTER; 15721cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 15731cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1574aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 15751cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 15761cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return NULL; 15771cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 15781cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1579aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 15800113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 15810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 15820113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 15830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1584aae69bed019826ddec93f761514652a93d871e49Harald Welte return &r->entry[0].counters; 15851cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 15861cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 15871cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 15881cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 15891cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 15901cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 15911cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1592aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1593aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 15941cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 15951cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_ZERO_COUNTER; 15961cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 15971cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1598aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 15991cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 16001cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 16011cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 16021cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1603aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 16040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 16050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 16060113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 16070113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1608aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 1609aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 16101cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16111cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 16121cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16131cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 16141cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 16151cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16161cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 16171cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_SET_COUNTER(const IPT_CHAINLABEL chain, 16181cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 16191cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 16201cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 16211cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1622aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1623aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 16241cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 16251cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16261cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_SET_COUNTER; 16271cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 16281cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1629aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 16301cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 16311cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 16321cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 16330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1634aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 16350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 16360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 16370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 16380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1639aae69bed019826ddec93f761514652a93d871e49Harald Welte e = r->entry; 1640aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 16410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 16420113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 16431cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16441cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 16451cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16461cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 16471cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 16481cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1649e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Creates a new chain. */ 1650e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* To create a chain, create two rules: error node and unconditional 1651e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * return. */ 1652e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 165379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1654e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1655aae69bed019826ddec93f761514652a93d871e49Harald Welte static struct chain_head *c; 1656e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 165779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_CREATE_CHAIN; 1658e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1659e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* find_label doesn't cover built-in targets: DROP, ACCEPT, 1660e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher QUEUE, RETURN. */ 1661aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_find_label(chain, *handle) 166279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_DROP) == 0 166379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_ACCEPT) == 0 166467088e73ce7707229c56987868f112051defca5aRusty Russell || strcmp(chain, LABEL_QUEUE) == 0 166579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_RETURN) == 0) { 1666aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain `%s' already exists\n", chain); 1667e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1668e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1669e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1670e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 167179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 1672aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain name `%s' too long\n", chain); 1673e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1674e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1675e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1676e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1677aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_alloc_chain_head(chain, 0); 1678aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1679aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Cannot allocate memory for chain `%s'\n", chain); 1680aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1681aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1682e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1683aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1684e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1685aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Creating chain `%s'\n", chain); 1686aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&c->list, &(*handle)->chains); 1687e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1688aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1689e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1690aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1691e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1692e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1693e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get the number of references to this chain. */ 1694e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 169579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 169679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1697e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1698aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1699e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1700aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1701e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1702e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1703e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1704e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1705aae69bed019826ddec93f761514652a93d871e49Harald Welte *ref = c->references; 1706aae69bed019826ddec93f761514652a93d871e49Harald Welte 1707e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1708e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1709e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1710e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Deletes a chain. */ 1711e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 171279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1713e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1714e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int references; 1715aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 17167e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 171779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_CHAIN; 1718e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1719aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1720aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 1721aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1722aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1723aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1724aae69bed019826ddec93f761514652a93d871e49Harald Welte 172579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (TC_BUILTIN(chain, *handle)) { 1726aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot remove builtin chain `%s'\n", chain); 1727e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1728e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1729e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1730e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1731aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!TC_GET_REFERENCES(&references, chain, handle)) { 1732aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot get references on chain `%s'\n", chain); 1733e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1734e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1735e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1736aae69bed019826ddec93f761514652a93d871e49Harald Welte if (references > 0) { 1737aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' still has references\n", chain); 1738aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EMLINK; 1739e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1740e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1741e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1742aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->num_rules) { 1743aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' is not empty\n", chain); 1744e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOTEMPTY; 1745e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1746e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1747e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1748aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the chain that is the current 1749aae69bed019826ddec93f761514652a93d871e49Harald Welte * iterator, move chain iterator firward. */ 1750aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c == (*handle)->chain_iterator_cur) 1751aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 1752aae69bed019826ddec93f761514652a93d871e49Harald Welte 1753aae69bed019826ddec93f761514652a93d871e49Harald Welte list_del(&c->list); 1754aae69bed019826ddec93f761514652a93d871e49Harald Welte free(c); 17550113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1756aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' deleted\n", chain); 17570113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1758aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1759aae69bed019826ddec93f761514652a93d871e49Harald Welte 1760aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1761e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1762e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1763e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Renames a chain. */ 176479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 176579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL newname, 176679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1767e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1768aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 176979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_RENAME_CHAIN; 1770e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 17711de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte /* find_label doesn't cover built-in targets: DROP, ACCEPT, 17721de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte QUEUE, RETURN. */ 1773aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_find_label(newname, *handle) 177479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_DROP) == 0 177579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_ACCEPT) == 0 17761de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte || strcmp(newname, LABEL_QUEUE) == 0 177779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_RETURN) == 0) { 1778e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1779e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1780e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1781e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1782aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(oldname, *handle)) 178379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || TC_BUILTIN(oldname, *handle)) { 1784e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1785e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1786e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1787e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 178879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 1789e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1790e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1791e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1792e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1793aae69bed019826ddec93f761514652a93d871e49Harald Welte strncpy(c->name, newname, sizeof(IPT_CHAINLABEL)); 1794aae69bed019826ddec93f761514652a93d871e49Harald Welte 17950113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte set_changed(*handle); 17960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1797e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1798e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1799e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1800e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Sets the policy on a built-in chain. */ 1801e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 180279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_SET_POLICY(const IPT_CHAINLABEL chain, 180379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL policy, 18041cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 180579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1806e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1807aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1808e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 180979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_SET_POLICY; 1810aae69bed019826ddec93f761514652a93d871e49Harald Welte 1811aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1812aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 1813c8264991454b5e77279830736f80ea3153b6f814Marc Boucher errno = ENOENT; 1814e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1815aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1816e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1817aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 1818aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain); 1819aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 18209e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte return 0; 18219e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte } 18229e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 182379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(policy, LABEL_ACCEPT) == 0) 1824aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_ACCEPT - 1; 182579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(policy, LABEL_DROP) == 0) 1826aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_DROP - 1; 1827e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else { 1828e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1829e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1830e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 18311cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 18321cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (counters) { 18331cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte /* set byte and packet counters */ 1834aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS)); 1835aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_SET; 18361cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } else { 1837aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_NOMAP; 18381cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 18391cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1840175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1841e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1842e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1843e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1844e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1845e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Without this, on gcc 2.7.2.3, we get: 184679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell libiptc.c: In function `TC_COMMIT': 1847e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher libiptc.c:833: fixed or forbidden register was spilled. 1848e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher This may be due to a compiler bug or to impossible asm 1849e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher statements or clauses. 1850e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher*/ 1851e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 185279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellsubtract_counters(STRUCT_COUNTERS *answer, 185379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *a, 185479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *b) 1855e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1856e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->pcnt = a->pcnt - b->pcnt; 1857e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->bcnt = a->bcnt - b->bcnt; 1858e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1859e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1860aae69bed019826ddec93f761514652a93d871e49Harald Welte 1861aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, 1862aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index) 1863aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1864aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->counters[index] = ((STRUCT_COUNTERS) { 0, 0}); 1865aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NOMAP => zero\n"); 1866aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1867aae69bed019826ddec93f761514652a93d871e49Harald Welte 1868aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters, 1869aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_REPLACE *repl, 1870aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 1871aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int mappos) 1872aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1873aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 1874aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 1875aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 1876aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: X + Y + Z. 1877aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in X + Y 1878aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in replacement read. 1879aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 1880aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->counters[index] = repl->counters[mappos]; 1881aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos); 1882aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1883aae69bed019826ddec93f761514652a93d871e49Harald Welte 1884aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters, 1885aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_REPLACE *repl, 1886aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 1887aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int mappos, 1888aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters) 1889aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1890aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 1891aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 1892aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 1893aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: Y + Z. 1894aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in Y. 1895aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in (replacement read - original read). 1896aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 1897aae69bed019826ddec93f761514652a93d871e49Harald Welte subtract_counters(&newcounters->counters[index], 1898aae69bed019826ddec93f761514652a93d871e49Harald Welte &repl->counters[mappos], 1899aae69bed019826ddec93f761514652a93d871e49Harald Welte counters); 1900aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("ZEROED => mappos %u\n", mappos); 1901aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1902aae69bed019826ddec93f761514652a93d871e49Harald Welte 1903aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_set(STRUCT_COUNTERS_INFO *newcounters, 1904aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 1905aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters) 1906aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1907aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Want to set counter (iptables-restore) */ 1908aae69bed019826ddec93f761514652a93d871e49Harald Welte 1909aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&newcounters->counters[index], counters, 1910aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(STRUCT_COUNTERS)); 1911aae69bed019826ddec93f761514652a93d871e49Harald Welte 1912aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("SET\n"); 1913aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1914aae69bed019826ddec93f761514652a93d871e49Harald Welte 1915aae69bed019826ddec93f761514652a93d871e49Harald Welte 1916e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 191779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_COMMIT(TC_HANDLE_T *handle) 1918e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1919e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Replace, then map back the counters. */ 192079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_REPLACE *repl; 192179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_COUNTERS_INFO *newcounters; 1922aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1923aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 1924841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson size_t counterlen; 1925aae69bed019826ddec93f761514652a93d871e49Harald Welte int new_number; 1926aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int new_size; 1927e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1928e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1929841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 1930e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#if 0 193154c307e0ff401f40a6fe382af4ae5bff0f5b40baRusty Russell TC_DUMP_ENTRIES(*handle); 1932e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#endif 1933e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1934e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Don't commit if nothing changed. */ 1935e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!(*handle)->changed) 1936e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher goto finished; 1937e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1938aae69bed019826ddec93f761514652a93d871e49Harald Welte new_number = iptcc_compile_table_prep(*handle, &new_size); 1939aae69bed019826ddec93f761514652a93d871e49Harald Welte if (new_number < 0) { 1940aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1941aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1942aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1943aae69bed019826ddec93f761514652a93d871e49Harald Welte 1944aae69bed019826ddec93f761514652a93d871e49Harald Welte repl = malloc(sizeof(*repl) + new_size); 1945e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl) { 1946e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1947e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1948e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1949aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(repl, 0, sizeof(*repl)); 1950aae69bed019826ddec93f761514652a93d871e49Harald Welte 1951aae69bed019826ddec93f761514652a93d871e49Harald Welte counterlen = sizeof(STRUCT_COUNTERS_INFO) 1952aae69bed019826ddec93f761514652a93d871e49Harald Welte + sizeof(STRUCT_COUNTERS) * new_number; 1953e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1954e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the old counters we will get from kernel */ 195579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell repl->counters = malloc(sizeof(STRUCT_COUNTERS) 1956e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * (*handle)->info.num_entries); 1957e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl->counters) { 1958e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1959e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1960e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1961e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1962e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the counters we're going to put back, later. */ 1963e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters = malloc(counterlen); 1964e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!newcounters) { 1965e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 1966e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1967e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1968e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1969e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1970aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(newcounters, 0, counterlen); 1971e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1972e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(repl->name, (*handle)->info.name); 1973aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries = new_number; 1974aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->size = new_size; 1975aae69bed019826ddec93f761514652a93d871e49Harald Welte 1976e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->num_counters = (*handle)->info.num_entries; 1977e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->valid_hooks = (*handle)->info.valid_hooks; 1978aae69bed019826ddec93f761514652a93d871e49Harald Welte 1979aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("num_entries=%u, size=%u, num_counters=%u\n", 1980aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries, repl->size, repl->num_counters); 1981aae69bed019826ddec93f761514652a93d871e49Harald Welte 1982aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_table(*handle, repl); 1983aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) { 1984aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ret; 1985aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl->counters); 1986aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl); 1987aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1988aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1989aae69bed019826ddec93f761514652a93d871e49Harald Welte 1990aae69bed019826ddec93f761514652a93d871e49Harald Welte 1991aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 1992aae69bed019826ddec93f761514652a93d871e49Harald Welte { 1993aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_set_replace.blob", 1994aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 1995aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 1996aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, repl, sizeof(*repl) + repl->size); 1997aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 1998aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1999aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2000aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2001e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 200279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 2003aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(*repl) + repl->size) < 0) { 2004e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2005e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2006e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2007e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2008e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2009e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2010e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Put counters back. */ 2011e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(newcounters->name, (*handle)->info.name); 2012aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->num_counters = new_number; 2013aae69bed019826ddec93f761514652a93d871e49Harald Welte 2014aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &(*handle)->chains, list) { 2015aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 2016aae69bed019826ddec93f761514652a93d871e49Harald Welte 2017aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Builtin chains have their own counters */ 2018aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_is_builtin(c)) { 2019aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for chain-index %u: ", c->foot_index); 2020aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(c->counter_map.maptype) { 2021aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2022aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, c->foot_index); 2023aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2024aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2025aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2026aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index, 2027aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos); 2028aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2029aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2030aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2031aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index, 2032aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos, 2033aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2034aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2035aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2036aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, c->foot_index, 2037aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2038aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2039aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2040aae69bed019826ddec93f761514652a93d871e49Harald Welte } 20411cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2042aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 2043aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for index %u: ", r->index); 2044aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (r->counter_map.maptype) { 2045aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2046aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, r->index); 2047aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2048aae69bed019826ddec93f761514652a93d871e49Harald Welte 2049aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2050aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2051aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index, 2052aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos); 2053aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2054aae69bed019826ddec93f761514652a93d871e49Harald Welte 2055aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2056aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2057aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index, 2058aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos, 2059aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2060aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2061aae69bed019826ddec93f761514652a93d871e49Harald Welte 2062aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2063aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, r->index, 2064aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2065aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2066aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2067e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2068e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 206962527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell 2070aae69bed019826ddec93f761514652a93d871e49Harald Welte 207162527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell#ifdef KERNEL_64_USERSPACE_32 207262527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell { 207362527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell /* Kernel will think that pointer should be 64-bits, and get 207462527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell padding. So we accomodate here (assumption: alignment of 207562527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell `counters' is on 64-bit boundary). */ 207662527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell u_int64_t *kernptr = (u_int64_t *)&newcounters->counters; 207762527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell if ((unsigned long)&newcounters->counters % 8 != 0) { 207862527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell fprintf(stderr, 207962527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell "counters alignment incorrect! Mail rusty!\n"); 208062527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell abort(); 208162527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell } 208262527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell *kernptr = newcounters->counters; 208354c307e0ff401f40a6fe382af4ae5bff0f5b40baRusty Russell } 208462527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell#endif /* KERNEL_64_USERSPACE_32 */ 2085e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2086aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 2087aae69bed019826ddec93f761514652a93d871e49Harald Welte { 2088aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_set_add_counters.blob", 2089aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 2090aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 2091aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, newcounters, counterlen); 2092aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 2093aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2094aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2095aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2096aae69bed019826ddec93f761514652a93d871e49Harald Welte 209779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 209879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell newcounters, counterlen) < 0) { 2099e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2100e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2101e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2102e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2103e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2104e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2105e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2106e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2107e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2108e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2109e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher finished: 2110841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson TC_FREE(handle); 2111e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2112e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2113e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2114e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get raw socket. */ 2115e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 211679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_RAW_SOCKET() 2117e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2118e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return sockfd; 2119e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2120e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2121e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Translates errno numbers into more human-readable form than strerror. */ 2122e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 212379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_STRERROR(int err) 2124e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2125e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 2126e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct table_struct { 2127e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher void *fn; 2128e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int err; 2129e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char *message; 2130e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } table [] = 21314ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 213279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INIT, EINVAL, "Module is wrong version" }, 21334ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_INIT, ENOENT, 21344ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Table does not exist (do you need to insmod?)" }, 213579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 213679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 213779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EMLINK, 2138e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher "Can't delete chain with references left" }, 213979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 214079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 214179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 214279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 21431cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 21441cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 214579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 214679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 2147e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* EINVAL for CHECK probably means bad interface. */ 214879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CHECK_PACKET, EINVAL, 2149c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad arguments (does that interface exist?)" }, 21504ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_CHECK_PACKET, ENOSYS, 21514ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Checking will most likely never get implemented" }, 2152e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* ENOENT for DELETE probably means no matching rule */ 215379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_ENTRY, ENOENT, 2154c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad rule (does a matching rule exist in that chain?)" }, 215579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, ENOENT, 2156c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad built-in chain name" }, 215779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, EINVAL, 2158c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad policy name" }, 21594ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte 21604ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, 0, "Incompatible with this kernel" }, 21614ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 21624ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 21634ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOMEM, "Memory allocation problem" }, 21644ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOENT, "No chain/target/match by that name" }, 2165e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher }; 2166e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2167e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 2168e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((!table[i].fn || table[i].fn == iptc_fn) 2169e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && table[i].err == err) 2170e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return table[i].message; 2171e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2172e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2173e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return strerror(err); 2174e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2175