libiptc.c revision 1336451ead58d608618ff5b0a251d132b73f9866
10f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson/* Library which manipulates firewall rules. Version $Revision$ */ 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 47e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int sockfd = -1; 48664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Patesstatic int sockfd_use = 0; 49e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void *iptc_fn = NULL; 50e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 510b63936140032deac44072951451bdf47b54296aPatrick McHardystatic const char *hooknames[] = { 520b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_PRE_ROUTING] = "PREROUTING", 530b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_LOCAL_IN] = "INPUT", 540b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_FORWARD] = "FORWARD", 550b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_LOCAL_OUT] = "OUTPUT", 560b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_POST_ROUTING] = "POSTROUTING", 5710758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell#ifdef HOOK_DROPPING 580b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_DROPPING] = "DROPPING" 5910758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell#endif 60e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 61e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 62aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Convenience structures */ 63aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct ipt_error_target 64aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 65aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY_TARGET t; 66aae69bed019826ddec93f761514652a93d871e49Harald Welte char error[TABLE_MAXNAMELEN]; 67aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 68aae69bed019826ddec93f761514652a93d871e49Harald Welte 69aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct chain_head; 70aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct rule_head; 71aae69bed019826ddec93f761514652a93d871e49Harald Welte 72e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstruct counter_map 73e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 74e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher enum { 75e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_NOMAP, 76e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_NORMAL_MAP, 771cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte COUNTER_MAP_ZEROED, 781cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte COUNTER_MAP_SET 79e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } maptype; 80e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int mappos; 81e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 82e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 83aae69bed019826ddec93f761514652a93d871e49Harald Welteenum iptcc_rule_type { 84aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_STANDARD, /* standard target (ACCEPT, ...) */ 85aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_MODULE, /* extension module (SNAT, ...) */ 86aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_FALLTHROUGH, /* fallthrough rule */ 87aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_JUMP, /* jump to other chain */ 88aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 89aae69bed019826ddec93f761514652a93d871e49Harald Welte 90aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct rule_head 91e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 92aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head list; 93aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *chain; 94aae69bed019826ddec93f761514652a93d871e49Harald Welte struct counter_map counter_map; 95aae69bed019826ddec93f761514652a93d871e49Harald Welte 96aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index; /* index (needed for counter_map) */ 97aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset; /* offset in rule blob */ 98aae69bed019826ddec93f761514652a93d871e49Harald Welte 99aae69bed019826ddec93f761514652a93d871e49Harald Welte enum iptcc_rule_type type; 100aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *jump; /* jump target, if IPTCC_R_JUMP */ 101aae69bed019826ddec93f761514652a93d871e49Harald Welte 102aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int size; /* size of entry data */ 103aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY entry[0]; 104e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 105e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 106aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct chain_head 10730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 108aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head list; 10979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell char name[TABLE_MAXNAMELEN]; 110aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int hooknum; /* hook number+1 if builtin */ 111aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int references; /* how many jumps reference us */ 112aae69bed019826ddec93f761514652a93d871e49Harald Welte int verdict; /* verdict if builtin */ 113aae69bed019826ddec93f761514652a93d871e49Harald Welte 114aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS counters; /* per-chain counters */ 115aae69bed019826ddec93f761514652a93d871e49Harald Welte struct counter_map counter_map; 116aae69bed019826ddec93f761514652a93d871e49Harald Welte 117aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int num_rules; /* number of rules in list */ 118aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head rules; /* list of rules */ 119aae69bed019826ddec93f761514652a93d871e49Harald Welte 120aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index; /* index (needed for jump resolval) */ 121aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int head_offset; /* offset in rule blob */ 122aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int foot_index; /* index (needed for counter_map) */ 123aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int foot_offset; /* offset in rule blob */ 12430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell}; 12530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 12679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellSTRUCT_TC_HANDLE 127e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 128aae69bed019826ddec93f761514652a93d871e49Harald Welte int changed; /* Have changes been made? */ 129aae69bed019826ddec93f761514652a93d871e49Harald Welte 130aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head chains; 131aae69bed019826ddec93f761514652a93d871e49Harald Welte 132aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *chain_iterator_cur; 133aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *rule_iterator_cur; 134aae69bed019826ddec93f761514652a93d871e49Harald Welte 13579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 136aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_GET_ENTRIES *entries; 137aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 138e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 139aae69bed019826ddec93f761514652a93d871e49Harald Welte/* allocate a new chain head for the cache */ 140aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct chain_head *iptcc_alloc_chain_head(const char *name, int hooknum) 141aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 142aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = malloc(sizeof(*c)); 143aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) 144aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 145aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(c, 0, sizeof(*c)); 146aae69bed019826ddec93f761514652a93d871e49Harald Welte 147aae69bed019826ddec93f761514652a93d871e49Harald Welte strncpy(c->name, name, TABLE_MAXNAMELEN); 148aae69bed019826ddec93f761514652a93d871e49Harald Welte c->hooknum = hooknum; 149aae69bed019826ddec93f761514652a93d871e49Harald Welte INIT_LIST_HEAD(&c->rules); 150e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 151aae69bed019826ddec93f761514652a93d871e49Harald Welte return c; 152aae69bed019826ddec93f761514652a93d871e49Harald Welte} 15330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 154aae69bed019826ddec93f761514652a93d871e49Harald Welte/* allocate and initialize a new rule for the cache */ 155aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct rule_head *iptcc_alloc_rule(struct chain_head *c, unsigned int size) 156aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 157aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r = malloc(sizeof(*r)+size); 158aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!r) 159aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 160aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(r, 0, sizeof(*r)); 16130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 162aae69bed019826ddec93f761514652a93d871e49Harald Welte r->chain = c; 163aae69bed019826ddec93f761514652a93d871e49Harald Welte r->size = size; 164175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 165aae69bed019826ddec93f761514652a93d871e49Harald Welte return r; 166aae69bed019826ddec93f761514652a93d871e49Harald Welte} 167e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 168aae69bed019826ddec93f761514652a93d871e49Harald Welte/* notify us that the ruleset has been modified by the user */ 169175f64177743e5a417e98d483ef995bf7151f3bcRusty Russellstatic void 17079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellset_changed(TC_HANDLE_T h) 171175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell{ 172175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell h->changed = 1; 173175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell} 174175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 175380ba5f3074a16fbaa8869d9594962d58b5f8608Harald Welte#ifdef IPTC_DEBUG 17679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic void do_check(TC_HANDLE_T h, unsigned int line); 177849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell#define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0) 17830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#else 17930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#define CHECK(h) 18030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#endif 181e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 182aae69bed019826ddec93f761514652a93d871e49Harald Welte 183aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 184aae69bed019826ddec93f761514652a93d871e49Harald Welte * iptc blob utility functions (iptcb_*) 185aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 186aae69bed019826ddec93f761514652a93d871e49Harald Welte 187e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 188aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_get_number(const STRUCT_ENTRY *i, 18979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *seek, 190e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int *pos) 191e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 192e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (i == seek) 193e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 194e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*pos)++; 195e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 196e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 197e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 198aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int 199aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_get_entry_n(STRUCT_ENTRY *i, 200aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int number, 201aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int *pos, 202aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY **pe) 203aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 204aae69bed019826ddec93f761514652a93d871e49Harald Welte if (*pos == number) { 205aae69bed019826ddec93f761514652a93d871e49Harald Welte *pe = i; 206aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 207aae69bed019826ddec93f761514652a93d871e49Harald Welte } 208aae69bed019826ddec93f761514652a93d871e49Harald Welte (*pos)++; 209aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 210aae69bed019826ddec93f761514652a93d871e49Harald Welte} 211aae69bed019826ddec93f761514652a93d871e49Harald Welte 212aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline STRUCT_ENTRY * 213aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_get_entry(TC_HANDLE_T h, unsigned int offset) 214aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 215aae69bed019826ddec93f761514652a93d871e49Harald Welte return (STRUCT_ENTRY *)((char *)h->entries->entrytable + offset); 216aae69bed019826ddec93f761514652a93d871e49Harald Welte} 217aae69bed019826ddec93f761514652a93d871e49Harald Welte 218e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic unsigned int 219aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_entry2index(const TC_HANDLE_T h, const STRUCT_ENTRY *seek) 220e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 221e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int pos = 0; 222e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 223aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 224aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcb_get_number, seek, &pos) == 0) { 225a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson fprintf(stderr, "ERROR: offset %u not an entry!\n", 226aae69bed019826ddec93f761514652a93d871e49Harald Welte (unsigned int)((char *)seek - (char *)h->entries->entrytable)); 227e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 228e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 229e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return pos; 230e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 231e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 232aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline STRUCT_ENTRY * 233aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_offset2entry(TC_HANDLE_T h, unsigned int offset) 234e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 235aae69bed019826ddec93f761514652a93d871e49Harald Welte return (STRUCT_ENTRY *) ((void *)h->entries->entrytable+offset); 236aae69bed019826ddec93f761514652a93d871e49Harald Welte} 237aae69bed019826ddec93f761514652a93d871e49Harald Welte 238aae69bed019826ddec93f761514652a93d871e49Harald Welte 239aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline unsigned long 240aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_entry2offset(const TC_HANDLE_T h, const STRUCT_ENTRY *e) 241aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 242aae69bed019826ddec93f761514652a93d871e49Harald Welte return (void *)e - (void *)h->entries->entrytable; 243aae69bed019826ddec93f761514652a93d871e49Harald Welte} 244aae69bed019826ddec93f761514652a93d871e49Harald Welte 245aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline unsigned int 246aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_offset2index(const TC_HANDLE_T h, unsigned int offset) 247aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 248aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcb_entry2index(h, iptcb_offset2entry(h, offset)); 249aae69bed019826ddec93f761514652a93d871e49Harald Welte} 250aae69bed019826ddec93f761514652a93d871e49Harald Welte 251aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns 0 if not hook entry, else hooknumber + 1 */ 252aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline unsigned int 253aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_ent_is_hook_entry(STRUCT_ENTRY *e, TC_HANDLE_T h) 254aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 255aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int i; 256aae69bed019826ddec93f761514652a93d871e49Harald Welte 257aae69bed019826ddec93f761514652a93d871e49Harald Welte for (i = 0; i < NUMHOOKS; i++) { 258aae69bed019826ddec93f761514652a93d871e49Harald Welte if ((h->info.valid_hooks & (1 << i)) 259aae69bed019826ddec93f761514652a93d871e49Harald Welte && iptcb_get_entry(h, h->info.hook_entry[i]) == e) 260aae69bed019826ddec93f761514652a93d871e49Harald Welte return i+1; 261aae69bed019826ddec93f761514652a93d871e49Harald Welte } 262aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 263aae69bed019826ddec93f761514652a93d871e49Harald Welte} 264aae69bed019826ddec93f761514652a93d871e49Harald Welte 265aae69bed019826ddec93f761514652a93d871e49Harald Welte 266aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 267aae69bed019826ddec93f761514652a93d871e49Harald Welte * iptc cache utility functions (iptcc_*) 268aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 269aae69bed019826ddec93f761514652a93d871e49Harald Welte 270aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Is the given chain builtin (1) or user-defined (0) */ 271aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic unsigned int iptcc_is_builtin(struct chain_head *c) 272aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 273aae69bed019826ddec93f761514652a93d871e49Harald Welte return (c->hooknum ? 1 : 0); 274aae69bed019826ddec93f761514652a93d871e49Harald Welte} 275aae69bed019826ddec93f761514652a93d871e49Harald Welte 276aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Get a specific rule within a chain */ 277aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct rule_head *iptcc_get_rule_num(struct chain_head *c, 278aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int rulenum) 279aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 280aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 281aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int num = 0; 282aae69bed019826ddec93f761514652a93d871e49Harald Welte 283aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 284aae69bed019826ddec93f761514652a93d871e49Harald Welte num++; 285aae69bed019826ddec93f761514652a93d871e49Harald Welte if (num == rulenum) 286aae69bed019826ddec93f761514652a93d871e49Harald Welte return r; 287aae69bed019826ddec93f761514652a93d871e49Harald Welte } 288aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 289aae69bed019826ddec93f761514652a93d871e49Harald Welte} 290aae69bed019826ddec93f761514652a93d871e49Harald Welte 291a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson/* Get a specific rule within a chain backwards */ 292a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefssonstatic struct rule_head *iptcc_get_rule_num_reverse(struct chain_head *c, 293a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson unsigned int rulenum) 294a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson{ 295a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson struct rule_head *r; 296a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson unsigned int num = 0; 297a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson 298a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson list_for_each_entry_reverse(r, &c->rules, list) { 299a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson num++; 300a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson if (num == rulenum) 301a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson return r; 302a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } 303a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson return NULL; 304a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson} 305a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson 306aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns chain head if found, otherwise NULL. */ 307aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct chain_head * 308aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_find_chain_by_offset(TC_HANDLE_T handle, unsigned int offset) 309aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 310aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head *pos; 311aae69bed019826ddec93f761514652a93d871e49Harald Welte 312aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&handle->chains)) 313aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 314aae69bed019826ddec93f761514652a93d871e49Harald Welte 315aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each(pos, &handle->chains) { 316aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = list_entry(pos, struct chain_head, list); 317aae69bed019826ddec93f761514652a93d871e49Harald Welte if (offset >= c->head_offset && offset <= c->foot_offset) 318aae69bed019826ddec93f761514652a93d871e49Harald Welte return c; 319aae69bed019826ddec93f761514652a93d871e49Harald Welte } 320aae69bed019826ddec93f761514652a93d871e49Harald Welte 321aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 322aae69bed019826ddec93f761514652a93d871e49Harald Welte} 323aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns chain head if found, otherwise NULL. */ 324aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct chain_head * 325aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_find_label(const char *name, TC_HANDLE_T handle) 326aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 327aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head *pos; 328aae69bed019826ddec93f761514652a93d871e49Harald Welte 329aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&handle->chains)) 330aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 331aae69bed019826ddec93f761514652a93d871e49Harald Welte 332aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each(pos, &handle->chains) { 333aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = list_entry(pos, struct chain_head, list); 334aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!strcmp(c->name, name)) 335aae69bed019826ddec93f761514652a93d871e49Harald Welte return c; 336aae69bed019826ddec93f761514652a93d871e49Harald Welte } 337aae69bed019826ddec93f761514652a93d871e49Harald Welte 338aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 339aae69bed019826ddec93f761514652a93d871e49Harald Welte} 340aae69bed019826ddec93f761514652a93d871e49Harald Welte 341aae69bed019826ddec93f761514652a93d871e49Harald Welte/* called when rule is to be removed from cache */ 342aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void iptcc_delete_rule(struct rule_head *r) 343aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 344aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("deleting rule %p (offset %u)\n", r, r->offset); 345aae69bed019826ddec93f761514652a93d871e49Harald Welte /* clean up reference count of called chain */ 346aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type == IPTCC_R_JUMP 347aae69bed019826ddec93f761514652a93d871e49Harald Welte && r->jump) 348aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump->references--; 349aae69bed019826ddec93f761514652a93d871e49Harald Welte 350aae69bed019826ddec93f761514652a93d871e49Harald Welte list_del(&r->list); 351aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 352aae69bed019826ddec93f761514652a93d871e49Harald Welte} 353aae69bed019826ddec93f761514652a93d871e49Harald Welte 354aae69bed019826ddec93f761514652a93d871e49Harald Welte 355aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 356aae69bed019826ddec93f761514652a93d871e49Harald Welte * RULESET PARSER (blob -> cache) 357aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 358aae69bed019826ddec93f761514652a93d871e49Harald Welte 359aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Delete policy rule of previous chain, since cache doesn't contain 360aae69bed019826ddec93f761514652a93d871e49Harald Welte * chain policy rules. 361aae69bed019826ddec93f761514652a93d871e49Harald Welte * WARNING: This function has ugly design and relies on a lot of context, only 362aae69bed019826ddec93f761514652a93d871e49Harald Welte * to be called from specific places within the parser */ 363aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int __iptcc_p_del_policy(TC_HANDLE_T h, unsigned int num) 364aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 365aae69bed019826ddec93f761514652a93d871e49Harald Welte if (h->chain_iterator_cur) { 366aae69bed019826ddec93f761514652a93d871e49Harald Welte /* policy rule is last rule */ 367aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *pr = (struct rule_head *) 368aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->rules.prev; 369aae69bed019826ddec93f761514652a93d871e49Harald Welte 370aae69bed019826ddec93f761514652a93d871e49Harald Welte /* save verdict */ 371aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->verdict = 372aae69bed019826ddec93f761514652a93d871e49Harald Welte *(int *)GET_TARGET(pr->entry)->data; 373aae69bed019826ddec93f761514652a93d871e49Harald Welte 374aae69bed019826ddec93f761514652a93d871e49Harald Welte /* save counter and counter_map information */ 375aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->counter_map.maptype = 376aae69bed019826ddec93f761514652a93d871e49Harald Welte COUNTER_MAP_NORMAL_MAP; 377aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->counter_map.mappos = num-1; 378aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters, 379aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(h->chain_iterator_cur->counters)); 380aae69bed019826ddec93f761514652a93d871e49Harald Welte 381aae69bed019826ddec93f761514652a93d871e49Harald Welte /* foot_offset points to verdict rule */ 382aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->foot_index = num; 383aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->foot_offset = pr->offset; 384aae69bed019826ddec93f761514652a93d871e49Harald Welte 385aae69bed019826ddec93f761514652a93d871e49Harald Welte /* delete rule from cache */ 386aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(pr); 3878d1b38a064d146c77eb8fc951717663e1a713cfcMartin Josefsson h->chain_iterator_cur->num_rules--; 388aae69bed019826ddec93f761514652a93d871e49Harald Welte 389e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 390e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 391e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 392e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 393e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 394ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte/* alphabetically insert a chain into the list */ 395ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Weltestatic inline void iptc_insert_chain(TC_HANDLE_T h, struct chain_head *c) 396ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte{ 397ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte struct chain_head *tmp; 398ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte 3999d3ed77341361674994f584ff69a61f31a342739Olaf Rempel /* sort only user defined chains */ 4009d3ed77341361674994f584ff69a61f31a342739Olaf Rempel if (!c->hooknum) { 4019d3ed77341361674994f584ff69a61f31a342739Olaf Rempel list_for_each_entry(tmp, &h->chains, list) { 402feca0578a5d035122b4b7cdb8d44d6cca819f35cRobert de Barth if (!tmp->hooknum && strcmp(c->name, tmp->name) <= 0) { 4039d3ed77341361674994f584ff69a61f31a342739Olaf Rempel list_add(&c->list, tmp->list.prev); 4049d3ed77341361674994f584ff69a61f31a342739Olaf Rempel return; 4059d3ed77341361674994f584ff69a61f31a342739Olaf Rempel } 406ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte } 407ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte } 408ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte 409ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte /* survived till end of list: add at tail */ 410ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte list_add_tail(&c->list, &h->chains); 411ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte} 412ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte 413aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Another ugly helper function split out of cache_add_entry to make it less 414aae69bed019826ddec93f761514652a93d871e49Harald Welte * spaghetti code */ 415aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void __iptcc_p_add_chain(TC_HANDLE_T h, struct chain_head *c, 416aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset, unsigned int *num) 417e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 4181336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer struct list_head *tail = h->chains.prev; 4191336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer struct chain_head *ctail; 4201336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer 421aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_del_policy(h, *num); 422e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 423aae69bed019826ddec93f761514652a93d871e49Harald Welte c->head_offset = offset; 424aae69bed019826ddec93f761514652a93d871e49Harald Welte c->index = *num; 425e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 4261336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer /* Chains from kernel are already sorted, as they are inserted 4271336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer * sorted. But there exists an issue when shifting to 1.4.0 4281336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer * from an older version, as old versions allow last created 4291336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer * chain to be unsorted. 4301336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer */ 4311336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer if (iptcc_is_builtin(c)) /* Only user defined chains are sorted*/ 4321336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer list_add_tail(&c->list, &h->chains); 4331336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer else { 4341336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer ctail = list_entry(tail, struct chain_head, list); 4351336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer if (strcmp(c->name, ctail->name) > 0) 4361336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer list_add_tail(&c->list, &h->chains);/* Already sorted*/ 4371336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer else 4381336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer iptc_insert_chain(h, c);/* Was not sorted */ 4391336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer } 440d8cb787ab44e9d2de4fd3b04fcaa370c9918fc5dJesper Dangaard Brouer 441aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur = c; 442e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 443e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 444aae69bed019826ddec93f761514652a93d871e49Harald Welte/* main parser function: add an entry from the blob to the cache */ 445aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int cache_add_entry(STRUCT_ENTRY *e, 446aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T h, 447aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY **prev, 448aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int *num) 449e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 450aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int builtin; 451aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset = (char *)e - (char *)h->entries->entrytable; 452aae69bed019826ddec93f761514652a93d871e49Harald Welte 453aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("entering..."); 454aae69bed019826ddec93f761514652a93d871e49Harald Welte 455aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Last entry ("policy rule"). End it.*/ 456aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcb_entry2offset(h,e) + e->next_offset == h->entries->size) { 457aae69bed019826ddec93f761514652a93d871e49Harald Welte /* This is the ERROR node at the end of the chain */ 458aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u: end of table:\n", *num, offset); 459aae69bed019826ddec93f761514652a93d871e49Harald Welte 460aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_del_policy(h, *num); 461aae69bed019826ddec93f761514652a93d871e49Harald Welte 462aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur = NULL; 463aae69bed019826ddec93f761514652a93d871e49Harald Welte goto out_inc; 464aae69bed019826ddec93f761514652a93d871e49Harald Welte } 465aae69bed019826ddec93f761514652a93d871e49Harald Welte 466aae69bed019826ddec93f761514652a93d871e49Harald Welte /* We know this is the start of a new chain if it's an ERROR 467aae69bed019826ddec93f761514652a93d871e49Harald Welte * target, or a hook entry point */ 468aae69bed019826ddec93f761514652a93d871e49Harald Welte 469aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) { 470aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = 471aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0); 472aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset, 473aae69bed019826ddec93f761514652a93d871e49Harald Welte (char *)c->name, c); 474aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 475aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = -ENOMEM; 476aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 477aae69bed019826ddec93f761514652a93d871e49Harald Welte } 478aae69bed019826ddec93f761514652a93d871e49Harald Welte 479aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_add_chain(h, c, offset, num); 480aae69bed019826ddec93f761514652a93d871e49Harald Welte 481aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) { 482aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = 483aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_alloc_chain_head((char *)hooknames[builtin-1], 484aae69bed019826ddec93f761514652a93d871e49Harald Welte builtin); 485aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n", 486aae69bed019826ddec93f761514652a93d871e49Harald Welte *num, offset, c, &c->rules); 487aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 488aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = -ENOMEM; 489aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 490aae69bed019826ddec93f761514652a93d871e49Harald Welte } 491aae69bed019826ddec93f761514652a93d871e49Harald Welte 492aae69bed019826ddec93f761514652a93d871e49Harald Welte c->hooknum = builtin; 493aae69bed019826ddec93f761514652a93d871e49Harald Welte 494aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_add_chain(h, c, offset, num); 495aae69bed019826ddec93f761514652a93d871e49Harald Welte 496aae69bed019826ddec93f761514652a93d871e49Harald Welte /* FIXME: this is ugly. */ 497aae69bed019826ddec93f761514652a93d871e49Harald Welte goto new_rule; 498aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 499aae69bed019826ddec93f761514652a93d871e49Harald Welte /* has to be normal rule */ 500aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 501aae69bed019826ddec93f761514652a93d871e49Harald Weltenew_rule: 502aae69bed019826ddec93f761514652a93d871e49Harald Welte 503aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, 504aae69bed019826ddec93f761514652a93d871e49Harald Welte e->next_offset))) { 505aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 506aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 507aae69bed019826ddec93f761514652a93d871e49Harald Welte } 508aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r); 509aae69bed019826ddec93f761514652a93d871e49Harald Welte 510aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index = *num; 511aae69bed019826ddec93f761514652a93d871e49Harald Welte r->offset = offset; 512aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 513aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_NORMAL_MAP; 514aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos = r->index; 515aae69bed019826ddec93f761514652a93d871e49Harald Welte 516aae69bed019826ddec93f761514652a93d871e49Harald Welte /* handling of jumps, etc. */ 517aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET)) { 518aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 519aae69bed019826ddec93f761514652a93d871e49Harald Welte 520aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 521aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->target.u.target_size 522aae69bed019826ddec93f761514652a93d871e49Harald Welte != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 523aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EINVAL; 524aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 525aae69bed019826ddec93f761514652a93d871e49Harald Welte } 526aae69bed019826ddec93f761514652a93d871e49Harald Welte 527aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->verdict < 0) { 528aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("standard, verdict=%d\n", t->verdict); 529aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_STANDARD; 530aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (t->verdict == r->offset+e->next_offset) { 531aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("fallthrough\n"); 532aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_FALLTHROUGH; 533aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 534aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("jump, target=%u\n", t->verdict); 535aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_JUMP; 536aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Jump target fixup has to be deferred 537aae69bed019826ddec93f761514652a93d871e49Harald Welte * until second pass, since we migh not 538aae69bed019826ddec93f761514652a93d871e49Harald Welte * yet have parsed the target */ 539aae69bed019826ddec93f761514652a93d871e49Harald Welte } 54052c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson } else { 54152c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson DEBUGP_C("module, target=%s\n", GET_TARGET(e)->u.user.name); 54252c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson r->type = IPTCC_R_MODULE; 543aae69bed019826ddec93f761514652a93d871e49Harald Welte } 544aae69bed019826ddec93f761514652a93d871e49Harald Welte 545aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &h->chain_iterator_cur->rules); 5468d1b38a064d146c77eb8fc951717663e1a713cfcMartin Josefsson h->chain_iterator_cur->num_rules++; 547aae69bed019826ddec93f761514652a93d871e49Harald Welte } 548aae69bed019826ddec93f761514652a93d871e49Harald Welteout_inc: 549aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 550aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 551e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 552e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 553aae69bed019826ddec93f761514652a93d871e49Harald Welte 554aae69bed019826ddec93f761514652a93d871e49Harald Welte/* parse an iptables blob into it's pieces */ 555aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int parse_table(TC_HANDLE_T h) 556e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 557aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *prev; 558aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int num = 0; 559aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 560aae69bed019826ddec93f761514652a93d871e49Harald Welte 561aae69bed019826ddec93f761514652a93d871e49Harald Welte /* First pass: over ruleset blob */ 562aae69bed019826ddec93f761514652a93d871e49Harald Welte ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 563aae69bed019826ddec93f761514652a93d871e49Harald Welte cache_add_entry, h, &prev, &num); 564aae69bed019826ddec93f761514652a93d871e49Harald Welte 565aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Second pass: fixup parsed data from first pass */ 566aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 567aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 568aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 569aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 570aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 571aae69bed019826ddec93f761514652a93d871e49Harald Welte 572aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type != IPTCC_R_JUMP) 573aae69bed019826ddec93f761514652a93d871e49Harald Welte continue; 574aae69bed019826ddec93f761514652a93d871e49Harald Welte 575aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 576aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_chain_by_offset(h, t->verdict); 577aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) 578aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 579aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump = c; 580aae69bed019826ddec93f761514652a93d871e49Harald Welte c->references++; 581aae69bed019826ddec93f761514652a93d871e49Harald Welte } 582aae69bed019826ddec93f761514652a93d871e49Harald Welte } 583aae69bed019826ddec93f761514652a93d871e49Harald Welte 584aae69bed019826ddec93f761514652a93d871e49Harald Welte /* FIXME: sort chains */ 585aae69bed019826ddec93f761514652a93d871e49Harald Welte 586aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 5870113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 5889e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 589aae69bed019826ddec93f761514652a93d871e49Harald Welte 590aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 591aae69bed019826ddec93f761514652a93d871e49Harald Welte * RULESET COMPILATION (cache -> blob) 592aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 593aae69bed019826ddec93f761514652a93d871e49Harald Welte 594aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Convenience structures */ 595aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_start{ 596aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY e; 597aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_error_target name; 598aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 599aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) + \ 600aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target))) 601aae69bed019826ddec93f761514652a93d871e49Harald Welte 602aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_foot { 603aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY e; 604aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET target; 605aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 606aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_FOOT_SIZE (sizeof(STRUCT_ENTRY) + \ 607aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(STRUCT_STANDARD_TARGET))) 608aae69bed019826ddec93f761514652a93d871e49Harald Welte 609aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_error { 610aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY entry; 611aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_error_target target; 612aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 613aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) + \ 614aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target))) 615aae69bed019826ddec93f761514652a93d871e49Harald Welte 616aae69bed019826ddec93f761514652a93d871e49Harald Welte 617aae69bed019826ddec93f761514652a93d871e49Harald Welte 618aae69bed019826ddec93f761514652a93d871e49Harald Welte/* compile rule from cache into blob */ 619aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int iptcc_compile_rule (TC_HANDLE_T h, STRUCT_REPLACE *repl, struct rule_head *r) 6200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 621aae69bed019826ddec93f761514652a93d871e49Harald Welte /* handle jumps */ 622aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type == IPTCC_R_JUMP) { 623aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 624aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 625aae69bed019826ddec93f761514652a93d871e49Harald Welte /* memset for memcmp convenience on delete/replace */ 626aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 627aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(t->target.u.user.name, STANDARD_TARGET); 628aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Jumps can only happen to builtin chains, so we 629aae69bed019826ddec93f761514652a93d871e49Harald Welte * can safely assume that they always have a header */ 630aae69bed019826ddec93f761514652a93d871e49Harald Welte t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE; 631aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (r->type == IPTCC_R_FALLTHROUGH) { 632aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 633aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 634aae69bed019826ddec93f761514652a93d871e49Harald Welte t->verdict = r->offset + r->size; 635aae69bed019826ddec93f761514652a93d871e49Harald Welte } 636aae69bed019826ddec93f761514652a93d871e49Harald Welte 637aae69bed019826ddec93f761514652a93d871e49Harald Welte /* copy entry from cache to blob */ 638aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy((char *)repl->entries+r->offset, r->entry, r->size); 639aae69bed019826ddec93f761514652a93d871e49Harald Welte 640aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 641e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 642e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 643aae69bed019826ddec93f761514652a93d871e49Harald Welte/* compile chain from cache into blob */ 644aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain_head *c) 6453ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 646aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 647aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 648aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_start *head; 649aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_foot *foot; 650aae69bed019826ddec93f761514652a93d871e49Harald Welte 651aae69bed019826ddec93f761514652a93d871e49Harald Welte /* only user-defined chains have heaer */ 652aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 653aae69bed019826ddec93f761514652a93d871e49Harald Welte /* put chain header in place */ 654aae69bed019826ddec93f761514652a93d871e49Harald Welte head = (void *)repl->entries + c->head_offset; 655aae69bed019826ddec93f761514652a93d871e49Harald Welte head->e.target_offset = sizeof(STRUCT_ENTRY); 656aae69bed019826ddec93f761514652a93d871e49Harald Welte head->e.next_offset = IPTCB_CHAIN_START_SIZE; 657aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(head->name.t.u.user.name, ERROR_TARGET); 658aae69bed019826ddec93f761514652a93d871e49Harald Welte head->name.t.u.target_size = 659aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target)); 660aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(head->name.error, c->name); 661aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 662aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->hook_entry[c->hooknum-1] = c->head_offset; 663aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->underflow[c->hooknum-1] = c->foot_offset; 664aae69bed019826ddec93f761514652a93d871e49Harald Welte } 665aae69bed019826ddec93f761514652a93d871e49Harald Welte 666aae69bed019826ddec93f761514652a93d871e49Harald Welte /* iterate over rules */ 667aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 668aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_rule(h, repl, r); 669aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 670aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 671aae69bed019826ddec93f761514652a93d871e49Harald Welte } 672aae69bed019826ddec93f761514652a93d871e49Harald Welte 673aae69bed019826ddec93f761514652a93d871e49Harald Welte /* put chain footer in place */ 674aae69bed019826ddec93f761514652a93d871e49Harald Welte foot = (void *)repl->entries + c->foot_offset; 675aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->e.target_offset = sizeof(STRUCT_ENTRY); 676aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE; 677aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(foot->target.target.u.user.name, STANDARD_TARGET); 678aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.target.u.target_size = 679aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 680aae69bed019826ddec93f761514652a93d871e49Harald Welte /* builtin targets have verdict, others return */ 681aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_is_builtin(c)) 682aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.verdict = c->verdict; 683aae69bed019826ddec93f761514652a93d871e49Harald Welte else 684aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.verdict = RETURN; 685aae69bed019826ddec93f761514652a93d871e49Harald Welte /* set policy-counters */ 686aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS)); 687aae69bed019826ddec93f761514652a93d871e49Harald Welte 688aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 6893ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 6903ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 691aae69bed019826ddec93f761514652a93d871e49Harald Welte/* calculate offset and number for every rule in the cache */ 692aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_chain_offsets(TC_HANDLE_T h, struct chain_head *c, 693efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte unsigned int *offset, unsigned int *num) 6943ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 695aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 696aae69bed019826ddec93f761514652a93d871e49Harald Welte 697aae69bed019826ddec93f761514652a93d871e49Harald Welte c->head_offset = *offset; 698aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("%s: chain_head %u, offset=%u\n", c->name, *num, *offset); 699aae69bed019826ddec93f761514652a93d871e49Harald Welte 700aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 701aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Chain has header */ 702aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += sizeof(STRUCT_ENTRY) 703aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(struct ipt_error_target)); 704aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 705aae69bed019826ddec93f761514652a93d871e49Harald Welte } 706aae69bed019826ddec93f761514652a93d871e49Harald Welte 707aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 708aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("rule %u, offset=%u, index=%u\n", *num, *offset, *num); 709aae69bed019826ddec93f761514652a93d871e49Harald Welte r->offset = *offset; 710aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index = *num; 711aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += r->size; 712aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 713aae69bed019826ddec93f761514652a93d871e49Harald Welte } 714aae69bed019826ddec93f761514652a93d871e49Harald Welte 715aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num, 716aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset, *num); 717aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_offset = *offset; 718aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index = *num; 719aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += sizeof(STRUCT_ENTRY) 720aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 721aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 722aae69bed019826ddec93f761514652a93d871e49Harald Welte 723aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 7243ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 7253ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 726aae69bed019826ddec93f761514652a93d871e49Harald Welte/* put the pieces back together again */ 727aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_table_prep(TC_HANDLE_T h, unsigned int *size) 728aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 729aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 730aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset = 0, num = 0; 731aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret = 0; 7323ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 733aae69bed019826ddec93f761514652a93d871e49Harald Welte /* First pass: calculate offset for every rule */ 734aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 735aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_chain_offsets(h, c, &offset, &num); 736aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 737aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 738aae69bed019826ddec93f761514652a93d871e49Harald Welte } 739aae69bed019826ddec93f761514652a93d871e49Harald Welte 740aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Append one error rule at end of chain */ 741aae69bed019826ddec93f761514652a93d871e49Harald Welte num++; 742aae69bed019826ddec93f761514652a93d871e49Harald Welte offset += sizeof(STRUCT_ENTRY) 743aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(struct ipt_error_target)); 744aae69bed019826ddec93f761514652a93d871e49Harald Welte 745aae69bed019826ddec93f761514652a93d871e49Harald Welte /* ruleset size is now in offset */ 746aae69bed019826ddec93f761514652a93d871e49Harald Welte *size = offset; 747aae69bed019826ddec93f761514652a93d871e49Harald Welte return num; 748aae69bed019826ddec93f761514652a93d871e49Harald Welte} 749aae69bed019826ddec93f761514652a93d871e49Harald Welte 750aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE *repl) 7510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 752aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 753aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_error *error; 7540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 755aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Second pass: copy from cache to offsets, fill in jumps */ 756aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 757aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret = iptcc_compile_chain(h, repl, c); 758aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 759aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 7600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 7610113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 762aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Append error rule at end of chain */ 763aae69bed019826ddec93f761514652a93d871e49Harald Welte error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE; 764aae69bed019826ddec93f761514652a93d871e49Harald Welte error->entry.target_offset = sizeof(STRUCT_ENTRY); 765aae69bed019826ddec93f761514652a93d871e49Harald Welte error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE; 766aae69bed019826ddec93f761514652a93d871e49Harald Welte error->target.t.u.user.target_size = 767aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target)); 768aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET); 769aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy((char *)&error->target.error, "ERROR"); 770aae69bed019826ddec93f761514652a93d871e49Harald Welte 771aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 7720113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 773e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 774aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 775aae69bed019826ddec93f761514652a93d871e49Harald Welte * EXTERNAL API (operates on cache only) 776aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 777aae69bed019826ddec93f761514652a93d871e49Harald Welte 778e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Allocate handle of given size */ 77979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic TC_HANDLE_T 7800113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltealloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 781e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 782e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher size_t len; 78379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 784e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 785aae69bed019826ddec93f761514652a93d871e49Harald Welte len = sizeof(STRUCT_TC_HANDLE) + size; 786e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 787aae69bed019826ddec93f761514652a93d871e49Harald Welte h = malloc(sizeof(STRUCT_TC_HANDLE)); 788aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h) { 789e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 790e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 791e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 792aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(h, 0, sizeof(*h)); 793aae69bed019826ddec93f761514652a93d871e49Harald Welte INIT_LIST_HEAD(&h->chains); 794e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(h->info.name, tablename); 795aae69bed019826ddec93f761514652a93d871e49Harald Welte 7960371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size); 797aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h->entries) 798aae69bed019826ddec93f761514652a93d871e49Harald Welte goto out_free_handle; 799aae69bed019826ddec93f761514652a93d871e49Harald Welte 800aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(h->entries->name, tablename); 8010371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries->size = size; 802e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 803e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 804aae69bed019826ddec93f761514652a93d871e49Harald Welte 805aae69bed019826ddec93f761514652a93d871e49Harald Welteout_free_handle: 806aae69bed019826ddec93f761514652a93d871e49Harald Welte free(h); 807aae69bed019826ddec93f761514652a93d871e49Harald Welte 808aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 809e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 810e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 811aae69bed019826ddec93f761514652a93d871e49Harald Welte 81279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_HANDLE_T 81379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INIT(const char *tablename) 814e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 81579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 81679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 817efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte unsigned int tmp; 818e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher socklen_t s; 819e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 82079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INIT; 821e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 822841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson if (strlen(tablename) >= TABLE_MAXNAMELEN) { 823841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson errno = EINVAL; 824841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson return NULL; 825841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 826841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 827664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (sockfd_use == 0) { 828664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 829664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (sockfd < 0) 830664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates return NULL; 831664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 832664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates sockfd_use++; 833e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 834e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher s = sizeof(info); 835841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 836e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(info.name, tablename); 837664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) { 838664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (--sockfd_use == 0) { 839664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates close(sockfd); 840664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates sockfd = -1; 841664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 842e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 843664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 844e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 845aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n", 846aae69bed019826ddec93f761514652a93d871e49Harald Welte info.valid_hooks, info.num_entries, info.size); 847aae69bed019826ddec93f761514652a93d871e49Harald Welte 8480113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((h = alloc_handle(info.name, info.size, info.num_entries)) 849841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson == NULL) { 850664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (--sockfd_use == 0) { 851664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates close(sockfd); 852664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates sockfd = -1; 853664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 854e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 855841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 856e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 857e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Initialize current state */ 858e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->info = info; 8590113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 860aae69bed019826ddec93f761514652a93d871e49Harald Welte h->entries->size = h->info.size; 861e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 86279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 863e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 864aae69bed019826ddec93f761514652a93d871e49Harald Welte if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries, 865aae69bed019826ddec93f761514652a93d871e49Harald Welte &tmp) < 0) 866aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 867aae69bed019826ddec93f761514652a93d871e49Harald Welte 868aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 869aae69bed019826ddec93f761514652a93d871e49Harald Welte { 870aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_get_entries.blob", 871aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 872aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 873aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, h->entries, tmp); 874aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 875aae69bed019826ddec93f761514652a93d871e49Harald Welte } 876e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 877aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 878aae69bed019826ddec93f761514652a93d871e49Harald Welte 879aae69bed019826ddec93f761514652a93d871e49Harald Welte if (parse_table(h) < 0) 880aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 8817e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 882e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(h); 883e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 884aae69bed019826ddec93f761514652a93d871e49Harald Welteerror: 885aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_FREE(&h); 886aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 887e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 888e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 889841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefssonvoid 890841e4aed2349046eb2c0b1375139c06569a93bd0Martin JosefssonTC_FREE(TC_HANDLE_T *h) 891841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson{ 892aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c, *tmp; 893aae69bed019826ddec93f761514652a93d871e49Harald Welte 894664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_FREE; 895664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (--sockfd_use == 0) { 896664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates close(sockfd); 897664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates sockfd = -1; 898664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 899aae69bed019826ddec93f761514652a93d871e49Harald Welte 900aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(c, tmp, &(*h)->chains, list) { 901aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *rtmp; 902aae69bed019826ddec93f761514652a93d871e49Harald Welte 903aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, rtmp, &c->rules, list) { 904aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 905aae69bed019826ddec93f761514652a93d871e49Harald Welte } 906aae69bed019826ddec93f761514652a93d871e49Harald Welte 907aae69bed019826ddec93f761514652a93d871e49Harald Welte free(c); 908aae69bed019826ddec93f761514652a93d871e49Harald Welte } 909aae69bed019826ddec93f761514652a93d871e49Harald Welte 910aae69bed019826ddec93f761514652a93d871e49Harald Welte free((*h)->entries); 911841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson free(*h); 912aae69bed019826ddec93f761514652a93d871e49Harald Welte 913841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson *h = NULL; 914841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson} 915841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 916e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 91779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellprint_match(const STRUCT_ENTRY_MATCH *m) 918e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 919228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell printf("Match name: `%s'\n", m->u.user.name); 920e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 921e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 922e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 92379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle); 92479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell 925e6869a8f59d779ff4d5a0984c86d80db7078496Marc Bouchervoid 92679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DUMP_ENTRIES(const TC_HANDLE_T handle) 927e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 928664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_DUMP_ENTRIES; 929e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(handle); 93097fb2f1579f0794377db1dca7c5bb07fade1a0dcPatrick McHardy 931e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell printf("libiptc v%s. %u bytes.\n", 932e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell IPTABLES_VERSION, handle->entries->size); 933e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Table `%s'\n", handle->info.name); 934e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 93567088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_PRE_ROUTING], 93667088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_IN], 93767088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_FORWARD], 93867088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_OUT], 93967088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_POST_ROUTING]); 940e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 94167088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_PRE_ROUTING], 94267088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_IN], 94367088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_FORWARD], 94467088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_OUT], 94567088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_POST_ROUTING]); 946e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 947aae69bed019826ddec93f761514652a93d871e49Harald Welte ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size, 94879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell dump_entry, handle); 9490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 950e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 951e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Does this chain exist? */ 95279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle) 953e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 954664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_IS_CHAIN; 955aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_find_label(chain, handle) != NULL; 956e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 957e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 958aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void iptcc_chain_iterator_advance(TC_HANDLE_T handle) 959aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 960aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = handle->chain_iterator_cur; 961aae69bed019826ddec93f761514652a93d871e49Harald Welte 962aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->list.next == &handle->chains) 963aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->chain_iterator_cur = NULL; 964aae69bed019826ddec93f761514652a93d871e49Harald Welte else 965aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->chain_iterator_cur = 966aae69bed019826ddec93f761514652a93d871e49Harald Welte list_entry(c->list.next, struct chain_head, list); 967aae69bed019826ddec93f761514652a93d871e49Harald Welte} 968e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 96930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. */ 970e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 9718c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_CHAIN(TC_HANDLE_T *handle) 972e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 973aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = list_entry((*handle)->chains.next, 974aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head, list); 975aae69bed019826ddec93f761514652a93d871e49Harald Welte 976aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_CHAIN; 977aae69bed019826ddec93f761514652a93d871e49Harald Welte 978aae69bed019826ddec93f761514652a93d871e49Harald Welte 979aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&(*handle)->chains)) { 980aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no chains\n"); 9810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 982aae69bed019826ddec93f761514652a93d871e49Harald Welte } 9830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 984aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->chain_iterator_cur = c; 985aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 98630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 987aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 988aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 98930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 99030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 99130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. Returns NULL at end. */ 99230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellconst char * 99379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NEXT_CHAIN(TC_HANDLE_T *handle) 99430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 995aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = (*handle)->chain_iterator_cur; 996aae69bed019826ddec93f761514652a93d871e49Harald Welte 997aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_CHAIN; 99830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 999aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1000aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no more chains\n"); 100130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1002aae69bed019826ddec93f761514652a93d871e49Harald Welte } 100330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1004aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 1005aae69bed019826ddec93f761514652a93d871e49Harald Welte 1006aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 1007aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 100830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 100930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 101030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Get first rule in the given chain: NULL for empty chain. */ 101179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 10128c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_RULE(const char *chain, TC_HANDLE_T *handle) 101330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 1014aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1015aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1016aae69bed019826ddec93f761514652a93d871e49Harald Welte 1017aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_RULE; 101830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1019aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("first rule(%s): ", chain); 1020aae69bed019826ddec93f761514652a93d871e49Harald Welte 1021aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 102230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!c) { 102330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell errno = ENOENT; 102430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1025e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1026e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 102730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Empty chain: single return/policy rule */ 1028aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&c->rules)) { 1029aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("no rules, returning NULL\n"); 103030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1031aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1032aae69bed019826ddec93f761514652a93d871e49Harald Welte 1033aae69bed019826ddec93f761514652a93d871e49Harald Welte r = list_entry(c->rules.next, struct rule_head, list); 1034aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = r; 1035aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%p\n", r); 103630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1037aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 1038e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1039e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 104030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Returns NULL when rules run out. */ 104179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 10428c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle) 104330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 1044aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1045aae69bed019826ddec93f761514652a93d871e49Harald Welte 1046664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_NEXT_RULE; 1047aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("rule_iterator_cur=%p...", (*handle)->rule_iterator_cur); 1048aae69bed019826ddec93f761514652a93d871e49Harald Welte 1049aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(*handle)->rule_iterator_cur) { 1050aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning NULL\n"); 105130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1052aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1053aae69bed019826ddec93f761514652a93d871e49Harald Welte 1054aae69bed019826ddec93f761514652a93d871e49Harald Welte r = list_entry((*handle)->rule_iterator_cur->list.next, 1055aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 105630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1057aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_RULE; 1058aae69bed019826ddec93f761514652a93d871e49Harald Welte 1059aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("next=%p, head=%p...", &r->list, 1060aae69bed019826ddec93f761514652a93d871e49Harald Welte &(*handle)->rule_iterator_cur->chain->rules); 1061aae69bed019826ddec93f761514652a93d871e49Harald Welte 1062aae69bed019826ddec93f761514652a93d871e49Harald Welte if (&r->list == &(*handle)->rule_iterator_cur->chain->rules) { 1063aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = NULL; 1064aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("finished, returning NULL\n"); 1065aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1066aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1067aae69bed019826ddec93f761514652a93d871e49Harald Welte 1068aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = r; 1069aae69bed019826ddec93f761514652a93d871e49Harald Welte 1070aae69bed019826ddec93f761514652a93d871e49Harald Welte /* NOTE: prev is without any influence ! */ 1071aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning rule %p\n", r); 1072aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 107330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 107430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1075e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* How many rules in this chain? */ 1076e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherunsigned int 107779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NUM_RULES(const char *chain, TC_HANDLE_T *handle) 1078e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1079aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1080aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NUM_RULES; 1081e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1082aae69bed019826ddec93f761514652a93d871e49Harald Welte 1083aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1084aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1085e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1086e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return (unsigned int)-1; 1087e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1088aae69bed019826ddec93f761514652a93d871e49Harald Welte 1089aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->num_rules; 1090e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1091e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 109279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY *TC_GET_RULE(const char *chain, 109379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int n, 109479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1095e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1096aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1097aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1098aae69bed019826ddec93f761514652a93d871e49Harald Welte 1099aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_RULE; 1100e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1101e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1102aae69bed019826ddec93f761514652a93d871e49Harald Welte 1103aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1104aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1105e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1106e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1107e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1108e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1109aae69bed019826ddec93f761514652a93d871e49Harald Welte r = iptcc_get_rule_num(c, n); 1110aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!r) 1111aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1112aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 1113e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1114e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1115aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 1116aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char *standard_target_map(int verdict) 1117e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1118aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (verdict) { 1119aae69bed019826ddec93f761514652a93d871e49Harald Welte case RETURN: 112079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_RETURN; 1121aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1122aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_ACCEPT-1: 112379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_ACCEPT; 1124aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1125aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_DROP-1: 1126aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_DROP; 1127aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1128aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_QUEUE-1: 1129aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_QUEUE; 1130aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1131aae69bed019826ddec93f761514652a93d871e49Harald Welte default: 1132aae69bed019826ddec93f761514652a93d871e49Harald Welte fprintf(stderr, "ERROR: %d not a valid target)\n", 1133aae69bed019826ddec93f761514652a93d871e49Harald Welte verdict); 1134aae69bed019826ddec93f761514652a93d871e49Harald Welte abort(); 1135aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1136e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1137aae69bed019826ddec93f761514652a93d871e49Harald Welte /* not reached */ 1138aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1139e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1140e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1141aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 1142aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char *TC_GET_TARGET(const STRUCT_ENTRY *ce, 1143aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T *handle) 1144e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1145aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 1146e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell struct rule_head *r = container_of(e, struct rule_head, entry[0]); 1147e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1148aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_TARGET; 11490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1150aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(r->type) { 1151aae69bed019826ddec93f761514652a93d871e49Harald Welte int spos; 1152aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_FALLTHROUGH: 1153aae69bed019826ddec93f761514652a93d871e49Harald Welte return ""; 1154aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1155aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_JUMP: 1156aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name); 1157aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->jump->name; 1158aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1159aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_STANDARD: 1160aae69bed019826ddec93f761514652a93d871e49Harald Welte spos = *(int *)GET_TARGET(e)->data; 1161aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, spos=%d'\n", r, spos); 1162aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(spos); 1163aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1164aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_MODULE: 1165aae69bed019826ddec93f761514652a93d871e49Harald Welte return GET_TARGET(e)->u.user.name; 1166aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 11670113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 1168aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1169aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1170aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Is this a built-in chain? Actually returns hook + 1. */ 1171aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1172aae69bed019826ddec93f761514652a93d871e49Harald WelteTC_BUILTIN(const char *chain, const TC_HANDLE_T handle) 1173aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1174aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1175aae69bed019826ddec93f761514652a93d871e49Harald Welte 1176aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_BUILTIN; 11770113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1178aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, handle); 1179aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1180aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1181b0f3d2d7261be3fe256a66abcc237241fea43a02Martin Josefsson return 0; 11820113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 11830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1184aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_is_builtin(c); 11850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 11860113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1187aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Get the policy of a given built-in chain */ 1188aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char * 1189aae69bed019826ddec93f761514652a93d871e49Harald WelteTC_GET_POLICY(const char *chain, 1190aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters, 1191aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T *handle) 11920113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 1193aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 11940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1195aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_POLICY; 1196fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte 1197aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("called for chain %s\n", chain); 11980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1199aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1200aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1201aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1202aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 12030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 12040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1205aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) 1206aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 12070113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1208aae69bed019826ddec93f761514652a93d871e49Harald Welte *counters = c->counters; 12090113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1210aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(c->verdict); 12110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 1212e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1213e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1214aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_standard_map(struct rule_head *r, int verdict) 1215e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1216aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 121779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 1218e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 121979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1220e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 122167088e73ce7707229c56987868f112051defca5aRusty Russell if (t->target.u.target_size 12228c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1223e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1224e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1225e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1226e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset for memcmp convenience on delete/replace */ 122779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 122879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell strcpy(t->target.u.user.name, STANDARD_TARGET); 1229e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = verdict; 1230e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1231aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_STANDARD; 1232aae69bed019826ddec93f761514652a93d871e49Harald Welte 1233e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1234e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 12357e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1236e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1237aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_map_target(const TC_HANDLE_T handle, 1238aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r) 1239e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1240aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 12410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 1242e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1243e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's empty (=> fall through) */ 1244aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(t->u.user.name, "") == 0) { 1245aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_FALLTHROUGH; 1246aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1247aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1248e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's a standard target name... */ 124979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 1250aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_ACCEPT - 1); 125179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 1252aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_DROP - 1); 125367088e73ce7707229c56987868f112051defca5aRusty Russell else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 1254aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_QUEUE - 1); 125579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 1256aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, RETURN); 125779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (TC_BUILTIN(t->u.user.name, handle)) { 1258e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Can't jump to builtins. */ 1259e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1260e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1261e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 1262e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's an existing chain name. */ 1263aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1264aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("trying to find chain `%s': ", t->u.user.name); 1265aae69bed019826ddec93f761514652a93d871e49Harald Welte 1266aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(t->u.user.name, handle); 1267aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c) { 1268aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("found!\n"); 1269aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_JUMP; 1270aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump = c; 1271aae69bed019826ddec93f761514652a93d871e49Harald Welte c->references++; 1272aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1273aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1274aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("not found :(\n"); 1275e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1276e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1277e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Must be a module? If not, kernel will reject... */ 12783aef54dce4f9bbe0b466478fd33a1d3131efbbb8Rusty Russell /* memset to all 0 for your memcmp convenience: don't clear version */ 1279228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell memset(t->u.user.name + strlen(t->u.user.name), 1280e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 0, 12813aef54dce4f9bbe0b466478fd33a1d3131efbbb8Rusty Russell FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name)); 1282733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell r->type = IPTCC_R_MODULE; 1283aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(handle); 1284aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1285e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1286e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 12870113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 1288e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 128979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 129079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 129179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 129279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1293e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1294aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1295eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson struct rule_head *r; 1296eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson struct list_head *prev; 1297e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 129879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INSERT_ENTRY; 1299aae69bed019826ddec93f761514652a93d871e49Harald Welte 1300aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1301e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1302e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1303e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1304e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1305eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson /* first rulenum index = 0 1306eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson first c->num_rules index = 1 */ 1307eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson if (rulenum > c->num_rules) { 1308e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1309e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1310e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1311e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1312631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson /* If we are inserting at the end just take advantage of the 1313631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson double linked list, insert will happen before the entry 1314631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson prev points to. */ 1315631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson if (rulenum == c->num_rules) { 1316eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson prev = &c->rules; 1317a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else if (rulenum + 1 <= c->num_rules/2) { 1318631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson r = iptcc_get_rule_num(c, rulenum + 1); 1319a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson prev = &r->list; 1320a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else { 1321a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1322631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson prev = &r->list; 1323631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson } 1324eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson 1325aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1326aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1327aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1328aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1329aae69bed019826ddec93f761514652a93d871e49Harald Welte 1330aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1331aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1332aae69bed019826ddec93f761514652a93d871e49Harald Welte 1333aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 1334aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 13350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1336aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1337aae69bed019826ddec93f761514652a93d871e49Harald Welte 1338eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson list_add_tail(&r->list, prev); 1339aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1340aae69bed019826ddec93f761514652a93d871e49Harald Welte 1341aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1342e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1343aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1344e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1345e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1346e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 1347e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 134879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 134979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 135079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 135179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1352e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1353aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1354aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *old; 1355e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 135679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_REPLACE_ENTRY; 1357e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1358aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1359e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1360e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1361e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1362e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13630f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson if (rulenum >= c->num_rules) { 1364e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1365e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1366e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1367e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13680f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson /* Take advantage of the double linked list if possible. */ 13690f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson if (rulenum + 1 <= c->num_rules/2) { 13700f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson old = iptcc_get_rule_num(c, rulenum + 1); 13710f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson } else { 13720f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson old = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 13730f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson } 13740f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson 1375aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1376aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1377e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1378aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1379aae69bed019826ddec93f761514652a93d871e49Harald Welte 1380aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1381aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1382e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1383aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 1384aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 13850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1386aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1387aae69bed019826ddec93f761514652a93d871e49Harald Welte 1388aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add(&r->list, &old->list); 1389aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(old); 13900113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1391aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1392aae69bed019826ddec93f761514652a93d871e49Harald Welte 1393aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1394e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1395e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Append entry `fw' to chain `chain'. Equivalent to insert with 1397e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher rulenum = length of chain. */ 1398e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 139979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 140079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 140179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1402e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1403aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1404aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1405e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 140679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_APPEND_ENTRY; 1407aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1408aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to find chain `%s'\n", chain); 1409e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1410e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1411e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1412e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1413aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1414aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to allocate rule for chain `%s'\n", chain); 1415aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1416aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1417aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1418aae69bed019826ddec93f761514652a93d871e49Harald Welte 1419aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1420aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1421aae69bed019826ddec93f761514652a93d871e49Harald Welte 1422aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 142312009531e6a96a62ee398eb0ab3e9ec0b3b57701Martin Josefsson DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1424aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 14250113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1426aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1427aae69bed019826ddec93f761514652a93d871e49Harald Welte 1428aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &c->rules); 1429aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1430aae69bed019826ddec93f761514652a93d871e49Harald Welte 1431aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 14320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1433aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1434e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1435e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1436e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 143779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellmatch_different(const STRUCT_ENTRY_MATCH *a, 1438edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *a_elems, 1439edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_elems, 1440edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned char **maskptr) 1441e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 144279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY_MATCH *b; 1443edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1444e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1445e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Offset of b is the same as a. */ 144630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell b = (void *)b_elems + ((unsigned char *)a - a_elems); 1447e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1448228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (a->u.match_size != b->u.match_size) 1449e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1450e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1451228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (strcmp(a->u.user.name, b->u.user.name) != 0) 1452e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1453e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 145473ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell *maskptr += ALIGN(sizeof(*a)); 1455edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 145673ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1457edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1458edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 1; 1459edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell *maskptr += i; 1460edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 0; 1461edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell} 1462edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 1463edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russellstatic inline int 1464733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russelltarget_same(struct rule_head *a, struct rule_head *b,const unsigned char *mask) 1465edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell{ 1466edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1467733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell STRUCT_ENTRY_TARGET *ta, *tb; 1468e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1469733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (a->type != b->type) 1470733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1471733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1472733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell ta = GET_TARGET(a->entry); 1473733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell tb = GET_TARGET(b->entry); 1474733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1475733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell switch (a->type) { 1476733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_FALLTHROUGH: 1477733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 1478733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_JUMP: 1479733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return a->jump == b->jump; 1480733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_STANDARD: 1481733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return ((STRUCT_STANDARD_TARGET *)ta)->verdict 1482733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell == ((STRUCT_STANDARD_TARGET *)tb)->verdict; 1483733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_MODULE: 1484733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (ta->u.target_size != tb->u.target_size) 1485733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1486733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (strcmp(ta->u.user.name, tb->u.user.name) != 0) 1487733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1488733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1489733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell for (i = 0; i < ta->u.target_size - sizeof(*ta); i++) 1490daade4452715cbd1feea05d5231c5e38e3b0b98bRusty Russell if (((ta->data[i] ^ tb->data[i]) & mask[i]) != 0) 1491733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1492733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 1493733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell default: 1494733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell fprintf(stderr, "ERROR: bad type %i\n", a->type); 1495733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell abort(); 1496733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell } 1497e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1498e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1499733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russellstatic unsigned char * 150079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellis_same(const STRUCT_ENTRY *a, 150179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *b, 150279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask); 1503e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 15040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Delete the first rule in `chain' which matches `fw'. */ 1505e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 150679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_ENTRY(const IPT_CHAINLABEL chain, 150779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *origfw, 150879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask, 150979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1510e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1511aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1512e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell struct rule_head *r, *i; 1513e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 151479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_ENTRY; 1515aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1516e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1517e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1518e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1519e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1520e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell /* Create a rule_head from origfw. */ 1521e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell r = iptcc_alloc_rule(c, origfw->next_offset); 1522e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell if (!r) { 15230113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = ENOMEM; 15240113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 15250113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 15260113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1527e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell memcpy(r->entry, origfw, origfw->next_offset); 1528e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell r->counter_map.maptype = COUNTER_MAP_NOMAP; 1529e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell if (!iptcc_map_target(*handle, r)) { 1530e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1531e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell free(r); 1532e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell return 0; 153304a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer } else { 153404a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer /* iptcc_map_target increment target chain references 153504a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer * since this is a fake rule only used for matching 153604a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer * the chain references count is decremented again. 153704a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer */ 153804a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer if (r->type == IPTCC_R_JUMP 153904a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer && r->jump) 154004a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer r->jump->references--; 1541e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell } 1542fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 1543e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell list_for_each_entry(i, &c->rules, list) { 1544733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell unsigned char *mask; 1545733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1546733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell mask = is_same(r->entry, i->entry, matchmask); 1547733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (!mask) 1548733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell continue; 1549733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1550733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (!target_same(r, i, mask)) 1551733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell continue; 1552733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1553733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell /* If we are about to delete the rule that is the 1554733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell * current iterator, move rule iterator back. next 1555733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell * pointer will then point to real next node */ 1556733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (i == (*handle)->rule_iterator_cur) { 1557733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell (*handle)->rule_iterator_cur = 1558733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell list_entry((*handle)->rule_iterator_cur->list.prev, 1559733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell struct rule_head, list); 1560733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell } 1561fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 1562733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell c->num_rules--; 1563733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell iptcc_delete_rule(i); 15642a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson 1565733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell set_changed(*handle); 1566733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell free(r); 1567733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 1568e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1569e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1570e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell free(r); 1571e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1572e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 15737e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell} 1574aae69bed019826ddec93f761514652a93d871e49Harald Welte 1575e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1576e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Delete the rule in position `rulenum' in `chain'. */ 1577e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 157879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 157979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 158079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1581e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1582aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1583aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1584e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 158579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_NUM_ENTRY; 1586aae69bed019826ddec93f761514652a93d871e49Harald Welte 1587aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1588e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1589e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1590e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1591e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1592a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson if (rulenum >= c->num_rules) { 1593631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson errno = E2BIG; 1594631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson return 0; 1595631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson } 1596631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson 1597631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson /* Take advantage of the double linked list if possible. */ 1598a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson if (rulenum + 1 <= c->num_rules/2) { 1599a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num(c, rulenum + 1); 1600a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else { 1601a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1602e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1603e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1604aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the rule that is the current 1605aae69bed019826ddec93f761514652a93d871e49Harald Welte * iterator, move rule iterator back. next pointer will then 1606aae69bed019826ddec93f761514652a93d871e49Harald Welte * point to real next node */ 1607aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r == (*handle)->rule_iterator_cur) { 1608aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = 1609aae69bed019826ddec93f761514652a93d871e49Harald Welte list_entry((*handle)->rule_iterator_cur->list.prev, 1610aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 16110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 1612e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1613aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules--; 1614aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 1615aae69bed019826ddec93f761514652a93d871e49Harald Welte 16162a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson set_changed(*handle); 16172a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson 1618aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1619e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1620e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1621e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Check the packet `fw' on chain `chain'. Returns the verdict, or 1622e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher NULL and sets errno. */ 1623e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 162479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CHECK_PACKET(const IPT_CHAINLABEL chain, 162579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *entry, 162679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1627e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1628664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_CHECK_PACKET; 1629e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOSYS; 1630e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1631e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1632e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1633e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Flushes the entries in the given chain (ie. empties chain). */ 1634e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 163579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1636e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1637aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1638aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *tmp; 1639e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 16400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte iptc_fn = TC_FLUSH_ENTRIES; 1641aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1642e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1643e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1644e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1645e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1646aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, tmp, &c->rules, list) { 1647aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 1648aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1649aae69bed019826ddec93f761514652a93d871e49Harald Welte 1650aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules = 0; 1651aae69bed019826ddec93f761514652a93d871e49Harald Welte 1652aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1653aae69bed019826ddec93f761514652a93d871e49Harald Welte 1654aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1655e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1656e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1657e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Zeroes the counters in a chain. */ 1658e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 165979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1660e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1661aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1662aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 16637e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1664664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_ZERO_ENTRIES; 1665aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1666e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1667e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1668e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1669e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1670e5bd1d779fab33353c1dc2d2fa49db639dcebd38Andy Gay if (c->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 1671e5bd1d779fab33353c1dc2d2fa49db639dcebd38Andy Gay c->counter_map.maptype = COUNTER_MAP_ZEROED; 1672e5bd1d779fab33353c1dc2d2fa49db639dcebd38Andy Gay 1673aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 1674aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 1675aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 1676e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1677aae69bed019826ddec93f761514652a93d871e49Harald Welte 1678175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1679e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1680e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1681e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1682e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 16831cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteSTRUCT_COUNTERS * 16841cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_READ_COUNTER(const IPT_CHAINLABEL chain, 16851cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 16861cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 16871cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1688aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1689aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 16901cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16911cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_READ_COUNTER; 16921cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 16931cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1694aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 16951cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 16961cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return NULL; 16971cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 16981cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1699aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 17000113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 17010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 17020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 17030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1704aae69bed019826ddec93f761514652a93d871e49Harald Welte return &r->entry[0].counters; 17051cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 17061cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17071cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 17081cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 17091cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 17101cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 17111cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1712aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1713aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 17141cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17151cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_ZERO_COUNTER; 17161cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 17171cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1718aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 17191cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 17201cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 17211cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 17221cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1723aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 17240113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 17250113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 17260113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 17270113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1728aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 1729aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 17301cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17311cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 17321cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17331cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 17341cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 17351cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17361cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 17371cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_SET_COUNTER(const IPT_CHAINLABEL chain, 17381cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 17391cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 17401cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 17411cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1742aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1743aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 17441cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 17451cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17461cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_SET_COUNTER; 17471cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 17481cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1749aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 17501cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 17511cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 17521cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 17530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1754aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 17550113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 17560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 17570113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 17580113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1759aae69bed019826ddec93f761514652a93d871e49Harald Welte e = r->entry; 1760aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 17610113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 17620113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 17631cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17641cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 17651cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17661cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 17671cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 17681cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1769e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Creates a new chain. */ 1770e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* To create a chain, create two rules: error node and unconditional 1771e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * return. */ 1772e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 177379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1774e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1775aae69bed019826ddec93f761514652a93d871e49Harald Welte static struct chain_head *c; 1776e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 177779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_CREATE_CHAIN; 1778e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1779e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* find_label doesn't cover built-in targets: DROP, ACCEPT, 1780e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher QUEUE, RETURN. */ 1781aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_find_label(chain, *handle) 178279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_DROP) == 0 178379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_ACCEPT) == 0 178467088e73ce7707229c56987868f112051defca5aRusty Russell || strcmp(chain, LABEL_QUEUE) == 0 178579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_RETURN) == 0) { 1786aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain `%s' already exists\n", chain); 1787e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1788e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1789e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1790e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 179179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 1792aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain name `%s' too long\n", chain); 1793e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1794e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1795e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1796e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1797aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_alloc_chain_head(chain, 0); 1798aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1799aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Cannot allocate memory for chain `%s'\n", chain); 1800aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1801aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1802e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1803aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1804e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1805aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Creating chain `%s'\n", chain); 1806d8cb787ab44e9d2de4fd3b04fcaa370c9918fc5dJesper Dangaard Brouer iptc_insert_chain(*handle, c); /* Insert sorted */ 1807e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1808aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1809e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1810aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1811e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1812e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1813e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get the number of references to this chain. */ 1814e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 181579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 181679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1817e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1818aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1819e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1820664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_GET_REFERENCES; 1821aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1822e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1823e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1824e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1825e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1826aae69bed019826ddec93f761514652a93d871e49Harald Welte *ref = c->references; 1827aae69bed019826ddec93f761514652a93d871e49Harald Welte 1828e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1829e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1830e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1831e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Deletes a chain. */ 1832e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 183379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1834e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1835e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int references; 1836aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 18377e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 183879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_CHAIN; 1839e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1840aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1841aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 1842aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1843aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1844aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1845aae69bed019826ddec93f761514652a93d871e49Harald Welte 184679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (TC_BUILTIN(chain, *handle)) { 1847aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot remove builtin chain `%s'\n", chain); 1848e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1849e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1850e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1851e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1852aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!TC_GET_REFERENCES(&references, chain, handle)) { 1853aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot get references on chain `%s'\n", chain); 1854e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1855e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1856e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1857aae69bed019826ddec93f761514652a93d871e49Harald Welte if (references > 0) { 1858aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' still has references\n", chain); 1859aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EMLINK; 1860e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1861e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1862e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1863aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->num_rules) { 1864aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' is not empty\n", chain); 1865e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOTEMPTY; 1866e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1867e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1868e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1869aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the chain that is the current 1870aae69bed019826ddec93f761514652a93d871e49Harald Welte * iterator, move chain iterator firward. */ 1871aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c == (*handle)->chain_iterator_cur) 1872aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 1873aae69bed019826ddec93f761514652a93d871e49Harald Welte 1874aae69bed019826ddec93f761514652a93d871e49Harald Welte list_del(&c->list); 1875aae69bed019826ddec93f761514652a93d871e49Harald Welte free(c); 18760113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1877aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' deleted\n", chain); 18780113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1879aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1880aae69bed019826ddec93f761514652a93d871e49Harald Welte 1881aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1882e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1883e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1884e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Renames a chain. */ 188579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 188679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL newname, 188779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1888e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1889aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 189079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_RENAME_CHAIN; 1891e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18921de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte /* find_label doesn't cover built-in targets: DROP, ACCEPT, 18931de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte QUEUE, RETURN. */ 1894aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_find_label(newname, *handle) 189579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_DROP) == 0 189679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_ACCEPT) == 0 18971de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte || strcmp(newname, LABEL_QUEUE) == 0 189879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_RETURN) == 0) { 1899e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1900e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1901e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1902e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1903aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(oldname, *handle)) 190479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || TC_BUILTIN(oldname, *handle)) { 1905e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1906e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1907e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1908e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 190979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 1910e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1911e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1912e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1913e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1914aae69bed019826ddec93f761514652a93d871e49Harald Welte strncpy(c->name, newname, sizeof(IPT_CHAINLABEL)); 1915aae69bed019826ddec93f761514652a93d871e49Harald Welte 19160113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte set_changed(*handle); 19170113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1918e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1919e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1920e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1921e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Sets the policy on a built-in chain. */ 1922e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 192379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_SET_POLICY(const IPT_CHAINLABEL chain, 192479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL policy, 19251cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 192679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1927e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1928aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1929e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 193079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_SET_POLICY; 1931aae69bed019826ddec93f761514652a93d871e49Harald Welte 1932aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1933aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 1934c8264991454b5e77279830736f80ea3153b6f814Marc Boucher errno = ENOENT; 1935e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1936aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1937e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1938aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 1939aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain); 1940aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 19419e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte return 0; 19429e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte } 19439e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 194479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(policy, LABEL_ACCEPT) == 0) 1945aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_ACCEPT - 1; 194679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(policy, LABEL_DROP) == 0) 1947aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_DROP - 1; 1948e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else { 1949e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1950e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1951e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 19521cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 19531cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (counters) { 19541cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte /* set byte and packet counters */ 1955aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS)); 1956aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_SET; 19571cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } else { 1958aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_NOMAP; 19591cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 19601cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1961175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1962e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1963e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1964e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1965e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1966e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Without this, on gcc 2.7.2.3, we get: 196779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell libiptc.c: In function `TC_COMMIT': 1968e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher libiptc.c:833: fixed or forbidden register was spilled. 1969e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher This may be due to a compiler bug or to impossible asm 1970e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher statements or clauses. 1971e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher*/ 1972e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 197379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellsubtract_counters(STRUCT_COUNTERS *answer, 197479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *a, 197579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *b) 1976e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1977e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->pcnt = a->pcnt - b->pcnt; 1978e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->bcnt = a->bcnt - b->bcnt; 1979e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1980e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1981aae69bed019826ddec93f761514652a93d871e49Harald Welte 1982aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, 1983aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index) 1984aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1985aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->counters[index] = ((STRUCT_COUNTERS) { 0, 0}); 1986aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NOMAP => zero\n"); 1987aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1988aae69bed019826ddec93f761514652a93d871e49Harald Welte 1989aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters, 1990aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_REPLACE *repl, 1991aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 1992aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int mappos) 1993aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1994aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 1995aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 1996aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 1997aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: X + Y + Z. 1998aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in X + Y 1999aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in replacement read. 2000aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 2001aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->counters[index] = repl->counters[mappos]; 2002aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos); 2003aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2004aae69bed019826ddec93f761514652a93d871e49Harald Welte 2005aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters, 2006aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_REPLACE *repl, 2007aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 2008aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int mappos, 2009aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters) 2010aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 2011aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 2012aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 2013aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 2014aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: Y + Z. 2015aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in Y. 2016aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in (replacement read - original read). 2017aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 2018aae69bed019826ddec93f761514652a93d871e49Harald Welte subtract_counters(&newcounters->counters[index], 2019aae69bed019826ddec93f761514652a93d871e49Harald Welte &repl->counters[mappos], 2020aae69bed019826ddec93f761514652a93d871e49Harald Welte counters); 2021aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("ZEROED => mappos %u\n", mappos); 2022aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2023aae69bed019826ddec93f761514652a93d871e49Harald Welte 2024aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_set(STRUCT_COUNTERS_INFO *newcounters, 2025aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 2026aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters) 2027aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 2028aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Want to set counter (iptables-restore) */ 2029aae69bed019826ddec93f761514652a93d871e49Harald Welte 2030aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&newcounters->counters[index], counters, 2031aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(STRUCT_COUNTERS)); 2032aae69bed019826ddec93f761514652a93d871e49Harald Welte 2033aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("SET\n"); 2034aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2035aae69bed019826ddec93f761514652a93d871e49Harald Welte 2036aae69bed019826ddec93f761514652a93d871e49Harald Welte 2037e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 203879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_COMMIT(TC_HANDLE_T *handle) 2039e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2040e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Replace, then map back the counters. */ 204179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_REPLACE *repl; 204279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_COUNTERS_INFO *newcounters; 2043aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2044aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 2045841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson size_t counterlen; 2046aae69bed019826ddec93f761514652a93d871e49Harald Welte int new_number; 2047aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int new_size; 2048e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2049664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_COMMIT; 2050e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 2051841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 2052e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Don't commit if nothing changed. */ 2053e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!(*handle)->changed) 2054e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher goto finished; 2055e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2056aae69bed019826ddec93f761514652a93d871e49Harald Welte new_number = iptcc_compile_table_prep(*handle, &new_size); 2057aae69bed019826ddec93f761514652a93d871e49Harald Welte if (new_number < 0) { 2058aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 2059d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_zero; 2060aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2061aae69bed019826ddec93f761514652a93d871e49Harald Welte 2062aae69bed019826ddec93f761514652a93d871e49Harald Welte repl = malloc(sizeof(*repl) + new_size); 2063e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl) { 2064e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2065d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_zero; 2066e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2067ad3b4f9973ac15981b98b8fc4d364ef1ce524212Martin Josefsson memset(repl, 0, sizeof(*repl) + new_size); 2068aae69bed019826ddec93f761514652a93d871e49Harald Welte 2069e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell#if 0 2070e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell TC_DUMP_ENTRIES(*handle); 2071e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell#endif 2072e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell 2073aae69bed019826ddec93f761514652a93d871e49Harald Welte counterlen = sizeof(STRUCT_COUNTERS_INFO) 2074aae69bed019826ddec93f761514652a93d871e49Harald Welte + sizeof(STRUCT_COUNTERS) * new_number; 2075e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2076e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the old counters we will get from kernel */ 207779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell repl->counters = malloc(sizeof(STRUCT_COUNTERS) 2078e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * (*handle)->info.num_entries); 2079e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl->counters) { 2080e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2081d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_repl; 2082e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2083e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the counters we're going to put back, later. */ 2084e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters = malloc(counterlen); 2085e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!newcounters) { 2086e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2087d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_repl_counters; 2088e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2089aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(newcounters, 0, counterlen); 2090e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2091e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(repl->name, (*handle)->info.name); 2092aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries = new_number; 2093aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->size = new_size; 2094aae69bed019826ddec93f761514652a93d871e49Harald Welte 2095e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->num_counters = (*handle)->info.num_entries; 2096e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->valid_hooks = (*handle)->info.valid_hooks; 2097aae69bed019826ddec93f761514652a93d871e49Harald Welte 2098aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("num_entries=%u, size=%u, num_counters=%u\n", 2099aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries, repl->size, repl->num_counters); 2100aae69bed019826ddec93f761514652a93d871e49Harald Welte 2101aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_table(*handle, repl); 2102aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) { 2103aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ret; 2104d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_newcounters; 2105aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2106aae69bed019826ddec93f761514652a93d871e49Harald Welte 2107aae69bed019826ddec93f761514652a93d871e49Harald Welte 2108aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 2109aae69bed019826ddec93f761514652a93d871e49Harald Welte { 2110aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_set_replace.blob", 2111aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 2112aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 2113aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, repl, sizeof(*repl) + repl->size); 2114aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 2115aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2116aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2117aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2118e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2119d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte ret = setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 2120d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte sizeof(*repl) + repl->size); 2121e0865ad29d53b0d3d34b5cc8b5e023eb593172a8Patrick McHardy if (ret < 0) 2122d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_newcounters; 2123e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2124e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Put counters back. */ 2125e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(newcounters->name, (*handle)->info.name); 2126aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->num_counters = new_number; 2127aae69bed019826ddec93f761514652a93d871e49Harald Welte 2128aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &(*handle)->chains, list) { 2129aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 2130aae69bed019826ddec93f761514652a93d871e49Harald Welte 2131aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Builtin chains have their own counters */ 2132aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_is_builtin(c)) { 2133aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for chain-index %u: ", c->foot_index); 2134aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(c->counter_map.maptype) { 2135aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2136aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, c->foot_index); 2137aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2138aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2139aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2140aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index, 2141aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos); 2142aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2143aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2144aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2145aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index, 2146aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos, 2147aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2148aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2149aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2150aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, c->foot_index, 2151aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2152aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2153aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2154aae69bed019826ddec93f761514652a93d871e49Harald Welte } 21551cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2156aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 2157aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for index %u: ", r->index); 2158aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (r->counter_map.maptype) { 2159aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2160aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, r->index); 2161aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2162aae69bed019826ddec93f761514652a93d871e49Harald Welte 2163aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2164aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2165aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index, 2166aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos); 2167aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2168aae69bed019826ddec93f761514652a93d871e49Harald Welte 2169aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2170aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2171aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index, 2172aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos, 2173aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2174aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2175aae69bed019826ddec93f761514652a93d871e49Harald Welte 2176aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2177aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, r->index, 2178aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2179aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2180aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2181e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2182e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 218362527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell 2184aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 2185aae69bed019826ddec93f761514652a93d871e49Harald Welte { 2186aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_set_add_counters.blob", 2187aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 2188aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 2189aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, newcounters, counterlen); 2190aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 2191aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2192aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2193aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2194aae69bed019826ddec93f761514652a93d871e49Harald Welte 2195d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte ret = setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 2196d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte newcounters, counterlen); 2197e0865ad29d53b0d3d34b5cc8b5e023eb593172a8Patrick McHardy if (ret < 0) 2198d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_newcounters; 2199e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2200e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2201e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2202e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2203e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2204d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Weltefinished: 2205841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson TC_FREE(handle); 2206e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2207d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte 2208d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_free_newcounters: 2209d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte free(newcounters); 2210d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_free_repl_counters: 2211d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte free(repl->counters); 2212d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_free_repl: 2213d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte free(repl); 2214d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_zero: 2215d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte return 0; 2216e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2217e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2218e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get raw socket. */ 2219e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 22200b63936140032deac44072951451bdf47b54296aPatrick McHardyTC_GET_RAW_SOCKET(void) 2221e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2222e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return sockfd; 2223e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2224e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2225e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Translates errno numbers into more human-readable form than strerror. */ 2226e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 222779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_STRERROR(int err) 2228e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2229e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 2230e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct table_struct { 2231e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher void *fn; 2232e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int err; 2233e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char *message; 2234e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } table [] = 22354ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 223679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INIT, EINVAL, "Module is wrong version" }, 22374ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_INIT, ENOENT, 22384ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Table does not exist (do you need to insmod?)" }, 223979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 224079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 224179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EMLINK, 2242e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher "Can't delete chain with references left" }, 224379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 224479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 224579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 224679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 22471cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 22481cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 224979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 225079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 2251e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* EINVAL for CHECK probably means bad interface. */ 225279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CHECK_PACKET, EINVAL, 2253c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad arguments (does that interface exist?)" }, 22544ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_CHECK_PACKET, ENOSYS, 22554ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Checking will most likely never get implemented" }, 2256e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* ENOENT for DELETE probably means no matching rule */ 225779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_ENTRY, ENOENT, 2258c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad rule (does a matching rule exist in that chain?)" }, 225979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, ENOENT, 2260c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad built-in chain name" }, 226179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, EINVAL, 2262c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad policy name" }, 22634ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte 22644ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, 0, "Incompatible with this kernel" }, 22654ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 22664ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 22674ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOMEM, "Memory allocation problem" }, 22684ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOENT, "No chain/target/match by that name" }, 2269e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher }; 2270e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2271e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 2272e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((!table[i].fn || table[i].fn == iptc_fn) 2273e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && table[i].err == err) 2274e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return table[i].message; 2275e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2276e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2277e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return strerror(err); 2278e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2279