libiptc.c revision efa8fc2123a2a9fc229ab471edd2b2688ce1da3a
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 51e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic const char *hooknames[] 5279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell= { [HOOK_PRE_ROUTING] "PREROUTING", 5379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_LOCAL_IN] "INPUT", 5479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_FORWARD] "FORWARD", 5579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_LOCAL_OUT] "OUTPUT", 5610758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell [HOOK_POST_ROUTING] "POSTROUTING", 5710758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell#ifdef HOOK_DROPPING 5810758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell [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) { 4029d3ed77341361674994f584ff69a61f31a342739Olaf Rempel if (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{ 418aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_del_policy(h, *num); 419e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 420aae69bed019826ddec93f761514652a93d871e49Harald Welte c->head_offset = offset; 421aae69bed019826ddec93f761514652a93d871e49Harald Welte c->index = *num; 422e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 423ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte iptc_insert_chain(h, c); 424ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte 425aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur = c; 426e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 427e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 428aae69bed019826ddec93f761514652a93d871e49Harald Welte/* main parser function: add an entry from the blob to the cache */ 429aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int cache_add_entry(STRUCT_ENTRY *e, 430aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T h, 431aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY **prev, 432aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int *num) 433e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 434aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int builtin; 435aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset = (char *)e - (char *)h->entries->entrytable; 436aae69bed019826ddec93f761514652a93d871e49Harald Welte 437aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("entering..."); 438aae69bed019826ddec93f761514652a93d871e49Harald Welte 439aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Last entry ("policy rule"). End it.*/ 440aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcb_entry2offset(h,e) + e->next_offset == h->entries->size) { 441aae69bed019826ddec93f761514652a93d871e49Harald Welte /* This is the ERROR node at the end of the chain */ 442aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u: end of table:\n", *num, offset); 443aae69bed019826ddec93f761514652a93d871e49Harald Welte 444aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_del_policy(h, *num); 445aae69bed019826ddec93f761514652a93d871e49Harald Welte 446aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur = NULL; 447aae69bed019826ddec93f761514652a93d871e49Harald Welte goto out_inc; 448aae69bed019826ddec93f761514652a93d871e49Harald Welte } 449aae69bed019826ddec93f761514652a93d871e49Harald Welte 450aae69bed019826ddec93f761514652a93d871e49Harald Welte /* We know this is the start of a new chain if it's an ERROR 451aae69bed019826ddec93f761514652a93d871e49Harald Welte * target, or a hook entry point */ 452aae69bed019826ddec93f761514652a93d871e49Harald Welte 453aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) { 454aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = 455aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0); 456aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset, 457aae69bed019826ddec93f761514652a93d871e49Harald Welte (char *)c->name, c); 458aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 459aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = -ENOMEM; 460aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 461aae69bed019826ddec93f761514652a93d871e49Harald Welte } 462aae69bed019826ddec93f761514652a93d871e49Harald Welte 463aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_add_chain(h, c, offset, num); 464aae69bed019826ddec93f761514652a93d871e49Harald Welte 465aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) { 466aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = 467aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_alloc_chain_head((char *)hooknames[builtin-1], 468aae69bed019826ddec93f761514652a93d871e49Harald Welte builtin); 469aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n", 470aae69bed019826ddec93f761514652a93d871e49Harald Welte *num, offset, c, &c->rules); 471aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 472aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = -ENOMEM; 473aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 474aae69bed019826ddec93f761514652a93d871e49Harald Welte } 475aae69bed019826ddec93f761514652a93d871e49Harald Welte 476aae69bed019826ddec93f761514652a93d871e49Harald Welte c->hooknum = builtin; 477aae69bed019826ddec93f761514652a93d871e49Harald Welte 478aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_add_chain(h, c, offset, num); 479aae69bed019826ddec93f761514652a93d871e49Harald Welte 480aae69bed019826ddec93f761514652a93d871e49Harald Welte /* FIXME: this is ugly. */ 481aae69bed019826ddec93f761514652a93d871e49Harald Welte goto new_rule; 482aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 483aae69bed019826ddec93f761514652a93d871e49Harald Welte /* has to be normal rule */ 484aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 485aae69bed019826ddec93f761514652a93d871e49Harald Weltenew_rule: 486aae69bed019826ddec93f761514652a93d871e49Harald Welte 487aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, 488aae69bed019826ddec93f761514652a93d871e49Harald Welte e->next_offset))) { 489aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 490aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 491aae69bed019826ddec93f761514652a93d871e49Harald Welte } 492aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r); 493aae69bed019826ddec93f761514652a93d871e49Harald Welte 494aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index = *num; 495aae69bed019826ddec93f761514652a93d871e49Harald Welte r->offset = offset; 496aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 497aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_NORMAL_MAP; 498aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos = r->index; 499aae69bed019826ddec93f761514652a93d871e49Harald Welte 500aae69bed019826ddec93f761514652a93d871e49Harald Welte /* handling of jumps, etc. */ 501aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET)) { 502aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 503aae69bed019826ddec93f761514652a93d871e49Harald Welte 504aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 505aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->target.u.target_size 506aae69bed019826ddec93f761514652a93d871e49Harald Welte != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 507aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EINVAL; 508aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 509aae69bed019826ddec93f761514652a93d871e49Harald Welte } 510aae69bed019826ddec93f761514652a93d871e49Harald Welte 511aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->verdict < 0) { 512aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("standard, verdict=%d\n", t->verdict); 513aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_STANDARD; 514aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (t->verdict == r->offset+e->next_offset) { 515aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("fallthrough\n"); 516aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_FALLTHROUGH; 517aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 518aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("jump, target=%u\n", t->verdict); 519aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_JUMP; 520aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Jump target fixup has to be deferred 521aae69bed019826ddec93f761514652a93d871e49Harald Welte * until second pass, since we migh not 522aae69bed019826ddec93f761514652a93d871e49Harald Welte * yet have parsed the target */ 523aae69bed019826ddec93f761514652a93d871e49Harald Welte } 52452c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson } else { 52552c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson DEBUGP_C("module, target=%s\n", GET_TARGET(e)->u.user.name); 52652c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson r->type = IPTCC_R_MODULE; 527aae69bed019826ddec93f761514652a93d871e49Harald Welte } 528aae69bed019826ddec93f761514652a93d871e49Harald Welte 529aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &h->chain_iterator_cur->rules); 5308d1b38a064d146c77eb8fc951717663e1a713cfcMartin Josefsson h->chain_iterator_cur->num_rules++; 531aae69bed019826ddec93f761514652a93d871e49Harald Welte } 532aae69bed019826ddec93f761514652a93d871e49Harald Welteout_inc: 533aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 534aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 535e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 536e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 537aae69bed019826ddec93f761514652a93d871e49Harald Welte 538aae69bed019826ddec93f761514652a93d871e49Harald Welte/* parse an iptables blob into it's pieces */ 539aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int parse_table(TC_HANDLE_T h) 540e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 541aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *prev; 542aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int num = 0; 543aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 544aae69bed019826ddec93f761514652a93d871e49Harald Welte 545aae69bed019826ddec93f761514652a93d871e49Harald Welte /* First pass: over ruleset blob */ 546aae69bed019826ddec93f761514652a93d871e49Harald Welte ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 547aae69bed019826ddec93f761514652a93d871e49Harald Welte cache_add_entry, h, &prev, &num); 548aae69bed019826ddec93f761514652a93d871e49Harald Welte 549aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Second pass: fixup parsed data from first pass */ 550aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 551aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 552aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 553aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 554aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 555aae69bed019826ddec93f761514652a93d871e49Harald Welte 556aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type != IPTCC_R_JUMP) 557aae69bed019826ddec93f761514652a93d871e49Harald Welte continue; 558aae69bed019826ddec93f761514652a93d871e49Harald Welte 559aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 560aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_chain_by_offset(h, t->verdict); 561aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) 562aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 563aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump = c; 564aae69bed019826ddec93f761514652a93d871e49Harald Welte c->references++; 565aae69bed019826ddec93f761514652a93d871e49Harald Welte } 566aae69bed019826ddec93f761514652a93d871e49Harald Welte } 567aae69bed019826ddec93f761514652a93d871e49Harald Welte 568aae69bed019826ddec93f761514652a93d871e49Harald Welte /* FIXME: sort chains */ 569aae69bed019826ddec93f761514652a93d871e49Harald Welte 570aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 5710113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 5729e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 573aae69bed019826ddec93f761514652a93d871e49Harald Welte 574aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 575aae69bed019826ddec93f761514652a93d871e49Harald Welte * RULESET COMPILATION (cache -> blob) 576aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 577aae69bed019826ddec93f761514652a93d871e49Harald Welte 578aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Convenience structures */ 579aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_start{ 580aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY e; 581aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_error_target name; 582aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 583aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) + \ 584aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target))) 585aae69bed019826ddec93f761514652a93d871e49Harald Welte 586aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_foot { 587aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY e; 588aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET target; 589aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 590aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_FOOT_SIZE (sizeof(STRUCT_ENTRY) + \ 591aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(STRUCT_STANDARD_TARGET))) 592aae69bed019826ddec93f761514652a93d871e49Harald Welte 593aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_error { 594aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY entry; 595aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_error_target target; 596aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 597aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) + \ 598aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target))) 599aae69bed019826ddec93f761514652a93d871e49Harald Welte 600aae69bed019826ddec93f761514652a93d871e49Harald Welte 601aae69bed019826ddec93f761514652a93d871e49Harald Welte 602aae69bed019826ddec93f761514652a93d871e49Harald Welte/* compile rule from cache into blob */ 603aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int iptcc_compile_rule (TC_HANDLE_T h, STRUCT_REPLACE *repl, struct rule_head *r) 6040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 605aae69bed019826ddec93f761514652a93d871e49Harald Welte /* handle jumps */ 606aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type == IPTCC_R_JUMP) { 607aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 608aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 609aae69bed019826ddec93f761514652a93d871e49Harald Welte /* memset for memcmp convenience on delete/replace */ 610aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 611aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(t->target.u.user.name, STANDARD_TARGET); 612aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Jumps can only happen to builtin chains, so we 613aae69bed019826ddec93f761514652a93d871e49Harald Welte * can safely assume that they always have a header */ 614aae69bed019826ddec93f761514652a93d871e49Harald Welte t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE; 615aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (r->type == IPTCC_R_FALLTHROUGH) { 616aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 617aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 618aae69bed019826ddec93f761514652a93d871e49Harald Welte t->verdict = r->offset + r->size; 619aae69bed019826ddec93f761514652a93d871e49Harald Welte } 620aae69bed019826ddec93f761514652a93d871e49Harald Welte 621aae69bed019826ddec93f761514652a93d871e49Harald Welte /* copy entry from cache to blob */ 622aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy((char *)repl->entries+r->offset, r->entry, r->size); 623aae69bed019826ddec93f761514652a93d871e49Harald Welte 624aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 625e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 626e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 627aae69bed019826ddec93f761514652a93d871e49Harald Welte/* compile chain from cache into blob */ 628aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain_head *c) 6293ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 630aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 631aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 632aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_start *head; 633aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_foot *foot; 634aae69bed019826ddec93f761514652a93d871e49Harald Welte 635aae69bed019826ddec93f761514652a93d871e49Harald Welte /* only user-defined chains have heaer */ 636aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 637aae69bed019826ddec93f761514652a93d871e49Harald Welte /* put chain header in place */ 638aae69bed019826ddec93f761514652a93d871e49Harald Welte head = (void *)repl->entries + c->head_offset; 639aae69bed019826ddec93f761514652a93d871e49Harald Welte head->e.target_offset = sizeof(STRUCT_ENTRY); 640aae69bed019826ddec93f761514652a93d871e49Harald Welte head->e.next_offset = IPTCB_CHAIN_START_SIZE; 641aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(head->name.t.u.user.name, ERROR_TARGET); 642aae69bed019826ddec93f761514652a93d871e49Harald Welte head->name.t.u.target_size = 643aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target)); 644aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(head->name.error, c->name); 645aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 646aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->hook_entry[c->hooknum-1] = c->head_offset; 647aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->underflow[c->hooknum-1] = c->foot_offset; 648aae69bed019826ddec93f761514652a93d871e49Harald Welte } 649aae69bed019826ddec93f761514652a93d871e49Harald Welte 650aae69bed019826ddec93f761514652a93d871e49Harald Welte /* iterate over rules */ 651aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 652aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_rule(h, repl, r); 653aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 654aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 655aae69bed019826ddec93f761514652a93d871e49Harald Welte } 656aae69bed019826ddec93f761514652a93d871e49Harald Welte 657aae69bed019826ddec93f761514652a93d871e49Harald Welte /* put chain footer in place */ 658aae69bed019826ddec93f761514652a93d871e49Harald Welte foot = (void *)repl->entries + c->foot_offset; 659aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->e.target_offset = sizeof(STRUCT_ENTRY); 660aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE; 661aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(foot->target.target.u.user.name, STANDARD_TARGET); 662aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.target.u.target_size = 663aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 664aae69bed019826ddec93f761514652a93d871e49Harald Welte /* builtin targets have verdict, others return */ 665aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_is_builtin(c)) 666aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.verdict = c->verdict; 667aae69bed019826ddec93f761514652a93d871e49Harald Welte else 668aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.verdict = RETURN; 669aae69bed019826ddec93f761514652a93d871e49Harald Welte /* set policy-counters */ 670aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS)); 671aae69bed019826ddec93f761514652a93d871e49Harald Welte 672aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 6733ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 6743ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 675aae69bed019826ddec93f761514652a93d871e49Harald Welte/* calculate offset and number for every rule in the cache */ 676aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_chain_offsets(TC_HANDLE_T h, struct chain_head *c, 677efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte unsigned int *offset, unsigned int *num) 6783ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 679aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 680aae69bed019826ddec93f761514652a93d871e49Harald Welte 681aae69bed019826ddec93f761514652a93d871e49Harald Welte c->head_offset = *offset; 682aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("%s: chain_head %u, offset=%u\n", c->name, *num, *offset); 683aae69bed019826ddec93f761514652a93d871e49Harald Welte 684aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 685aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Chain has header */ 686aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += sizeof(STRUCT_ENTRY) 687aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(struct ipt_error_target)); 688aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 689aae69bed019826ddec93f761514652a93d871e49Harald Welte } 690aae69bed019826ddec93f761514652a93d871e49Harald Welte 691aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 692aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("rule %u, offset=%u, index=%u\n", *num, *offset, *num); 693aae69bed019826ddec93f761514652a93d871e49Harald Welte r->offset = *offset; 694aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index = *num; 695aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += r->size; 696aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 697aae69bed019826ddec93f761514652a93d871e49Harald Welte } 698aae69bed019826ddec93f761514652a93d871e49Harald Welte 699aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num, 700aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset, *num); 701aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_offset = *offset; 702aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index = *num; 703aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += sizeof(STRUCT_ENTRY) 704aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 705aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 706aae69bed019826ddec93f761514652a93d871e49Harald Welte 707aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 7083ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 7093ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 710aae69bed019826ddec93f761514652a93d871e49Harald Welte/* put the pieces back together again */ 711aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_table_prep(TC_HANDLE_T h, unsigned int *size) 712aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 713aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 714aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset = 0, num = 0; 715aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret = 0; 7163ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 717aae69bed019826ddec93f761514652a93d871e49Harald Welte /* First pass: calculate offset for every rule */ 718aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 719aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_chain_offsets(h, c, &offset, &num); 720aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 721aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 722aae69bed019826ddec93f761514652a93d871e49Harald Welte } 723aae69bed019826ddec93f761514652a93d871e49Harald Welte 724aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Append one error rule at end of chain */ 725aae69bed019826ddec93f761514652a93d871e49Harald Welte num++; 726aae69bed019826ddec93f761514652a93d871e49Harald Welte offset += sizeof(STRUCT_ENTRY) 727aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(struct ipt_error_target)); 728aae69bed019826ddec93f761514652a93d871e49Harald Welte 729aae69bed019826ddec93f761514652a93d871e49Harald Welte /* ruleset size is now in offset */ 730aae69bed019826ddec93f761514652a93d871e49Harald Welte *size = offset; 731aae69bed019826ddec93f761514652a93d871e49Harald Welte return num; 732aae69bed019826ddec93f761514652a93d871e49Harald Welte} 733aae69bed019826ddec93f761514652a93d871e49Harald Welte 734aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE *repl) 7350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 736aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 737aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_error *error; 7380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 739aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Second pass: copy from cache to offsets, fill in jumps */ 740aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 741aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret = iptcc_compile_chain(h, repl, c); 742aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 743aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 7440113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 7450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 746aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Append error rule at end of chain */ 747aae69bed019826ddec93f761514652a93d871e49Harald Welte error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE; 748aae69bed019826ddec93f761514652a93d871e49Harald Welte error->entry.target_offset = sizeof(STRUCT_ENTRY); 749aae69bed019826ddec93f761514652a93d871e49Harald Welte error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE; 750aae69bed019826ddec93f761514652a93d871e49Harald Welte error->target.t.u.user.target_size = 751aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target)); 752aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET); 753aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy((char *)&error->target.error, "ERROR"); 754aae69bed019826ddec93f761514652a93d871e49Harald Welte 755aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 7560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 757e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 758aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 759aae69bed019826ddec93f761514652a93d871e49Harald Welte * EXTERNAL API (operates on cache only) 760aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 761aae69bed019826ddec93f761514652a93d871e49Harald Welte 762e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Allocate handle of given size */ 76379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic TC_HANDLE_T 7640113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltealloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 765e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 766e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher size_t len; 76779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 768e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 769aae69bed019826ddec93f761514652a93d871e49Harald Welte len = sizeof(STRUCT_TC_HANDLE) + size; 770e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 771aae69bed019826ddec93f761514652a93d871e49Harald Welte h = malloc(sizeof(STRUCT_TC_HANDLE)); 772aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h) { 773e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 774e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 775e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 776aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(h, 0, sizeof(*h)); 777aae69bed019826ddec93f761514652a93d871e49Harald Welte INIT_LIST_HEAD(&h->chains); 778e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(h->info.name, tablename); 779aae69bed019826ddec93f761514652a93d871e49Harald Welte 7800371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size); 781aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h->entries) 782aae69bed019826ddec93f761514652a93d871e49Harald Welte goto out_free_handle; 783aae69bed019826ddec93f761514652a93d871e49Harald Welte 784aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(h->entries->name, tablename); 7850371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries->size = size; 786e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 787e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 788aae69bed019826ddec93f761514652a93d871e49Harald Welte 789aae69bed019826ddec93f761514652a93d871e49Harald Welteout_free_handle: 790aae69bed019826ddec93f761514652a93d871e49Harald Welte free(h); 791aae69bed019826ddec93f761514652a93d871e49Harald Welte 792aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 793e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 794e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 795aae69bed019826ddec93f761514652a93d871e49Harald Welte 79679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_HANDLE_T 79779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INIT(const char *tablename) 798e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 79979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 80079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 801efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte unsigned int tmp; 802e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher socklen_t s; 803e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 80479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INIT; 805e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 806841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson if (strlen(tablename) >= TABLE_MAXNAMELEN) { 807841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson errno = EINVAL; 808841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson return NULL; 809841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 810841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 811664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (sockfd_use == 0) { 812664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 813664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (sockfd < 0) 814664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates return NULL; 815664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 816664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates sockfd_use++; 817e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 818e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher s = sizeof(info); 819841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 820e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(info.name, tablename); 821664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) { 822664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (--sockfd_use == 0) { 823664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates close(sockfd); 824664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates sockfd = -1; 825664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 826e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 827664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 828e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 829aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n", 830aae69bed019826ddec93f761514652a93d871e49Harald Welte info.valid_hooks, info.num_entries, info.size); 831aae69bed019826ddec93f761514652a93d871e49Harald Welte 8320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((h = alloc_handle(info.name, info.size, info.num_entries)) 833841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson == NULL) { 834664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (--sockfd_use == 0) { 835664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates close(sockfd); 836664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates sockfd = -1; 837664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 838e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 839841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 840e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 841e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Initialize current state */ 842e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->info = info; 8430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 844aae69bed019826ddec93f761514652a93d871e49Harald Welte h->entries->size = h->info.size; 845e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 84679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 847e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 848aae69bed019826ddec93f761514652a93d871e49Harald Welte if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries, 849aae69bed019826ddec93f761514652a93d871e49Harald Welte &tmp) < 0) 850aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 851aae69bed019826ddec93f761514652a93d871e49Harald Welte 852aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 853aae69bed019826ddec93f761514652a93d871e49Harald Welte { 854aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_get_entries.blob", 855aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 856aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 857aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, h->entries, tmp); 858aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 859aae69bed019826ddec93f761514652a93d871e49Harald Welte } 860e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 861aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 862aae69bed019826ddec93f761514652a93d871e49Harald Welte 863aae69bed019826ddec93f761514652a93d871e49Harald Welte if (parse_table(h) < 0) 864aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 8657e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 866e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(h); 867e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 868aae69bed019826ddec93f761514652a93d871e49Harald Welteerror: 869664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (--sockfd_use == 0) { 870664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates close(sockfd); 871664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates sockfd = -1; 872664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 873aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_FREE(&h); 874aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 875e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 876e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 877841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefssonvoid 878841e4aed2349046eb2c0b1375139c06569a93bd0Martin JosefssonTC_FREE(TC_HANDLE_T *h) 879841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson{ 880aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c, *tmp; 881aae69bed019826ddec93f761514652a93d871e49Harald Welte 882664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_FREE; 883664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (--sockfd_use == 0) { 884664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates close(sockfd); 885664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates sockfd = -1; 886664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 887aae69bed019826ddec93f761514652a93d871e49Harald Welte 888aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(c, tmp, &(*h)->chains, list) { 889aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *rtmp; 890aae69bed019826ddec93f761514652a93d871e49Harald Welte 891aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, rtmp, &c->rules, list) { 892aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 893aae69bed019826ddec93f761514652a93d871e49Harald Welte } 894aae69bed019826ddec93f761514652a93d871e49Harald Welte 895aae69bed019826ddec93f761514652a93d871e49Harald Welte free(c); 896aae69bed019826ddec93f761514652a93d871e49Harald Welte } 897aae69bed019826ddec93f761514652a93d871e49Harald Welte 898aae69bed019826ddec93f761514652a93d871e49Harald Welte free((*h)->entries); 899841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson free(*h); 900aae69bed019826ddec93f761514652a93d871e49Harald Welte 901841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson *h = NULL; 902841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson} 903841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 904e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 90579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellprint_match(const STRUCT_ENTRY_MATCH *m) 906e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 907228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell printf("Match name: `%s'\n", m->u.user.name); 908e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 909e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 910e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 91179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle); 91279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell 913e6869a8f59d779ff4d5a0984c86d80db7078496Marc Bouchervoid 91479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DUMP_ENTRIES(const TC_HANDLE_T handle) 915e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 916664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_DUMP_ENTRIES; 917e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(handle); 918aae69bed019826ddec93f761514652a93d871e49Harald Welte#if 0 919e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell printf("libiptc v%s. %u bytes.\n", 920e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell IPTABLES_VERSION, handle->entries->size); 921e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Table `%s'\n", handle->info.name); 922e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 92367088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_PRE_ROUTING], 92467088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_IN], 92567088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_FORWARD], 92667088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_OUT], 92767088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_POST_ROUTING]); 928e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 92967088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_PRE_ROUTING], 93067088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_IN], 93167088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_FORWARD], 93267088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_OUT], 93367088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_POST_ROUTING]); 934e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 935aae69bed019826ddec93f761514652a93d871e49Harald Welte ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size, 93679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell dump_entry, handle); 937aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 9380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 939e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 940e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Does this chain exist? */ 94179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle) 942e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 943664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_IS_CHAIN; 944aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_find_label(chain, handle) != NULL; 945e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 946e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 947aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void iptcc_chain_iterator_advance(TC_HANDLE_T handle) 948aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 949aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = handle->chain_iterator_cur; 950aae69bed019826ddec93f761514652a93d871e49Harald Welte 951aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->list.next == &handle->chains) 952aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->chain_iterator_cur = NULL; 953aae69bed019826ddec93f761514652a93d871e49Harald Welte else 954aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->chain_iterator_cur = 955aae69bed019826ddec93f761514652a93d871e49Harald Welte list_entry(c->list.next, struct chain_head, list); 956aae69bed019826ddec93f761514652a93d871e49Harald Welte} 957e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 95830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. */ 959e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 9608c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_CHAIN(TC_HANDLE_T *handle) 961e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 962aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = list_entry((*handle)->chains.next, 963aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head, list); 964aae69bed019826ddec93f761514652a93d871e49Harald Welte 965aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_CHAIN; 966aae69bed019826ddec93f761514652a93d871e49Harald Welte 967aae69bed019826ddec93f761514652a93d871e49Harald Welte 968aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&(*handle)->chains)) { 969aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no chains\n"); 9700113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 971aae69bed019826ddec93f761514652a93d871e49Harald Welte } 9720113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 973aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->chain_iterator_cur = c; 974aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 97530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 976aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 977aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 97830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 97930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 98030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. Returns NULL at end. */ 98130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellconst char * 98279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NEXT_CHAIN(TC_HANDLE_T *handle) 98330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 984aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = (*handle)->chain_iterator_cur; 985aae69bed019826ddec93f761514652a93d871e49Harald Welte 986aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_CHAIN; 98730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 988aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 989aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no more chains\n"); 99030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 991aae69bed019826ddec93f761514652a93d871e49Harald Welte } 99230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 993aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 994aae69bed019826ddec93f761514652a93d871e49Harald Welte 995aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 996aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 99730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 99830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 99930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Get first rule in the given chain: NULL for empty chain. */ 100079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 10018c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_RULE(const char *chain, TC_HANDLE_T *handle) 100230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 1003aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1004aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1005aae69bed019826ddec93f761514652a93d871e49Harald Welte 1006aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_RULE; 100730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1008aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("first rule(%s): ", chain); 1009aae69bed019826ddec93f761514652a93d871e49Harald Welte 1010aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 101130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!c) { 101230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell errno = ENOENT; 101330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1014e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1015e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 101630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Empty chain: single return/policy rule */ 1017aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&c->rules)) { 1018aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("no rules, returning NULL\n"); 101930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1020aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1021aae69bed019826ddec93f761514652a93d871e49Harald Welte 1022aae69bed019826ddec93f761514652a93d871e49Harald Welte r = list_entry(c->rules.next, struct rule_head, list); 1023aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = r; 1024aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%p\n", r); 102530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1026aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 1027e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1028e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 102930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Returns NULL when rules run out. */ 103079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 10318c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle) 103230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 1033aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1034aae69bed019826ddec93f761514652a93d871e49Harald Welte 1035664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_NEXT_RULE; 1036aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("rule_iterator_cur=%p...", (*handle)->rule_iterator_cur); 1037aae69bed019826ddec93f761514652a93d871e49Harald Welte 1038aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(*handle)->rule_iterator_cur) { 1039aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning NULL\n"); 104030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1041aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1042aae69bed019826ddec93f761514652a93d871e49Harald Welte 1043aae69bed019826ddec93f761514652a93d871e49Harald Welte r = list_entry((*handle)->rule_iterator_cur->list.next, 1044aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 104530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1046aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_RULE; 1047aae69bed019826ddec93f761514652a93d871e49Harald Welte 1048aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("next=%p, head=%p...", &r->list, 1049aae69bed019826ddec93f761514652a93d871e49Harald Welte &(*handle)->rule_iterator_cur->chain->rules); 1050aae69bed019826ddec93f761514652a93d871e49Harald Welte 1051aae69bed019826ddec93f761514652a93d871e49Harald Welte if (&r->list == &(*handle)->rule_iterator_cur->chain->rules) { 1052aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = NULL; 1053aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("finished, returning NULL\n"); 1054aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1055aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1056aae69bed019826ddec93f761514652a93d871e49Harald Welte 1057aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = r; 1058aae69bed019826ddec93f761514652a93d871e49Harald Welte 1059aae69bed019826ddec93f761514652a93d871e49Harald Welte /* NOTE: prev is without any influence ! */ 1060aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning rule %p\n", r); 1061aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 106230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 106330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1064e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* How many rules in this chain? */ 1065e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherunsigned int 106679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NUM_RULES(const char *chain, TC_HANDLE_T *handle) 1067e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1068aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1069aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NUM_RULES; 1070e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1071aae69bed019826ddec93f761514652a93d871e49Harald Welte 1072aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1073aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1074e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1075e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return (unsigned int)-1; 1076e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1077aae69bed019826ddec93f761514652a93d871e49Harald Welte 1078aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->num_rules; 1079e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1080e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 108179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY *TC_GET_RULE(const char *chain, 108279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int n, 108379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1084e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1085aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1086aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1087aae69bed019826ddec93f761514652a93d871e49Harald Welte 1088aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_RULE; 1089e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1090e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1091aae69bed019826ddec93f761514652a93d871e49Harald Welte 1092aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1093aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1094e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1095e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1096e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1097e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1098aae69bed019826ddec93f761514652a93d871e49Harald Welte r = iptcc_get_rule_num(c, n); 1099aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!r) 1100aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1101aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 1102e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1103e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1104aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 1105aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char *standard_target_map(int verdict) 1106e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1107aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (verdict) { 1108aae69bed019826ddec93f761514652a93d871e49Harald Welte case RETURN: 110979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_RETURN; 1110aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1111aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_ACCEPT-1: 111279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_ACCEPT; 1113aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1114aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_DROP-1: 1115aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_DROP; 1116aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1117aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_QUEUE-1: 1118aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_QUEUE; 1119aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1120aae69bed019826ddec93f761514652a93d871e49Harald Welte default: 1121aae69bed019826ddec93f761514652a93d871e49Harald Welte fprintf(stderr, "ERROR: %d not a valid target)\n", 1122aae69bed019826ddec93f761514652a93d871e49Harald Welte verdict); 1123aae69bed019826ddec93f761514652a93d871e49Harald Welte abort(); 1124aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1125e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1126aae69bed019826ddec93f761514652a93d871e49Harald Welte /* not reached */ 1127aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1128e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1129e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1130aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 1131aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char *TC_GET_TARGET(const STRUCT_ENTRY *ce, 1132aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T *handle) 1133e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1134aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 1135e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell struct rule_head *r = container_of(e, struct rule_head, entry[0]); 1136e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1137aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_TARGET; 11380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1139aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(r->type) { 1140aae69bed019826ddec93f761514652a93d871e49Harald Welte int spos; 1141aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_FALLTHROUGH: 1142aae69bed019826ddec93f761514652a93d871e49Harald Welte return ""; 1143aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1144aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_JUMP: 1145aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name); 1146aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->jump->name; 1147aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1148aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_STANDARD: 1149aae69bed019826ddec93f761514652a93d871e49Harald Welte spos = *(int *)GET_TARGET(e)->data; 1150aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, spos=%d'\n", r, spos); 1151aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(spos); 1152aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1153aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_MODULE: 1154aae69bed019826ddec93f761514652a93d871e49Harald Welte return GET_TARGET(e)->u.user.name; 1155aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 11560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 1157aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1158aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1159aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Is this a built-in chain? Actually returns hook + 1. */ 1160aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1161aae69bed019826ddec93f761514652a93d871e49Harald WelteTC_BUILTIN(const char *chain, const TC_HANDLE_T handle) 1162aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1163aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1164aae69bed019826ddec93f761514652a93d871e49Harald Welte 1165aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_BUILTIN; 11660113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1167aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, handle); 1168aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1169aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1170b0f3d2d7261be3fe256a66abcc237241fea43a02Martin Josefsson return 0; 11710113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 11720113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1173aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_is_builtin(c); 11740113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 11750113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1176aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Get the policy of a given built-in chain */ 1177aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char * 1178aae69bed019826ddec93f761514652a93d871e49Harald WelteTC_GET_POLICY(const char *chain, 1179aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters, 1180aae69bed019826ddec93f761514652a93d871e49Harald Welte TC_HANDLE_T *handle) 11810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 1182aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 11830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1184aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_POLICY; 1185fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte 1186aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("called for chain %s\n", chain); 11870113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1188aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, *handle); 1189aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1190aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1191aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 11920113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 11930113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1194aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) 1195aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 11960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1197aae69bed019826ddec93f761514652a93d871e49Harald Welte *counters = c->counters; 11980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1199aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(c->verdict); 12000113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 1201e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1202e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1203aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_standard_map(struct rule_head *r, int verdict) 1204e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1205aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 120679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 1207e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 120879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1209e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 121067088e73ce7707229c56987868f112051defca5aRusty Russell if (t->target.u.target_size 12118c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1212e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1213e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1214e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1215e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset for memcmp convenience on delete/replace */ 121679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 121779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell strcpy(t->target.u.user.name, STANDARD_TARGET); 1218e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = verdict; 1219e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1220aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_STANDARD; 1221aae69bed019826ddec93f761514652a93d871e49Harald Welte 1222e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1223e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 12247e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1225e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1226aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_map_target(const TC_HANDLE_T handle, 1227aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r) 1228e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1229aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 12300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 1231e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1232e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's empty (=> fall through) */ 1233aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(t->u.user.name, "") == 0) { 1234aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_FALLTHROUGH; 1235aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1236aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1237e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's a standard target name... */ 123879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 1239aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_ACCEPT - 1); 124079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 1241aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_DROP - 1); 124267088e73ce7707229c56987868f112051defca5aRusty Russell else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 1243aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_QUEUE - 1); 124479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 1245aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, RETURN); 124679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (TC_BUILTIN(t->u.user.name, handle)) { 1247e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Can't jump to builtins. */ 1248e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1249e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1250e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 1251e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's an existing chain name. */ 1252aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1253aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("trying to find chain `%s': ", t->u.user.name); 1254aae69bed019826ddec93f761514652a93d871e49Harald Welte 1255aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(t->u.user.name, handle); 1256aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c) { 1257aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("found!\n"); 1258aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_JUMP; 1259aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump = c; 1260aae69bed019826ddec93f761514652a93d871e49Harald Welte c->references++; 1261aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1262aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1263aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("not found :(\n"); 1264e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1265e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1266e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Must be a module? If not, kernel will reject... */ 12673aef54dce4f9bbe0b466478fd33a1d3131efbbb8Rusty Russell /* memset to all 0 for your memcmp convenience: don't clear version */ 1268228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell memset(t->u.user.name + strlen(t->u.user.name), 1269e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 0, 12703aef54dce4f9bbe0b466478fd33a1d3131efbbb8Rusty Russell FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name)); 1271733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell r->type = IPTCC_R_MODULE; 1272aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(handle); 1273aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1274e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1275e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 12760113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 1277e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 127879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 127979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 128079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 128179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1282e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1283aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1284eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson struct rule_head *r; 1285eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson struct list_head *prev; 1286e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 128779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INSERT_ENTRY; 1288aae69bed019826ddec93f761514652a93d871e49Harald Welte 1289aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1290e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1291e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1292e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1293e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1294eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson /* first rulenum index = 0 1295eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson first c->num_rules index = 1 */ 1296eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson if (rulenum > c->num_rules) { 1297e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1298e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1299e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1300e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1301631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson /* If we are inserting at the end just take advantage of the 1302631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson double linked list, insert will happen before the entry 1303631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson prev points to. */ 1304631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson if (rulenum == c->num_rules) { 1305eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson prev = &c->rules; 1306a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else if (rulenum + 1 <= c->num_rules/2) { 1307631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson r = iptcc_get_rule_num(c, rulenum + 1); 1308a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson prev = &r->list; 1309a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else { 1310a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1311631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson prev = &r->list; 1312631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson } 1313eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson 1314aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1315aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1316aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1317aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1318aae69bed019826ddec93f761514652a93d871e49Harald Welte 1319aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1320aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1321aae69bed019826ddec93f761514652a93d871e49Harald Welte 1322aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 1323aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 13240113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1325aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1326aae69bed019826ddec93f761514652a93d871e49Harald Welte 1327eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson list_add_tail(&r->list, prev); 1328aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1329aae69bed019826ddec93f761514652a93d871e49Harald Welte 1330aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1331e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1332aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1333e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1334e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1335e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 1336e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 133779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 133879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 133979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 134079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1341e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1342aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1343aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *old; 1344e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 134579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_REPLACE_ENTRY; 1346e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1347aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1348e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1349e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1350e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1351e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13520f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson if (rulenum >= c->num_rules) { 1353e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1354e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1355e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1356e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13570f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson /* Take advantage of the double linked list if possible. */ 13580f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson if (rulenum + 1 <= c->num_rules/2) { 13590f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson old = iptcc_get_rule_num(c, rulenum + 1); 13600f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson } else { 13610f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson old = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 13620f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson } 13630f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson 1364aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1365aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1366e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1367aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1368aae69bed019826ddec93f761514652a93d871e49Harald Welte 1369aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1370aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1371e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1372aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 1373aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 13740113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1375aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1376aae69bed019826ddec93f761514652a93d871e49Harald Welte 1377aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add(&r->list, &old->list); 1378aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(old); 13790113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1380aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1381aae69bed019826ddec93f761514652a93d871e49Harald Welte 1382aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1383e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1384e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Append entry `fw' to chain `chain'. Equivalent to insert with 1386e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher rulenum = length of chain. */ 1387e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 138879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 138979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 139079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1391e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1392aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1393aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1394e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 139579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_APPEND_ENTRY; 1396aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1397aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to find chain `%s'\n", chain); 1398e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1399e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1400e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1401e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1402aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1403aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to allocate rule for chain `%s'\n", chain); 1404aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1405aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1406aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1407aae69bed019826ddec93f761514652a93d871e49Harald Welte 1408aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1409aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1410aae69bed019826ddec93f761514652a93d871e49Harald Welte 1411aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_map_target(*handle, r)) { 141212009531e6a96a62ee398eb0ab3e9ec0b3b57701Martin Josefsson DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1413aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 14140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1415aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1416aae69bed019826ddec93f761514652a93d871e49Harald Welte 1417aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &c->rules); 1418aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1419aae69bed019826ddec93f761514652a93d871e49Harald Welte 1420aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 14210113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1422aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1423e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1424e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1425e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 142679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellmatch_different(const STRUCT_ENTRY_MATCH *a, 1427edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *a_elems, 1428edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_elems, 1429edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned char **maskptr) 1430e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 143179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY_MATCH *b; 1432edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1433e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1434e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Offset of b is the same as a. */ 143530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell b = (void *)b_elems + ((unsigned char *)a - a_elems); 1436e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1437228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (a->u.match_size != b->u.match_size) 1438e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1439e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1440228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (strcmp(a->u.user.name, b->u.user.name) != 0) 1441e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1442e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 144373ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell *maskptr += ALIGN(sizeof(*a)); 1444edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 144573ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1446edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1447edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 1; 1448edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell *maskptr += i; 1449edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 0; 1450edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell} 1451edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 1452edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russellstatic inline int 1453733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russelltarget_same(struct rule_head *a, struct rule_head *b,const unsigned char *mask) 1454edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell{ 1455edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1456733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell STRUCT_ENTRY_TARGET *ta, *tb; 1457e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1458733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (a->type != b->type) 1459733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1460733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1461733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell ta = GET_TARGET(a->entry); 1462733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell tb = GET_TARGET(b->entry); 1463733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1464733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell switch (a->type) { 1465733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_FALLTHROUGH: 1466733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 1467733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_JUMP: 1468733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return a->jump == b->jump; 1469733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_STANDARD: 1470733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return ((STRUCT_STANDARD_TARGET *)ta)->verdict 1471733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell == ((STRUCT_STANDARD_TARGET *)tb)->verdict; 1472733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_MODULE: 1473733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (ta->u.target_size != tb->u.target_size) 1474733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1475733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (strcmp(ta->u.user.name, tb->u.user.name) != 0) 1476733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1477733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1478733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell for (i = 0; i < ta->u.target_size - sizeof(*ta); i++) 1479daade4452715cbd1feea05d5231c5e38e3b0b98bRusty Russell if (((ta->data[i] ^ tb->data[i]) & mask[i]) != 0) 1480733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1481733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 1482733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell default: 1483733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell fprintf(stderr, "ERROR: bad type %i\n", a->type); 1484733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell abort(); 1485733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell } 1486e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1487e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1488733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russellstatic unsigned char * 148979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellis_same(const STRUCT_ENTRY *a, 149079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *b, 149179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask); 1492e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 14930113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Delete the first rule in `chain' which matches `fw'. */ 1494e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 149579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_ENTRY(const IPT_CHAINLABEL chain, 149679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *origfw, 149779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask, 149879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1499e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1500aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1501e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell struct rule_head *r, *i; 1502e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 150379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_ENTRY; 1504aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1505e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1506e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1507e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1508e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1509e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell /* Create a rule_head from origfw. */ 1510e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell r = iptcc_alloc_rule(c, origfw->next_offset); 1511e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell if (!r) { 15120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = ENOMEM; 15130113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 15140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 15150113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1516e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell memcpy(r->entry, origfw, origfw->next_offset); 1517e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell r->counter_map.maptype = COUNTER_MAP_NOMAP; 1518e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell if (!iptcc_map_target(*handle, r)) { 1519e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1520e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell free(r); 1521e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell return 0; 1522e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell } 1523fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 1524e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell list_for_each_entry(i, &c->rules, list) { 1525733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell unsigned char *mask; 1526733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1527733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell mask = is_same(r->entry, i->entry, matchmask); 1528733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (!mask) 1529733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell continue; 1530733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1531733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (!target_same(r, i, mask)) 1532733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell continue; 1533733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1534733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell /* If we are about to delete the rule that is the 1535733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell * current iterator, move rule iterator back. next 1536733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell * pointer will then point to real next node */ 1537733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (i == (*handle)->rule_iterator_cur) { 1538733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell (*handle)->rule_iterator_cur = 1539733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell list_entry((*handle)->rule_iterator_cur->list.prev, 1540733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell struct rule_head, list); 1541733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell } 1542fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 1543733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell c->num_rules--; 1544733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell iptcc_delete_rule(i); 15452a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson 1546733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell set_changed(*handle); 1547733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell free(r); 1548733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 1549e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1550e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1551e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell free(r); 1552e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1553e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 15547e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell} 1555aae69bed019826ddec93f761514652a93d871e49Harald Welte 1556e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1557e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Delete the rule in position `rulenum' in `chain'. */ 1558e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 155979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 156079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 156179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1562e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1563aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1564aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1565e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 156679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_NUM_ENTRY; 1567aae69bed019826ddec93f761514652a93d871e49Harald Welte 1568aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1569e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1570e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1571e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1572e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1573a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson if (rulenum >= c->num_rules) { 1574631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson errno = E2BIG; 1575631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson return 0; 1576631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson } 1577631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson 1578631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson /* Take advantage of the double linked list if possible. */ 1579a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson if (rulenum + 1 <= c->num_rules/2) { 1580a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num(c, rulenum + 1); 1581a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else { 1582a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1583e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1584e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1585aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the rule that is the current 1586aae69bed019826ddec93f761514652a93d871e49Harald Welte * iterator, move rule iterator back. next pointer will then 1587aae69bed019826ddec93f761514652a93d871e49Harald Welte * point to real next node */ 1588aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r == (*handle)->rule_iterator_cur) { 1589aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->rule_iterator_cur = 1590aae69bed019826ddec93f761514652a93d871e49Harald Welte list_entry((*handle)->rule_iterator_cur->list.prev, 1591aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 15920113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 1593e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1594aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules--; 1595aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 1596aae69bed019826ddec93f761514652a93d871e49Harald Welte 15972a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson set_changed(*handle); 15982a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson 1599aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1600e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1601e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1602e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Check the packet `fw' on chain `chain'. Returns the verdict, or 1603e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher NULL and sets errno. */ 1604e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 160579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CHECK_PACKET(const IPT_CHAINLABEL chain, 160679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *entry, 160779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1608e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1609664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_CHECK_PACKET; 1610e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOSYS; 1611e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1612e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1613e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1614e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Flushes the entries in the given chain (ie. empties chain). */ 1615e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 161679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1617e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1618aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1619aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *tmp; 1620e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 16210113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte iptc_fn = TC_FLUSH_ENTRIES; 1622aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1623e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1624e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1625e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1626e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1627aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, tmp, &c->rules, list) { 1628aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 1629aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1630aae69bed019826ddec93f761514652a93d871e49Harald Welte 1631aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules = 0; 1632aae69bed019826ddec93f761514652a93d871e49Harald Welte 1633aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1634aae69bed019826ddec93f761514652a93d871e49Harald Welte 1635aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1636e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1637e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1638e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Zeroes the counters in a chain. */ 1639e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 164079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1641e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1642aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1643aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 16447e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1645664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_ZERO_ENTRIES; 1646aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1647e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1648e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1649e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1650e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1651aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 1652aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 1653aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 1654e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1655aae69bed019826ddec93f761514652a93d871e49Harald Welte 1656175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1657e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1658e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1659e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1660e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 16611cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteSTRUCT_COUNTERS * 16621cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_READ_COUNTER(const IPT_CHAINLABEL chain, 16631cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 16641cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 16651cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1666aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1667aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 16681cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16691cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_READ_COUNTER; 16701cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 16711cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1672aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 16731cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 16741cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return NULL; 16751cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 16761cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1677aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 16780113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 16790113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 16800113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 16810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1682aae69bed019826ddec93f761514652a93d871e49Harald Welte return &r->entry[0].counters; 16831cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 16841cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16851cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 16861cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 16871cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 16881cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 16891cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1690aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1691aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 16921cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16931cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_ZERO_COUNTER; 16941cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 16951cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1696aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 16971cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 16981cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 16991cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 17001cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1701aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 17020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 17030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 17040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 17050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1706aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 1707aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 17081cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17091cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 17101cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17111cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 17121cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 17131cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17141cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 17151cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_SET_COUNTER(const IPT_CHAINLABEL chain, 17161cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 17171cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 17181cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 17191cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 1720aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1721aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 17221cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 17231cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17241cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_SET_COUNTER; 17251cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 17261cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1727aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 17281cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 17291cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 17301cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 17310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1732aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 17330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 17340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 17350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 17360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1737aae69bed019826ddec93f761514652a93d871e49Harald Welte e = r->entry; 1738aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 17390113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 17400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 17411cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17421cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 17431cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17441cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 17451cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 17461cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1747e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Creates a new chain. */ 1748e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* To create a chain, create two rules: error node and unconditional 1749e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * return. */ 1750e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 175179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1752e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1753aae69bed019826ddec93f761514652a93d871e49Harald Welte static struct chain_head *c; 1754e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 175579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_CREATE_CHAIN; 1756e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1757e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* find_label doesn't cover built-in targets: DROP, ACCEPT, 1758e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher QUEUE, RETURN. */ 1759aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_find_label(chain, *handle) 176079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_DROP) == 0 176179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_ACCEPT) == 0 176267088e73ce7707229c56987868f112051defca5aRusty Russell || strcmp(chain, LABEL_QUEUE) == 0 176379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_RETURN) == 0) { 1764aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain `%s' already exists\n", chain); 1765e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1766e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1767e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1768e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 176979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 1770aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain name `%s' too long\n", chain); 1771e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1772e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1773e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1774e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1775aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_alloc_chain_head(chain, 0); 1776aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1777aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Cannot allocate memory for chain `%s'\n", chain); 1778aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1779aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1780e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1781aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1782e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1783aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Creating chain `%s'\n", chain); 1784aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&c->list, &(*handle)->chains); 1785e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1786aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1787e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1788aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1789e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1790e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1791e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get the number of references to this chain. */ 1792e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 179379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 179479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1795e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1796aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1797e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1798664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_GET_REFERENCES; 1799aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1800e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1801e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1802e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1803e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1804aae69bed019826ddec93f761514652a93d871e49Harald Welte *ref = c->references; 1805aae69bed019826ddec93f761514652a93d871e49Harald Welte 1806e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1807e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1808e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1809e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Deletes a chain. */ 1810e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 181179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1812e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1813e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int references; 1814aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 18157e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 181679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_CHAIN; 1817e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1818aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1819aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 1820aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1821aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1822aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1823aae69bed019826ddec93f761514652a93d871e49Harald Welte 182479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (TC_BUILTIN(chain, *handle)) { 1825aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot remove builtin chain `%s'\n", chain); 1826e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1827e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1828e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1829e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1830aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!TC_GET_REFERENCES(&references, chain, handle)) { 1831aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot get references on chain `%s'\n", chain); 1832e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1833e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1834e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1835aae69bed019826ddec93f761514652a93d871e49Harald Welte if (references > 0) { 1836aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' still has references\n", chain); 1837aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EMLINK; 1838e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1839e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1840e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1841aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->num_rules) { 1842aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' is not empty\n", chain); 1843e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOTEMPTY; 1844e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1845e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1846e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1847aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the chain that is the current 1848aae69bed019826ddec93f761514652a93d871e49Harald Welte * iterator, move chain iterator firward. */ 1849aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c == (*handle)->chain_iterator_cur) 1850aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_chain_iterator_advance(*handle); 1851aae69bed019826ddec93f761514652a93d871e49Harald Welte 1852aae69bed019826ddec93f761514652a93d871e49Harald Welte list_del(&c->list); 1853aae69bed019826ddec93f761514652a93d871e49Harald Welte free(c); 18540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1855aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' deleted\n", chain); 18560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1857aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1858aae69bed019826ddec93f761514652a93d871e49Harald Welte 1859aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1860e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1861e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1862e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Renames a chain. */ 186379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 186479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL newname, 186579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1866e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1867aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 186879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_RENAME_CHAIN; 1869e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18701de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte /* find_label doesn't cover built-in targets: DROP, ACCEPT, 18711de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte QUEUE, RETURN. */ 1872aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_find_label(newname, *handle) 187379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_DROP) == 0 187479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_ACCEPT) == 0 18751de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte || strcmp(newname, LABEL_QUEUE) == 0 187679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_RETURN) == 0) { 1877e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1878e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1879e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1880e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1881aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(oldname, *handle)) 188279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || TC_BUILTIN(oldname, *handle)) { 1883e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1884e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1885e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1886e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 188779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 1888e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1889e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1890e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1891e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1892aae69bed019826ddec93f761514652a93d871e49Harald Welte strncpy(c->name, newname, sizeof(IPT_CHAINLABEL)); 1893aae69bed019826ddec93f761514652a93d871e49Harald Welte 18940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte set_changed(*handle); 18950113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1896e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1897e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1898e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1899e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Sets the policy on a built-in chain. */ 1900e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 190179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_SET_POLICY(const IPT_CHAINLABEL chain, 190279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL policy, 19031cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 190479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1905e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1906aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1907e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 190879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_SET_POLICY; 1909aae69bed019826ddec93f761514652a93d871e49Harald Welte 1910aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(c = iptcc_find_label(chain, *handle))) { 1911aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 1912c8264991454b5e77279830736f80ea3153b6f814Marc Boucher errno = ENOENT; 1913e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1914aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1915e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1916aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 1917aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain); 1918aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 19199e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte return 0; 19209e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte } 19219e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 192279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(policy, LABEL_ACCEPT) == 0) 1923aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_ACCEPT - 1; 192479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(policy, LABEL_DROP) == 0) 1925aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_DROP - 1; 1926e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else { 1927e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1928e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1929e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 19301cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 19311cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (counters) { 19321cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte /* set byte and packet counters */ 1933aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS)); 1934aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_SET; 19351cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } else { 1936aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_NOMAP; 19371cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 19381cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1939175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1940e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1941e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1942e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1943e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1944e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Without this, on gcc 2.7.2.3, we get: 194579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell libiptc.c: In function `TC_COMMIT': 1946e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher libiptc.c:833: fixed or forbidden register was spilled. 1947e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher This may be due to a compiler bug or to impossible asm 1948e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher statements or clauses. 1949e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher*/ 1950e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 195179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellsubtract_counters(STRUCT_COUNTERS *answer, 195279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *a, 195379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *b) 1954e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1955e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->pcnt = a->pcnt - b->pcnt; 1956e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->bcnt = a->bcnt - b->bcnt; 1957e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1958e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1959aae69bed019826ddec93f761514652a93d871e49Harald Welte 1960aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, 1961aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index) 1962aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1963aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->counters[index] = ((STRUCT_COUNTERS) { 0, 0}); 1964aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NOMAP => zero\n"); 1965aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1966aae69bed019826ddec93f761514652a93d871e49Harald Welte 1967aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters, 1968aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_REPLACE *repl, 1969aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 1970aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int mappos) 1971aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1972aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 1973aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 1974aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 1975aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: X + Y + Z. 1976aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in X + Y 1977aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in replacement read. 1978aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 1979aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->counters[index] = repl->counters[mappos]; 1980aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos); 1981aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1982aae69bed019826ddec93f761514652a93d871e49Harald Welte 1983aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters, 1984aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_REPLACE *repl, 1985aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 1986aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int mappos, 1987aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters) 1988aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1989aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 1990aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 1991aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 1992aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: Y + Z. 1993aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in Y. 1994aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in (replacement read - original read). 1995aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 1996aae69bed019826ddec93f761514652a93d871e49Harald Welte subtract_counters(&newcounters->counters[index], 1997aae69bed019826ddec93f761514652a93d871e49Harald Welte &repl->counters[mappos], 1998aae69bed019826ddec93f761514652a93d871e49Harald Welte counters); 1999aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("ZEROED => mappos %u\n", mappos); 2000aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2001aae69bed019826ddec93f761514652a93d871e49Harald Welte 2002aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_set(STRUCT_COUNTERS_INFO *newcounters, 2003aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index, 2004aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters) 2005aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 2006aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Want to set counter (iptables-restore) */ 2007aae69bed019826ddec93f761514652a93d871e49Harald Welte 2008aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&newcounters->counters[index], counters, 2009aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(STRUCT_COUNTERS)); 2010aae69bed019826ddec93f761514652a93d871e49Harald Welte 2011aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("SET\n"); 2012aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2013aae69bed019826ddec93f761514652a93d871e49Harald Welte 2014aae69bed019826ddec93f761514652a93d871e49Harald Welte 2015e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 201679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_COMMIT(TC_HANDLE_T *handle) 2017e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2018e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Replace, then map back the counters. */ 201979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_REPLACE *repl; 202079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_COUNTERS_INFO *newcounters; 2021aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2022aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 2023841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson size_t counterlen; 2024aae69bed019826ddec93f761514652a93d871e49Harald Welte int new_number; 2025aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int new_size; 2026e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2027664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_COMMIT; 2028e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 2029841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 2030e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Don't commit if nothing changed. */ 2031e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!(*handle)->changed) 2032e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher goto finished; 2033e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2034aae69bed019826ddec93f761514652a93d871e49Harald Welte new_number = iptcc_compile_table_prep(*handle, &new_size); 2035aae69bed019826ddec93f761514652a93d871e49Harald Welte if (new_number < 0) { 2036aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 2037aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 2038aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2039aae69bed019826ddec93f761514652a93d871e49Harald Welte 2040aae69bed019826ddec93f761514652a93d871e49Harald Welte repl = malloc(sizeof(*repl) + new_size); 2041e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl) { 2042e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2043e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2044e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2045ad3b4f9973ac15981b98b8fc4d364ef1ce524212Martin Josefsson memset(repl, 0, sizeof(*repl) + new_size); 2046aae69bed019826ddec93f761514652a93d871e49Harald Welte 2047e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell#if 0 2048e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell TC_DUMP_ENTRIES(*handle); 2049e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell#endif 2050e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell 2051aae69bed019826ddec93f761514652a93d871e49Harald Welte counterlen = sizeof(STRUCT_COUNTERS_INFO) 2052aae69bed019826ddec93f761514652a93d871e49Harald Welte + sizeof(STRUCT_COUNTERS) * new_number; 2053e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2054e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the old counters we will get from kernel */ 205579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell repl->counters = malloc(sizeof(STRUCT_COUNTERS) 2056e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * (*handle)->info.num_entries); 2057e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl->counters) { 2058e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2059e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2060e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2061e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2062e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the counters we're going to put back, later. */ 2063e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters = malloc(counterlen); 2064e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!newcounters) { 2065e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2066e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2067e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2068e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2069e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2070aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(newcounters, 0, counterlen); 2071e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2072e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(repl->name, (*handle)->info.name); 2073aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries = new_number; 2074aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->size = new_size; 2075aae69bed019826ddec93f761514652a93d871e49Harald Welte 2076e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->num_counters = (*handle)->info.num_entries; 2077e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->valid_hooks = (*handle)->info.valid_hooks; 2078aae69bed019826ddec93f761514652a93d871e49Harald Welte 2079aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("num_entries=%u, size=%u, num_counters=%u\n", 2080aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries, repl->size, repl->num_counters); 2081aae69bed019826ddec93f761514652a93d871e49Harald Welte 2082aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_table(*handle, repl); 2083aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) { 2084aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ret; 2085aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl->counters); 2086aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl); 2087aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 2088aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2089aae69bed019826ddec93f761514652a93d871e49Harald Welte 2090aae69bed019826ddec93f761514652a93d871e49Harald Welte 2091aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 2092aae69bed019826ddec93f761514652a93d871e49Harald Welte { 2093aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_set_replace.blob", 2094aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 2095aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 2096aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, repl, sizeof(*repl) + repl->size); 2097aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 2098aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2099aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2100aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2101e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 210279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 2103aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(*repl) + repl->size) < 0) { 2104e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2105e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2106e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2107e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2108e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2109e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2110e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Put counters back. */ 2111e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(newcounters->name, (*handle)->info.name); 2112aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->num_counters = new_number; 2113aae69bed019826ddec93f761514652a93d871e49Harald Welte 2114aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &(*handle)->chains, list) { 2115aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 2116aae69bed019826ddec93f761514652a93d871e49Harald Welte 2117aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Builtin chains have their own counters */ 2118aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_is_builtin(c)) { 2119aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for chain-index %u: ", c->foot_index); 2120aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(c->counter_map.maptype) { 2121aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2122aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, c->foot_index); 2123aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2124aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2125aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2126aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index, 2127aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos); 2128aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2129aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2130aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2131aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index, 2132aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos, 2133aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2134aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2135aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2136aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, c->foot_index, 2137aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2138aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2139aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2140aae69bed019826ddec93f761514652a93d871e49Harald Welte } 21411cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2142aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 2143aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for index %u: ", r->index); 2144aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (r->counter_map.maptype) { 2145aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2146aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, r->index); 2147aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2148aae69bed019826ddec93f761514652a93d871e49Harald Welte 2149aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2150aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2151aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index, 2152aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos); 2153aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2154aae69bed019826ddec93f761514652a93d871e49Harald Welte 2155aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2156aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2157aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index, 2158aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos, 2159aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2160aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2161aae69bed019826ddec93f761514652a93d871e49Harald Welte 2162aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2163aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, r->index, 2164aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2165aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2166aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2167e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2168e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 216962527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell 2170aae69bed019826ddec93f761514652a93d871e49Harald Welte 217162527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell#ifdef KERNEL_64_USERSPACE_32 217262527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell { 217362527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell /* Kernel will think that pointer should be 64-bits, and get 217462527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell padding. So we accomodate here (assumption: alignment of 217562527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell `counters' is on 64-bit boundary). */ 217662527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell u_int64_t *kernptr = (u_int64_t *)&newcounters->counters; 217762527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell if ((unsigned long)&newcounters->counters % 8 != 0) { 217862527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell fprintf(stderr, 217962527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell "counters alignment incorrect! Mail rusty!\n"); 218062527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell abort(); 218162527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell } 218262527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell *kernptr = newcounters->counters; 218354c307e0ff401f40a6fe382af4ae5bff0f5b40baRusty Russell } 218462527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell#endif /* KERNEL_64_USERSPACE_32 */ 2185e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2186aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 2187aae69bed019826ddec93f761514652a93d871e49Harald Welte { 2188aae69bed019826ddec93f761514652a93d871e49Harald Welte int fd = open("/tmp/libiptc-so_set_add_counters.blob", 2189aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 2190aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 2191aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, newcounters, counterlen); 2192aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 2193aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2194aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2195aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2196aae69bed019826ddec93f761514652a93d871e49Harald Welte 219779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 219879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell newcounters, counterlen) < 0) { 2199e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2200e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2201e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2202e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2203e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2204e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2205e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2206e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2207e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2208e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2209e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher finished: 2210841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson TC_FREE(handle); 2211e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2212e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2213e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2214e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get raw socket. */ 2215e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 221679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_RAW_SOCKET() 2217e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2218e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return sockfd; 2219e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2220e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2221e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Translates errno numbers into more human-readable form than strerror. */ 2222e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 222379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_STRERROR(int err) 2224e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2225e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 2226e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct table_struct { 2227e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher void *fn; 2228e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int err; 2229e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char *message; 2230e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } table [] = 22314ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 223279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INIT, EINVAL, "Module is wrong version" }, 22334ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_INIT, ENOENT, 22344ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Table does not exist (do you need to insmod?)" }, 223579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 223679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 223779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EMLINK, 2238e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher "Can't delete chain with references left" }, 223979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 224079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 224179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 224279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 22431cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 22441cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 224579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 224679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 2247e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* EINVAL for CHECK probably means bad interface. */ 224879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CHECK_PACKET, EINVAL, 2249c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad arguments (does that interface exist?)" }, 22504ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_CHECK_PACKET, ENOSYS, 22514ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Checking will most likely never get implemented" }, 2252e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* ENOENT for DELETE probably means no matching rule */ 225379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_ENTRY, ENOENT, 2254c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad rule (does a matching rule exist in that chain?)" }, 225579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, ENOENT, 2256c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad built-in chain name" }, 225779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, EINVAL, 2258c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad policy name" }, 22594ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte 22604ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, 0, "Incompatible with this kernel" }, 22614ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 22624ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 22634ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOMEM, "Memory allocation problem" }, 22644ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOENT, "No chain/target/match by that name" }, 2265e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher }; 2266e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2267e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 2268e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((!table[i].fn || table[i].fn == iptc_fn) 2269e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && table[i].err == err) 2270e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return table[i].message; 2271e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2272e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2273e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return strerror(err); 2274e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2275