libiptc.c revision d59b9db031abee37a9aa9776662dd15370faabf4
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 12a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer * 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 20a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer * up after a ruleset change. 21aae69bed019826ddec93f761514652a93d871e49Harald Welte * 2004-Aug-18: Harald Welte <laforge@netfilter.org>: 22a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer * - further 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/) 26c9477d0dcd01af5d1ee6c95c757a8c814fb3be63Jesper Dangaard Brouer * 27c9477d0dcd01af5d1ee6c95c757a8c814fb3be63Jesper Dangaard Brouer * 2008-Jan+Jul: Jesper Dangaard Brouer <hawk@comx.dk> 28c9477d0dcd01af5d1ee6c95c757a8c814fb3be63Jesper Dangaard Brouer * - performance work: speedup chain list "name" searching. 29c9477d0dcd01af5d1ee6c95c757a8c814fb3be63Jesper Dangaard Brouer * - performance work: speedup initial ruleset parsing. 30c9477d0dcd01af5d1ee6c95c757a8c814fb3be63Jesper Dangaard Brouer * - sponsored by ComX Networks A/S (http://www.comx.dk/) 313ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte */ 3215920d160760535e51a57b3834eba45257cfa6d8Harald Welte#include <sys/types.h> 3315920d160760535e51a57b3834eba45257cfa6d8Harald Welte#include <sys/socket.h> 34d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek#include <stdbool.h> 358b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt#include <xtables.h> 367cd002826d0f329620cb738bc4dc4760ef5e084aStephane Ouellette 37aae69bed019826ddec93f761514652a93d871e49Harald Welte#include "linux_list.h" 38aae69bed019826ddec93f761514652a93d871e49Harald Welte 39aae69bed019826ddec93f761514652a93d871e49Harald Welte//#define IPTC_DEBUG2 1 40aae69bed019826ddec93f761514652a93d871e49Harald Welte 41aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 42aae69bed019826ddec93f761514652a93d871e49Harald Welte#include <fcntl.h> 43aae69bed019826ddec93f761514652a93d871e49Harald Welte#define DEBUGP(x, args...) fprintf(stderr, "%s: " x, __FUNCTION__, ## args) 44aae69bed019826ddec93f761514652a93d871e49Harald Welte#define DEBUGP_C(x, args...) fprintf(stderr, x, ## args) 45aae69bed019826ddec93f761514652a93d871e49Harald Welte#else 46aae69bed019826ddec93f761514652a93d871e49Harald Welte#define DEBUGP(x, args...) 47aae69bed019826ddec93f761514652a93d871e49Harald Welte#define DEBUGP_C(x, args...) 48aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 49aae69bed019826ddec93f761514652a93d871e49Harald Welte 5001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#ifdef DEBUG 5101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#define debug(x, args...) fprintf(stderr, x, ## args) 5201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#else 5301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#define debug(x, args...) 5401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#endif 5501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 56e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void *iptc_fn = NULL; 57e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 580b63936140032deac44072951451bdf47b54296aPatrick McHardystatic const char *hooknames[] = { 590b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_PRE_ROUTING] = "PREROUTING", 600b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_LOCAL_IN] = "INPUT", 610b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_FORWARD] = "FORWARD", 620b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_LOCAL_OUT] = "OUTPUT", 630b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_POST_ROUTING] = "POSTROUTING", 6410758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell#ifdef HOOK_DROPPING 650b63936140032deac44072951451bdf47b54296aPatrick McHardy [HOOK_DROPPING] = "DROPPING" 6610758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell#endif 67e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 68e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 69aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Convenience structures */ 70aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct ipt_error_target 71aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 72aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY_TARGET t; 73aae69bed019826ddec93f761514652a93d871e49Harald Welte char error[TABLE_MAXNAMELEN]; 74aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 75aae69bed019826ddec93f761514652a93d871e49Harald Welte 76aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct chain_head; 77aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct rule_head; 78aae69bed019826ddec93f761514652a93d871e49Harald Welte 79e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstruct counter_map 80e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 81e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher enum { 82e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_NOMAP, 83e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_NORMAL_MAP, 841cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte COUNTER_MAP_ZEROED, 851cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte COUNTER_MAP_SET 86e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } maptype; 87e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int mappos; 88e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 89e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 90aae69bed019826ddec93f761514652a93d871e49Harald Welteenum iptcc_rule_type { 91aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_STANDARD, /* standard target (ACCEPT, ...) */ 92aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_MODULE, /* extension module (SNAT, ...) */ 93aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_FALLTHROUGH, /* fallthrough rule */ 94aae69bed019826ddec93f761514652a93d871e49Harald Welte IPTCC_R_JUMP, /* jump to other chain */ 95aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 96aae69bed019826ddec93f761514652a93d871e49Harald Welte 97aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct rule_head 98e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 99aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head list; 100aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *chain; 101aae69bed019826ddec93f761514652a93d871e49Harald Welte struct counter_map counter_map; 102aae69bed019826ddec93f761514652a93d871e49Harald Welte 103aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index; /* index (needed for counter_map) */ 104aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset; /* offset in rule blob */ 105aae69bed019826ddec93f761514652a93d871e49Harald Welte 106aae69bed019826ddec93f761514652a93d871e49Harald Welte enum iptcc_rule_type type; 107aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *jump; /* jump target, if IPTCC_R_JUMP */ 108aae69bed019826ddec93f761514652a93d871e49Harald Welte 109aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int size; /* size of entry data */ 110aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY entry[0]; 111e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 112e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 113aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct chain_head 11430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 115aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head list; 11679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell char name[TABLE_MAXNAMELEN]; 117aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int hooknum; /* hook number+1 if builtin */ 118aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int references; /* how many jumps reference us */ 119aae69bed019826ddec93f761514652a93d871e49Harald Welte int verdict; /* verdict if builtin */ 120aae69bed019826ddec93f761514652a93d871e49Harald Welte 121aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS counters; /* per-chain counters */ 122aae69bed019826ddec93f761514652a93d871e49Harald Welte struct counter_map counter_map; 123aae69bed019826ddec93f761514652a93d871e49Harald Welte 124aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int num_rules; /* number of rules in list */ 125aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head rules; /* list of rules */ 126aae69bed019826ddec93f761514652a93d871e49Harald Welte 127aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index; /* index (needed for jump resolval) */ 128aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int head_offset; /* offset in rule blob */ 129aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int foot_index; /* index (needed for counter_map) */ 130aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int foot_offset; /* offset in rule blob */ 13130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell}; 13230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 13379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellSTRUCT_TC_HANDLE 134e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 135175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt int sockfd; 136aae69bed019826ddec93f761514652a93d871e49Harald Welte int changed; /* Have changes been made? */ 137aae69bed019826ddec93f761514652a93d871e49Harald Welte 138aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head chains; 139a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 140aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *chain_iterator_cur; 141aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *rule_iterator_cur; 142aae69bed019826ddec93f761514652a93d871e49Harald Welte 14348bde40e73b45ad134d32cde88b779fe509faf64Jesper Dangaard Brouer unsigned int num_chains; /* number of user defined chains */ 14448bde40e73b45ad134d32cde88b779fe509faf64Jesper Dangaard Brouer 14501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct chain_head **chain_index; /* array for fast chain list access*/ 14601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int chain_index_sz;/* size of chain index array */ 14701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 1484bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer int sorted_offsets; /* if chains are received sorted from kernel, 1494bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * then the offsets are also sorted. Says if its 1504bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * possible to bsearch offsets using chain_index. 1514bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer */ 1524bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 15379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 154aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_GET_ENTRIES *entries; 155aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 156e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1574bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouerenum bsearch_type { 1584bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer BSEARCH_NAME, /* Binary search after chain name */ 1594bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer BSEARCH_OFFSET, /* Binary search based on offset */ 1604bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer}; 1614bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 162aae69bed019826ddec93f761514652a93d871e49Harald Welte/* allocate a new chain head for the cache */ 163aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct chain_head *iptcc_alloc_chain_head(const char *name, int hooknum) 164aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 165aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = malloc(sizeof(*c)); 166aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) 167aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 168aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(c, 0, sizeof(*c)); 169aae69bed019826ddec93f761514652a93d871e49Harald Welte 170aae69bed019826ddec93f761514652a93d871e49Harald Welte strncpy(c->name, name, TABLE_MAXNAMELEN); 171aae69bed019826ddec93f761514652a93d871e49Harald Welte c->hooknum = hooknum; 172aae69bed019826ddec93f761514652a93d871e49Harald Welte INIT_LIST_HEAD(&c->rules); 173e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 174aae69bed019826ddec93f761514652a93d871e49Harald Welte return c; 175aae69bed019826ddec93f761514652a93d871e49Harald Welte} 17630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 177aae69bed019826ddec93f761514652a93d871e49Harald Welte/* allocate and initialize a new rule for the cache */ 178aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct rule_head *iptcc_alloc_rule(struct chain_head *c, unsigned int size) 179aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 180aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r = malloc(sizeof(*r)+size); 181aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!r) 182aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 183aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(r, 0, sizeof(*r)); 18430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 185aae69bed019826ddec93f761514652a93d871e49Harald Welte r->chain = c; 186aae69bed019826ddec93f761514652a93d871e49Harald Welte r->size = size; 187175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 188aae69bed019826ddec93f761514652a93d871e49Harald Welte return r; 189aae69bed019826ddec93f761514652a93d871e49Harald Welte} 190e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 191aae69bed019826ddec93f761514652a93d871e49Harald Welte/* notify us that the ruleset has been modified by the user */ 192910939897ea0cb9be2729a98c60a92e807aad5c3Jesper Dangaard Brouerstatic inline void 193fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtset_changed(struct xtc_handle *h) 194175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell{ 195175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell h->changed = 1; 196175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell} 197175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 198380ba5f3074a16fbaa8869d9594962d58b5f8608Harald Welte#ifdef IPTC_DEBUG 199fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic void do_check(struct xtc_handle *h, unsigned int line); 200849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell#define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0) 20130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#else 20230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#define CHECK(h) 20330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#endif 204e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 205aae69bed019826ddec93f761514652a93d871e49Harald Welte 206aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 207aae69bed019826ddec93f761514652a93d871e49Harald Welte * iptc blob utility functions (iptcb_*) 208aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 209aae69bed019826ddec93f761514652a93d871e49Harald Welte 210e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 211aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_get_number(const STRUCT_ENTRY *i, 21279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *seek, 213e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int *pos) 214e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 215e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (i == seek) 216e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 217e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*pos)++; 218e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 219e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 220e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 221aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int 222aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcb_get_entry_n(STRUCT_ENTRY *i, 223aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int number, 224aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int *pos, 225aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY **pe) 226aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 227aae69bed019826ddec93f761514652a93d871e49Harald Welte if (*pos == number) { 228aae69bed019826ddec93f761514652a93d871e49Harald Welte *pe = i; 229aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 230aae69bed019826ddec93f761514652a93d871e49Harald Welte } 231aae69bed019826ddec93f761514652a93d871e49Harald Welte (*pos)++; 232aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 233aae69bed019826ddec93f761514652a93d871e49Harald Welte} 234aae69bed019826ddec93f761514652a93d871e49Harald Welte 235aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline STRUCT_ENTRY * 236fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptcb_get_entry(struct xtc_handle *h, unsigned int offset) 237aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 238aae69bed019826ddec93f761514652a93d871e49Harald Welte return (STRUCT_ENTRY *)((char *)h->entries->entrytable + offset); 239aae69bed019826ddec93f761514652a93d871e49Harald Welte} 240aae69bed019826ddec93f761514652a93d871e49Harald Welte 241e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic unsigned int 242fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptcb_entry2index(struct xtc_handle *const h, const STRUCT_ENTRY *seek) 243e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 244e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int pos = 0; 245e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 246aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 247aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcb_get_number, seek, &pos) == 0) { 248a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson fprintf(stderr, "ERROR: offset %u not an entry!\n", 249aae69bed019826ddec93f761514652a93d871e49Harald Welte (unsigned int)((char *)seek - (char *)h->entries->entrytable)); 250e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 251e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 252e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return pos; 253e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 254e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 255aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline STRUCT_ENTRY * 256fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptcb_offset2entry(struct xtc_handle *h, unsigned int offset) 257e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 258aae69bed019826ddec93f761514652a93d871e49Harald Welte return (STRUCT_ENTRY *) ((void *)h->entries->entrytable+offset); 259aae69bed019826ddec93f761514652a93d871e49Harald Welte} 260aae69bed019826ddec93f761514652a93d871e49Harald Welte 261aae69bed019826ddec93f761514652a93d871e49Harald Welte 262aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline unsigned long 263fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptcb_entry2offset(struct xtc_handle *const h, const STRUCT_ENTRY *e) 264aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 265aae69bed019826ddec93f761514652a93d871e49Harald Welte return (void *)e - (void *)h->entries->entrytable; 266aae69bed019826ddec93f761514652a93d871e49Harald Welte} 267aae69bed019826ddec93f761514652a93d871e49Harald Welte 268aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline unsigned int 269fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptcb_offset2index(struct xtc_handle *const h, unsigned int offset) 270aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 271aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcb_entry2index(h, iptcb_offset2entry(h, offset)); 272aae69bed019826ddec93f761514652a93d871e49Harald Welte} 273aae69bed019826ddec93f761514652a93d871e49Harald Welte 274aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns 0 if not hook entry, else hooknumber + 1 */ 275aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline unsigned int 276fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptcb_ent_is_hook_entry(STRUCT_ENTRY *e, struct xtc_handle *h) 277aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 278aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int i; 279aae69bed019826ddec93f761514652a93d871e49Harald Welte 280aae69bed019826ddec93f761514652a93d871e49Harald Welte for (i = 0; i < NUMHOOKS; i++) { 281aae69bed019826ddec93f761514652a93d871e49Harald Welte if ((h->info.valid_hooks & (1 << i)) 282aae69bed019826ddec93f761514652a93d871e49Harald Welte && iptcb_get_entry(h, h->info.hook_entry[i]) == e) 283aae69bed019826ddec93f761514652a93d871e49Harald Welte return i+1; 284aae69bed019826ddec93f761514652a93d871e49Harald Welte } 285aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 286aae69bed019826ddec93f761514652a93d871e49Harald Welte} 287aae69bed019826ddec93f761514652a93d871e49Harald Welte 288aae69bed019826ddec93f761514652a93d871e49Harald Welte 289aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 29001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * Chain index (cache utility) functions 29101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer ********************************************************************** 29201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * The chain index is an array with pointers into the chain list, with 29301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * CHAIN_INDEX_BUCKET_LEN spacing. This facilitates the ability to 29401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * speedup chain list searching, by find a more optimal starting 29501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * points when searching the linked list. 29601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * 29701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * The starting point can be found fast by using a binary search of 29801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * the chain index. Thus, reducing the previous search complexity of 29901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * O(n) to O(log(n/k) + k) where k is CHAIN_INDEX_BUCKET_LEN. 30001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * 30101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * A nice property of the chain index, is that the "bucket" list 30201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * length is max CHAIN_INDEX_BUCKET_LEN (when just build, inserts will 30301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * change this). Oppose to hashing, where the "bucket" list length can 30401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * vary a lot. 30501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer */ 30601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#ifndef CHAIN_INDEX_BUCKET_LEN 30701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#define CHAIN_INDEX_BUCKET_LEN 40 30801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#endif 30901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 31001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Another nice property of the chain index is that inserting/creating 31101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * chains in chain list don't change the correctness of the chain 31201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * index, it only causes longer lists in the buckets. 31301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * 31401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * To mitigate the performance penalty of longer bucket lists and the 31501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * penalty of rebuilding, the chain index is rebuild only when 31601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * CHAIN_INDEX_INSERT_MAX chains has been added. 31701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer */ 31801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#ifndef CHAIN_INDEX_INSERT_MAX 31901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#define CHAIN_INDEX_INSERT_MAX 355 32001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#endif 32101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 32201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerstatic inline unsigned int iptcc_is_builtin(struct chain_head *c); 32301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 32401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Use binary search in the chain index array, to find a chain_head 32501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * pointer closest to the place of the searched name element. 32601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * 32701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * Notes that, binary search (obviously) requires that the chain list 32801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * is sorted by name. 3294bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * 3304bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * The not so obvious: The chain index array, is actually both sorted 3314bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * by name and offset, at the same time!. This is only true because, 3324bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * chain are stored sorted in the kernel (as we pushed it in sorted). 3334bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * 33401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer */ 33501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerstatic struct list_head * 3364bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer__iptcc_bsearch_chain_index(const char *name, unsigned int offset, 337fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt unsigned int *idx, struct xtc_handle *handle, 3384bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer enum bsearch_type type) 33901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 34001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int pos, end; 34101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer int res; 34201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 34301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct list_head *list_pos; 34401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_pos=&handle->chains; 34501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 34601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Check for empty array, e.g. no user defined chains */ 34701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (handle->chain_index_sz == 0) { 34801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("WARNING: handle->chain_index_sz == 0\n"); 34901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return list_pos; 35001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 35101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 35201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Init */ 35301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer end = handle->chain_index_sz; 35401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer pos = end / 2; 35501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 3564bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer debug("bsearch Find chain:%s (pos:%d end:%d) (offset:%d)\n", 3574bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer name, pos, end, offset); 35801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 35901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Loop */ 36001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer loop: 36101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (!handle->chain_index[pos]) { 36201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer fprintf(stderr, "ERROR: NULL pointer chain_index[%d]\n", pos); 36301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return &handle->chains; /* Be safe, return orig start pos */ 36401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 36501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 3664bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer debug("bsearch Index[%d] name:%s ", 3674bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer pos, handle->chain_index[pos]->name); 3684bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 3694bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* Support for different compare functions */ 3704bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer switch (type) { 3714bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer case BSEARCH_NAME: 3724bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer res = strcmp(name, handle->chain_index[pos]->name); 3734bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer break; 3744bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer case BSEARCH_OFFSET: 3754bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer debug("head_offset:[%d] foot_offset:[%d] ", 3764bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->chain_index[pos]->head_offset, 3774bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->chain_index[pos]->foot_offset); 3784bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer res = offset - handle->chain_index[pos]->head_offset; 3794bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer break; 3804bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer default: 3814bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer fprintf(stderr, "ERROR: %d not a valid bsearch type\n", 3824bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer type); 3834bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer abort(); 3844bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer break; 3854bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer } 3864bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer debug("res:%d ", res); 3874bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 3884bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 38901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_pos = &handle->chain_index[pos]->list; 390dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt *idx = pos; 39101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 39201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (res == 0) { /* Found element, by direct hit */ 39301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("[found] Direct hit pos:%d end:%d\n", pos, end); 39401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return list_pos; 39501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } else if (res < 0) { /* Too far, jump back */ 39601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer end = pos; 39701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer pos = pos / 2; 39801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 39901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Exit case: First element of array */ 40001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (end == 0) { 40101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("[found] Reached first array elem (end%d)\n",end); 40201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return list_pos; 40301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 40401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("jump back to pos:%d (end:%d)\n", pos, end); 40501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer goto loop; 40601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } else if (res > 0 ){ /* Not far enough, jump forward */ 40701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 40801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Exit case: Last element of array */ 40901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (pos == handle->chain_index_sz-1) { 41001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("[found] Last array elem (end:%d)\n", end); 41101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return list_pos; 41201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 41301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 41401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Exit case: Next index less, thus elem in this list section */ 4154bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer switch (type) { 4164bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer case BSEARCH_NAME: 4174bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer res = strcmp(name, handle->chain_index[pos+1]->name); 4184bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer break; 4194bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer case BSEARCH_OFFSET: 4204bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer res = offset - handle->chain_index[pos+1]->head_offset; 4214bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer break; 4224bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer } 4234bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 42401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (res < 0) { 42501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("[found] closest list (end:%d)\n", end); 42601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return list_pos; 42701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 42801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 42901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer pos = (pos+end)/2; 43001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("jump forward to pos:%d (end:%d)\n", pos, end); 43101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer goto loop; 43201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 43301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 43401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return list_pos; 43501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 43601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 4374bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer/* Wrapper for string chain name based bsearch */ 4384bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouerstatic struct list_head * 4394bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Broueriptcc_bsearch_chain_index(const char *name, unsigned int *idx, 440fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt struct xtc_handle *handle) 4414bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer{ 4424bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer return __iptcc_bsearch_chain_index(name, 0, idx, handle, BSEARCH_NAME); 4434bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer} 4444bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 4454bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 4464bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer/* Wrapper for offset chain based bsearch */ 4474bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouerstatic struct list_head * 4484bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Broueriptcc_bsearch_chain_offset(unsigned int offset, unsigned int *idx, 449fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt struct xtc_handle *handle) 4504bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer{ 4514bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer struct list_head *pos; 4524bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 4534bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* If chains were not received sorted from kernel, then the 4544bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * offset bsearch is not possible. 4554bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer */ 4564bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer if (!handle->sorted_offsets) 4574bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer pos = handle->chains.next; 4584bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer else 4594bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer pos = __iptcc_bsearch_chain_index(NULL, offset, idx, handle, 4604bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer BSEARCH_OFFSET); 4614bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer return pos; 4624bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer} 4634bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 4644bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 46501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#ifdef DEBUG 46601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Trivial linear search of chain index. Function used for verifying 46701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer the output of bsearch function */ 46801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerstatic struct list_head * 469fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptcc_linearly_search_chain_index(const char *name, struct xtc_handle *handle) 47001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 47101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int i=0; 47201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer int res=0; 47301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 47401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct list_head *list_pos; 47501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_pos = &handle->chains; 47601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 47701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (handle->chain_index_sz) 47801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_pos = &handle->chain_index[0]->list; 47901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 48001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Linearly walk of chain index array */ 48101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 48201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer for (i=0; i < handle->chain_index_sz; i++) { 48301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (handle->chain_index[i]) { 48401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer res = strcmp(handle->chain_index[i]->name, name); 48501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (res > 0) 48601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer break; // One step too far 48701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_pos = &handle->chain_index[i]->list; 48801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (res == 0) 48901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer break; // Direct hit 49001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 49101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 49201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 49301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return list_pos; 49401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 49501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#endif 49601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 497fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int iptcc_chain_index_alloc(struct xtc_handle *h) 49801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 49901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int list_length = CHAIN_INDEX_BUCKET_LEN; 50001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int array_elems; 50101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int array_mem; 50201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 50301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Allocate memory for the chain index array */ 50401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer array_elems = (h->num_chains / list_length) + 50501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer (h->num_chains % list_length ? 1 : 0); 50601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer array_mem = sizeof(h->chain_index) * array_elems; 50701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 50801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("Alloc Chain index, elems:%d mem:%d bytes\n", 50901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer array_elems, array_mem); 51001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 51101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer h->chain_index = malloc(array_mem); 5120eee3009e7015b82a46b2eccad91f759d75ec4dfJan Engelhardt if (h->chain_index == NULL && array_mem > 0) { 51301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer h->chain_index_sz = 0; 51401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return -ENOMEM; 51501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 51601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer memset(h->chain_index, 0, array_mem); 51701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer h->chain_index_sz = array_elems; 51801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 51901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 1; 52001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 52101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 522fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic void iptcc_chain_index_free(struct xtc_handle *h) 52301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 52401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer h->chain_index_sz = 0; 52501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer free(h->chain_index); 52601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 52701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 52801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 52901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#ifdef DEBUG 530fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic void iptcc_chain_index_dump(struct xtc_handle *h) 53101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 53201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int i = 0; 53301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 53401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Dump: contents of chain index array */ 53501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer for (i=0; i < h->chain_index_sz; i++) { 53601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (h->chain_index[i]) { 53701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer fprintf(stderr, "Chain index[%d].name: %s\n", 53801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer i, h->chain_index[i]->name); 53901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 54001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 54101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 54201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#endif 54301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 54401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Build the chain index */ 545fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int iptcc_chain_index_build(struct xtc_handle *h) 54601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 54701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int list_length = CHAIN_INDEX_BUCKET_LEN; 54801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int chains = 0; 54901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int cindex = 0; 55001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct chain_head *c; 55101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 55201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Build up the chain index array here */ 55301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("Building chain index\n"); 55401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 55501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("Number of user defined chains:%d bucket_sz:%d array_sz:%d\n", 55601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer h->num_chains, list_length, h->chain_index_sz); 55701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 55801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (h->chain_index_sz == 0) 55901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 0; 56001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 56101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_for_each_entry(c, &h->chains, list) { 56201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 56301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Issue: The index array needs to start after the 56401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * builtin chains, as they are not sorted */ 56501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (!iptcc_is_builtin(c)) { 56601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer cindex=chains / list_length; 56701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 56801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Safe guard, break out on array limit, this 56901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * is useful if chains are added and array is 57001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * rebuild, without realloc of memory. */ 57101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (cindex >= h->chain_index_sz) 57201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer break; 57301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 57401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if ((chains % list_length)== 0) { 57501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("\nIndex[%d] Chains:", cindex); 57601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer h->chain_index[cindex] = c; 57701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 57801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer chains++; 57901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 58001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("%s, ", c->name); 58101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 58201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("\n"); 58301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 58401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 1; 58501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 58601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 587fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int iptcc_chain_index_rebuild(struct xtc_handle *h) 58801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 58901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("REBUILD chain index array\n"); 59001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer iptcc_chain_index_free(h); 59101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if ((iptcc_chain_index_alloc(h)) < 0) 59201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return -ENOMEM; 59301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer iptcc_chain_index_build(h); 59401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 1; 59501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 59601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 59701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Delete chain (pointer) from index array. Removing an element from 59801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * the chain list only affects the chain index array, if the chain 59901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * index points-to/uses that list pointer. 60001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * 60101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * There are different strategies, the simple and safe is to rebuild 60201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * the chain index every time. The more advanced is to update the 60301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * array index to point to the next element, but that requires some 60401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * house keeping and boundry checks. The advanced is implemented, as 60501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * the simple approach behaves badly when all chains are deleted 60601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * because list_for_each processing will always hit the first chain 60701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * index, thus causing a rebuild for every chain. 60801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer */ 609fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int iptcc_chain_index_delete_chain(struct chain_head *c, struct xtc_handle *h) 61001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 61101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct list_head *index_ptr, *index_ptr2, *next; 61201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct chain_head *c2; 613dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt unsigned int idx, idx2; 61401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 615dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt index_ptr = iptcc_bsearch_chain_index(c->name, &idx, h); 61601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 61701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("Del chain[%s] c->list:%p index_ptr:%p\n", 61801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer c->name, &c->list, index_ptr); 61901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 62001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Save the next pointer */ 62101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer next = c->list.next; 62201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_del(&c->list); 62301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 62401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (index_ptr == &c->list) { /* Chain used as index ptr */ 62501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 62601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* See if its possible to avoid a rebuild, by shifting 62701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * to next pointer. Its possible if the next pointer 62801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * is located in the same index bucket. 62901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer */ 63001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer c2 = list_entry(next, struct chain_head, list); 631dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt index_ptr2 = iptcc_bsearch_chain_index(c2->name, &idx2, h); 632dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt if (idx != idx2) { 63301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Rebuild needed */ 63401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return iptcc_chain_index_rebuild(h); 63501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } else { 63601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Avoiding rebuild */ 63701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("Update cindex[%d] with next ptr name:[%s]\n", 638dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt idx, c2->name); 639dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt h->chain_index[idx]=c2; 64001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 0; 64101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 64201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 64301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 0; 64401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 64501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 64601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 64701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/********************************************************************** 648aae69bed019826ddec93f761514652a93d871e49Harald Welte * iptc cache utility functions (iptcc_*) 649aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 650aae69bed019826ddec93f761514652a93d871e49Harald Welte 651aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Is the given chain builtin (1) or user-defined (0) */ 652910939897ea0cb9be2729a98c60a92e807aad5c3Jesper Dangaard Brouerstatic inline unsigned int iptcc_is_builtin(struct chain_head *c) 653aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 654aae69bed019826ddec93f761514652a93d871e49Harald Welte return (c->hooknum ? 1 : 0); 655aae69bed019826ddec93f761514652a93d871e49Harald Welte} 656aae69bed019826ddec93f761514652a93d871e49Harald Welte 657aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Get a specific rule within a chain */ 658aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct rule_head *iptcc_get_rule_num(struct chain_head *c, 659aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int rulenum) 660aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 661aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 662aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int num = 0; 663aae69bed019826ddec93f761514652a93d871e49Harald Welte 664aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 665aae69bed019826ddec93f761514652a93d871e49Harald Welte num++; 666aae69bed019826ddec93f761514652a93d871e49Harald Welte if (num == rulenum) 667aae69bed019826ddec93f761514652a93d871e49Harald Welte return r; 668aae69bed019826ddec93f761514652a93d871e49Harald Welte } 669aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 670aae69bed019826ddec93f761514652a93d871e49Harald Welte} 671aae69bed019826ddec93f761514652a93d871e49Harald Welte 672a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson/* Get a specific rule within a chain backwards */ 673a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefssonstatic struct rule_head *iptcc_get_rule_num_reverse(struct chain_head *c, 674a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson unsigned int rulenum) 675a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson{ 676a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson struct rule_head *r; 677a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson unsigned int num = 0; 678a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson 679a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson list_for_each_entry_reverse(r, &c->rules, list) { 680a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson num++; 681a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson if (num == rulenum) 682a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson return r; 683a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } 684a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson return NULL; 685a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson} 686a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson 687aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns chain head if found, otherwise NULL. */ 688aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct chain_head * 689fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptcc_find_chain_by_offset(struct xtc_handle *handle, unsigned int offset) 690aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 691aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head *pos; 6924bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer struct list_head *list_start_pos; 6934bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer unsigned int i; 694aae69bed019826ddec93f761514652a93d871e49Harald Welte 695aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&handle->chains)) 696aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 697aae69bed019826ddec93f761514652a93d871e49Harald Welte 6984bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* Find a smart place to start the search */ 6994bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer list_start_pos = iptcc_bsearch_chain_offset(offset, &i, handle); 7004bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 7014bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* Note that iptcc_bsearch_chain_offset() skips builtin 7024bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * chains, but this function is only used for finding jump 7034bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * targets, and a buildin chain is not a valid jump target */ 7044bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 7054bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer debug("Offset:[%u] starting search at index:[%u]\n", offset, i); 7064bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer// list_for_each(pos, &handle->chains) { 7074bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer list_for_each(pos, list_start_pos->prev) { 708aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = list_entry(pos, struct chain_head, list); 7094bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer debug("."); 7104bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer if (offset >= c->head_offset && offset <= c->foot_offset) { 7114bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer debug("Offset search found chain:[%s]\n", c->name); 712aae69bed019826ddec93f761514652a93d871e49Harald Welte return c; 7134bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer } 714aae69bed019826ddec93f761514652a93d871e49Harald Welte } 715aae69bed019826ddec93f761514652a93d871e49Harald Welte 716aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 717aae69bed019826ddec93f761514652a93d871e49Harald Welte} 71801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 719aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns chain head if found, otherwise NULL. */ 720aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct chain_head * 721fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptcc_find_label(const char *name, struct xtc_handle *handle) 722aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 723aae69bed019826ddec93f761514652a93d871e49Harald Welte struct list_head *pos; 72401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct list_head *list_start_pos; 72501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int i=0; 72601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer int res; 727aae69bed019826ddec93f761514652a93d871e49Harald Welte 728aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&handle->chains)) 729aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 730aae69bed019826ddec93f761514652a93d871e49Harald Welte 73101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* First look at builtin chains */ 732aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each(pos, &handle->chains) { 733aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = list_entry(pos, struct chain_head, list); 73401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (!iptcc_is_builtin(c)) 73501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer break; 736aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!strcmp(c->name, name)) 737aae69bed019826ddec93f761514652a93d871e49Harald Welte return c; 738aae69bed019826ddec93f761514652a93d871e49Harald Welte } 739aae69bed019826ddec93f761514652a93d871e49Harald Welte 74001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Find a smart place to start the search via chain index */ 74101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer //list_start_pos = iptcc_linearly_search_chain_index(name, handle); 74201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_start_pos = iptcc_bsearch_chain_index(name, &i, handle); 74301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 74401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Handel if bsearch bails out early */ 74501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (list_start_pos == &handle->chains) { 74601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_start_pos = pos; 74701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 74801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#ifdef DEBUG 74901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else { 75001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Verify result of bsearch against linearly index search */ 75101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct list_head *test_pos; 75201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct chain_head *test_c, *tmp_c; 75301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer test_pos = iptcc_linearly_search_chain_index(name, handle); 75401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (list_start_pos != test_pos) { 75501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("BUG in chain_index search\n"); 75601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer test_c=list_entry(test_pos, struct chain_head,list); 75701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer tmp_c =list_entry(list_start_pos,struct chain_head,list); 75801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("Verify search found:\n"); 75901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug(" Chain:%s\n", test_c->name); 76001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("BSearch found:\n"); 76101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug(" Chain:%s\n", tmp_c->name); 76201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer exit(42); 76301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 76401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 76501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer#endif 76601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 76701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Initial/special case, no user defined chains */ 76801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (handle->num_chains == 0) 76901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return NULL; 77001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 77101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Start searching through the chain list */ 77201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_for_each(pos, list_start_pos->prev) { 77301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct chain_head *c = list_entry(pos, struct chain_head, list); 77401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer res = strcmp(c->name, name); 77501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("List search name:%s == %s res:%d\n", name, c->name, res); 77601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (res==0) 77701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return c; 77801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 77901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* We can stop earlier as we know list is sorted */ 78001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (res>0 && !iptcc_is_builtin(c)) { /* Walked too far*/ 78101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug(" Not in list, walked too far, sorted list\n"); 78201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return NULL; 78301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 78401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 78501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Stop on wrap around, if list head is reached */ 78601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (pos == &handle->chains) { 78701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("Stop, list head reached\n"); 78801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return NULL; 78901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 79001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 79101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 79201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("List search NOT found name:%s\n", name); 793aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 794aae69bed019826ddec93f761514652a93d871e49Harald Welte} 795aae69bed019826ddec93f761514652a93d871e49Harald Welte 796aae69bed019826ddec93f761514652a93d871e49Harald Welte/* called when rule is to be removed from cache */ 797aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void iptcc_delete_rule(struct rule_head *r) 798aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 799aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("deleting rule %p (offset %u)\n", r, r->offset); 800aae69bed019826ddec93f761514652a93d871e49Harald Welte /* clean up reference count of called chain */ 801aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type == IPTCC_R_JUMP 802aae69bed019826ddec93f761514652a93d871e49Harald Welte && r->jump) 803aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump->references--; 804aae69bed019826ddec93f761514652a93d871e49Harald Welte 805aae69bed019826ddec93f761514652a93d871e49Harald Welte list_del(&r->list); 806aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 807aae69bed019826ddec93f761514652a93d871e49Harald Welte} 808aae69bed019826ddec93f761514652a93d871e49Harald Welte 809aae69bed019826ddec93f761514652a93d871e49Harald Welte 810aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 811aae69bed019826ddec93f761514652a93d871e49Harald Welte * RULESET PARSER (blob -> cache) 812aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 813aae69bed019826ddec93f761514652a93d871e49Harald Welte 814aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Delete policy rule of previous chain, since cache doesn't contain 815aae69bed019826ddec93f761514652a93d871e49Harald Welte * chain policy rules. 816aae69bed019826ddec93f761514652a93d871e49Harald Welte * WARNING: This function has ugly design and relies on a lot of context, only 817aae69bed019826ddec93f761514652a93d871e49Harald Welte * to be called from specific places within the parser */ 818fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int __iptcc_p_del_policy(struct xtc_handle *h, unsigned int num) 819aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 82051651b64fffc58d4f58d005fa7dc0d9669147c57Jan Engelhardt const unsigned char *data; 82151651b64fffc58d4f58d005fa7dc0d9669147c57Jan Engelhardt 822aae69bed019826ddec93f761514652a93d871e49Harald Welte if (h->chain_iterator_cur) { 823aae69bed019826ddec93f761514652a93d871e49Harald Welte /* policy rule is last rule */ 824aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *pr = (struct rule_head *) 825aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->rules.prev; 826aae69bed019826ddec93f761514652a93d871e49Harald Welte 827aae69bed019826ddec93f761514652a93d871e49Harald Welte /* save verdict */ 82851651b64fffc58d4f58d005fa7dc0d9669147c57Jan Engelhardt data = GET_TARGET(pr->entry)->data; 82951651b64fffc58d4f58d005fa7dc0d9669147c57Jan Engelhardt h->chain_iterator_cur->verdict = *(const int *)data; 830aae69bed019826ddec93f761514652a93d871e49Harald Welte 831aae69bed019826ddec93f761514652a93d871e49Harald Welte /* save counter and counter_map information */ 832a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer h->chain_iterator_cur->counter_map.maptype = 8337c4d668c9c2ee007c82063b7fc784cbbf46b2ec4Jan Engelhardt COUNTER_MAP_ZEROED; 834aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->counter_map.mappos = num-1; 835a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters, 836aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(h->chain_iterator_cur->counters)); 837aae69bed019826ddec93f761514652a93d871e49Harald Welte 838aae69bed019826ddec93f761514652a93d871e49Harald Welte /* foot_offset points to verdict rule */ 839aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->foot_index = num; 840aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur->foot_offset = pr->offset; 841aae69bed019826ddec93f761514652a93d871e49Harald Welte 842aae69bed019826ddec93f761514652a93d871e49Harald Welte /* delete rule from cache */ 843aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(pr); 8448d1b38a064d146c77eb8fc951717663e1a713cfcMartin Josefsson h->chain_iterator_cur->num_rules--; 845aae69bed019826ddec93f761514652a93d871e49Harald Welte 846e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 847e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 848e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 849e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 850e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 851ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte/* alphabetically insert a chain into the list */ 8527cd15e367cc81c839ef2ca061d201c46ca1deb7cChristoph Paaschstatic void iptc_insert_chain(struct xtc_handle *h, struct chain_head *c) 853ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte{ 854ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte struct chain_head *tmp; 85501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct list_head *list_start_pos; 85601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int i=1; 85701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 85801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Find a smart place to start the insert search */ 85901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_start_pos = iptcc_bsearch_chain_index(c->name, &i, h); 86001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 86101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Handle the case, where chain.name is smaller than index[0] */ 86201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (i==0 && strcmp(c->name, h->chain_index[0]->name) <= 0) { 86301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer h->chain_index[0] = c; /* Update chain index head */ 86401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_start_pos = h->chains.next; 86501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("Update chain_index[0] with %s\n", c->name); 86601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 86701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 86801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Handel if bsearch bails out early */ 86901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (list_start_pos == &h->chains) { 87001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_start_pos = h->chains.next; 87101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 872ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte 8739d3ed77341361674994f584ff69a61f31a342739Olaf Rempel /* sort only user defined chains */ 8749d3ed77341361674994f584ff69a61f31a342739Olaf Rempel if (!c->hooknum) { 87501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer list_for_each_entry(tmp, list_start_pos->prev, list) { 876feca0578a5d035122b4b7cdb8d44d6cca819f35cRobert de Barth if (!tmp->hooknum && strcmp(c->name, tmp->name) <= 0) { 8779d3ed77341361674994f584ff69a61f31a342739Olaf Rempel list_add(&c->list, tmp->list.prev); 8789d3ed77341361674994f584ff69a61f31a342739Olaf Rempel return; 8799d3ed77341361674994f584ff69a61f31a342739Olaf Rempel } 88001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 88101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Stop if list head is reached */ 88201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (&tmp->list == &h->chains) { 88301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("Insert, list head reached add to tail\n"); 88401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer break; 88501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 886ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte } 887ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte } 888ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte 889ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte /* survived till end of list: add at tail */ 890ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte list_add_tail(&c->list, &h->chains); 891ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte} 892ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte 893aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Another ugly helper function split out of cache_add_entry to make it less 894aae69bed019826ddec93f761514652a93d871e49Harald Welte * spaghetti code */ 895fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic void __iptcc_p_add_chain(struct xtc_handle *h, struct chain_head *c, 896aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset, unsigned int *num) 897e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 8981336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer struct list_head *tail = h->chains.prev; 8991336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer struct chain_head *ctail; 9001336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer 901aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_del_policy(h, *num); 902e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 903aae69bed019826ddec93f761514652a93d871e49Harald Welte c->head_offset = offset; 904aae69bed019826ddec93f761514652a93d871e49Harald Welte c->index = *num; 905e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 9061336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer /* Chains from kernel are already sorted, as they are inserted 9071336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer * sorted. But there exists an issue when shifting to 1.4.0 9081336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer * from an older version, as old versions allow last created 9091336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer * chain to be unsorted. 9101336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer */ 9111336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer if (iptcc_is_builtin(c)) /* Only user defined chains are sorted*/ 9121336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer list_add_tail(&c->list, &h->chains); 9131336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer else { 9141336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer ctail = list_entry(tail, struct chain_head, list); 9154bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 916526d3e138635e33773d1ca16477052a04f53f5bdJesper Dangaard Brouer if (strcmp(c->name, ctail->name) > 0 || 917526d3e138635e33773d1ca16477052a04f53f5bdJesper Dangaard Brouer iptcc_is_builtin(ctail)) 9181336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer list_add_tail(&c->list, &h->chains);/* Already sorted*/ 9194bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer else { 9201336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer iptc_insert_chain(h, c);/* Was not sorted */ 9214bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 9224bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* Notice, if chains were not received sorted 9234bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * from kernel, then an offset bsearch is no 9244bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer * longer valid. 9254bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer */ 9264bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer h->sorted_offsets = 0; 9274bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 9284bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer debug("NOTICE: chain:[%s] was NOT sorted(ctail:%s)\n", 9294bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer c->name, ctail->name); 9304bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer } 9311336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer } 932d8cb787ab44e9d2de4fd3b04fcaa370c9918fc5dJesper Dangaard Brouer 933aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur = c; 934e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 935e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 936aae69bed019826ddec93f761514652a93d871e49Harald Welte/* main parser function: add an entry from the blob to the cache */ 937a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouerstatic int cache_add_entry(STRUCT_ENTRY *e, 938a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer struct xtc_handle *h, 939aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY **prev, 940aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int *num) 941e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 942aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int builtin; 943aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset = (char *)e - (char *)h->entries->entrytable; 944aae69bed019826ddec93f761514652a93d871e49Harald Welte 945aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("entering..."); 946aae69bed019826ddec93f761514652a93d871e49Harald Welte 947aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Last entry ("policy rule"). End it.*/ 948aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcb_entry2offset(h,e) + e->next_offset == h->entries->size) { 949aae69bed019826ddec93f761514652a93d871e49Harald Welte /* This is the ERROR node at the end of the chain */ 950aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u: end of table:\n", *num, offset); 951aae69bed019826ddec93f761514652a93d871e49Harald Welte 952aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_del_policy(h, *num); 953aae69bed019826ddec93f761514652a93d871e49Harald Welte 954aae69bed019826ddec93f761514652a93d871e49Harald Welte h->chain_iterator_cur = NULL; 955aae69bed019826ddec93f761514652a93d871e49Harald Welte goto out_inc; 956aae69bed019826ddec93f761514652a93d871e49Harald Welte } 957aae69bed019826ddec93f761514652a93d871e49Harald Welte 958aae69bed019826ddec93f761514652a93d871e49Harald Welte /* We know this is the start of a new chain if it's an ERROR 959aae69bed019826ddec93f761514652a93d871e49Harald Welte * target, or a hook entry point */ 960aae69bed019826ddec93f761514652a93d871e49Harald Welte 961aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) { 962a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer struct chain_head *c = 963aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0); 964a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset, 965aae69bed019826ddec93f761514652a93d871e49Harald Welte (char *)c->name, c); 966aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 967aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = -ENOMEM; 968aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 969aae69bed019826ddec93f761514652a93d871e49Harald Welte } 97048bde40e73b45ad134d32cde88b779fe509faf64Jesper Dangaard Brouer h->num_chains++; /* New user defined chain */ 971aae69bed019826ddec93f761514652a93d871e49Harald Welte 972aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_add_chain(h, c, offset, num); 973aae69bed019826ddec93f761514652a93d871e49Harald Welte 974aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) { 975aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = 976a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer iptcc_alloc_chain_head((char *)hooknames[builtin-1], 977aae69bed019826ddec93f761514652a93d871e49Harald Welte builtin); 978a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n", 979aae69bed019826ddec93f761514652a93d871e49Harald Welte *num, offset, c, &c->rules); 980aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 981aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = -ENOMEM; 982aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 983aae69bed019826ddec93f761514652a93d871e49Harald Welte } 984aae69bed019826ddec93f761514652a93d871e49Harald Welte 985aae69bed019826ddec93f761514652a93d871e49Harald Welte c->hooknum = builtin; 986aae69bed019826ddec93f761514652a93d871e49Harald Welte 987aae69bed019826ddec93f761514652a93d871e49Harald Welte __iptcc_p_add_chain(h, c, offset, num); 988aae69bed019826ddec93f761514652a93d871e49Harald Welte 989aae69bed019826ddec93f761514652a93d871e49Harald Welte /* FIXME: this is ugly. */ 990aae69bed019826ddec93f761514652a93d871e49Harald Welte goto new_rule; 991aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 992aae69bed019826ddec93f761514652a93d871e49Harald Welte /* has to be normal rule */ 993aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 994aae69bed019826ddec93f761514652a93d871e49Harald Weltenew_rule: 995aae69bed019826ddec93f761514652a93d871e49Harald Welte 996a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, 997aae69bed019826ddec93f761514652a93d871e49Harald Welte e->next_offset))) { 998aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 999aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 1000aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1001aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r); 1002aae69bed019826ddec93f761514652a93d871e49Harald Welte 1003aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index = *num; 1004aae69bed019826ddec93f761514652a93d871e49Harald Welte r->offset = offset; 1005aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1006aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_NORMAL_MAP; 1007aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos = r->index; 1008aae69bed019826ddec93f761514652a93d871e49Harald Welte 1009aae69bed019826ddec93f761514652a93d871e49Harald Welte /* handling of jumps, etc. */ 1010aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET)) { 1011aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 1012aae69bed019826ddec93f761514652a93d871e49Harald Welte 1013aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1014aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->target.u.target_size 1015aae69bed019826ddec93f761514652a93d871e49Harald Welte != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1016aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EINVAL; 1017aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 1018aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1019aae69bed019826ddec93f761514652a93d871e49Harald Welte 1020aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->verdict < 0) { 1021aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("standard, verdict=%d\n", t->verdict); 1022aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_STANDARD; 1023aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (t->verdict == r->offset+e->next_offset) { 1024aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("fallthrough\n"); 1025aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_FALLTHROUGH; 1026aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 1027aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("jump, target=%u\n", t->verdict); 1028aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_JUMP; 1029aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Jump target fixup has to be deferred 1030aae69bed019826ddec93f761514652a93d871e49Harald Welte * until second pass, since we migh not 1031aae69bed019826ddec93f761514652a93d871e49Harald Welte * yet have parsed the target */ 1032aae69bed019826ddec93f761514652a93d871e49Harald Welte } 103352c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson } else { 103452c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson DEBUGP_C("module, target=%s\n", GET_TARGET(e)->u.user.name); 103552c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson r->type = IPTCC_R_MODULE; 1036aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1037aae69bed019826ddec93f761514652a93d871e49Harald Welte 1038aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &h->chain_iterator_cur->rules); 10398d1b38a064d146c77eb8fc951717663e1a713cfcMartin Josefsson h->chain_iterator_cur->num_rules++; 1040aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1041aae69bed019826ddec93f761514652a93d871e49Harald Welteout_inc: 1042aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 1043aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1044e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1045e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1046aae69bed019826ddec93f761514652a93d871e49Harald Welte 1047aae69bed019826ddec93f761514652a93d871e49Harald Welte/* parse an iptables blob into it's pieces */ 1048fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int parse_table(struct xtc_handle *h) 1049e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1050aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *prev; 1051aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int num = 0; 1052aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1053aae69bed019826ddec93f761514652a93d871e49Harald Welte 10544bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* Assume that chains offsets are sorted, this verified during 10554bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer parsing of ruleset (in __iptcc_p_add_chain())*/ 10564bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer h->sorted_offsets = 1; 10574bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 1058aae69bed019826ddec93f761514652a93d871e49Harald Welte /* First pass: over ruleset blob */ 1059aae69bed019826ddec93f761514652a93d871e49Harald Welte ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 1060aae69bed019826ddec93f761514652a93d871e49Harald Welte cache_add_entry, h, &prev, &num); 1061aae69bed019826ddec93f761514652a93d871e49Harald Welte 106201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Build the chain index, used for chain list search speedup */ 106301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if ((iptcc_chain_index_alloc(h)) < 0) 106401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return -ENOMEM; 106501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer iptcc_chain_index_build(h); 106601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 1067aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Second pass: fixup parsed data from first pass */ 1068aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 1069aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1070aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 1071dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt struct chain_head *lc; 1072aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 1073aae69bed019826ddec93f761514652a93d871e49Harald Welte 1074aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type != IPTCC_R_JUMP) 1075aae69bed019826ddec93f761514652a93d871e49Harald Welte continue; 1076aae69bed019826ddec93f761514652a93d871e49Harald Welte 1077aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 1078dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt lc = iptcc_find_chain_by_offset(h, t->verdict); 1079dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt if (!lc) 1080aae69bed019826ddec93f761514652a93d871e49Harald Welte return -1; 1081dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt r->jump = lc; 1082dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt lc->references++; 1083aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1084aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1085aae69bed019826ddec93f761514652a93d871e49Harald Welte 1086aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 10870113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 10889e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 1089aae69bed019826ddec93f761514652a93d871e49Harald Welte 1090aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 1091aae69bed019826ddec93f761514652a93d871e49Harald Welte * RULESET COMPILATION (cache -> blob) 1092aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 1093aae69bed019826ddec93f761514652a93d871e49Harald Welte 1094aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Convenience structures */ 1095aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_start{ 1096aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY e; 1097aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_error_target name; 1098aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 1099aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) + \ 1100aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target))) 1101aae69bed019826ddec93f761514652a93d871e49Harald Welte 1102aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_foot { 1103aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY e; 1104aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET target; 1105aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 1106aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_FOOT_SIZE (sizeof(STRUCT_ENTRY) + \ 1107aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(STRUCT_STANDARD_TARGET))) 1108aae69bed019826ddec93f761514652a93d871e49Harald Welte 1109aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptcb_chain_error { 1110aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY entry; 1111aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_error_target target; 1112aae69bed019826ddec93f761514652a93d871e49Harald Welte}; 1113aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) + \ 1114aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target))) 1115aae69bed019826ddec93f761514652a93d871e49Harald Welte 1116aae69bed019826ddec93f761514652a93d871e49Harald Welte 1117aae69bed019826ddec93f761514652a93d871e49Harald Welte 1118aae69bed019826ddec93f761514652a93d871e49Harald Welte/* compile rule from cache into blob */ 1119fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic inline int iptcc_compile_rule (struct xtc_handle *h, STRUCT_REPLACE *repl, struct rule_head *r) 11200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 1121aae69bed019826ddec93f761514652a93d871e49Harald Welte /* handle jumps */ 1122aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->type == IPTCC_R_JUMP) { 1123aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 1124aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 1125aae69bed019826ddec93f761514652a93d871e49Harald Welte /* memset for memcmp convenience on delete/replace */ 1126aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 1127aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(t->target.u.user.name, STANDARD_TARGET); 1128aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Jumps can only happen to builtin chains, so we 1129aae69bed019826ddec93f761514652a93d871e49Harald Welte * can safely assume that they always have a header */ 1130aae69bed019826ddec93f761514652a93d871e49Harald Welte t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE; 1131aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (r->type == IPTCC_R_FALLTHROUGH) { 1132aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_STANDARD_TARGET *t; 1133aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 1134aae69bed019826ddec93f761514652a93d871e49Harald Welte t->verdict = r->offset + r->size; 1135aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1136a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 1137aae69bed019826ddec93f761514652a93d871e49Harald Welte /* copy entry from cache to blob */ 1138aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy((char *)repl->entries+r->offset, r->entry, r->size); 1139aae69bed019826ddec93f761514652a93d871e49Harald Welte 1140aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1141e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1142e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1143aae69bed019826ddec93f761514652a93d871e49Harald Welte/* compile chain from cache into blob */ 1144fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int iptcc_compile_chain(struct xtc_handle *h, STRUCT_REPLACE *repl, struct chain_head *c) 11453ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 1146aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 1147aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1148aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_start *head; 1149aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_foot *foot; 1150aae69bed019826ddec93f761514652a93d871e49Harald Welte 1151aae69bed019826ddec93f761514652a93d871e49Harald Welte /* only user-defined chains have heaer */ 1152aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 1153aae69bed019826ddec93f761514652a93d871e49Harald Welte /* put chain header in place */ 1154aae69bed019826ddec93f761514652a93d871e49Harald Welte head = (void *)repl->entries + c->head_offset; 1155aae69bed019826ddec93f761514652a93d871e49Harald Welte head->e.target_offset = sizeof(STRUCT_ENTRY); 1156aae69bed019826ddec93f761514652a93d871e49Harald Welte head->e.next_offset = IPTCB_CHAIN_START_SIZE; 1157aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(head->name.t.u.user.name, ERROR_TARGET); 1158a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer head->name.t.u.target_size = 1159aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target)); 1160aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(head->name.error, c->name); 1161aae69bed019826ddec93f761514652a93d871e49Harald Welte } else { 1162a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer repl->hook_entry[c->hooknum-1] = c->head_offset; 1163aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->underflow[c->hooknum-1] = c->foot_offset; 1164aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1165aae69bed019826ddec93f761514652a93d871e49Harald Welte 1166aae69bed019826ddec93f761514652a93d871e49Harald Welte /* iterate over rules */ 1167aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 1168aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_rule(h, repl, r); 1169aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 1170aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 1171aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1172aae69bed019826ddec93f761514652a93d871e49Harald Welte 1173aae69bed019826ddec93f761514652a93d871e49Harald Welte /* put chain footer in place */ 1174aae69bed019826ddec93f761514652a93d871e49Harald Welte foot = (void *)repl->entries + c->foot_offset; 1175aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->e.target_offset = sizeof(STRUCT_ENTRY); 1176aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE; 1177aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(foot->target.target.u.user.name, STANDARD_TARGET); 1178aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.target.u.target_size = 1179aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 1180aae69bed019826ddec93f761514652a93d871e49Harald Welte /* builtin targets have verdict, others return */ 1181aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_is_builtin(c)) 1182aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.verdict = c->verdict; 1183aae69bed019826ddec93f761514652a93d871e49Harald Welte else 1184aae69bed019826ddec93f761514652a93d871e49Harald Welte foot->target.verdict = RETURN; 1185aae69bed019826ddec93f761514652a93d871e49Harald Welte /* set policy-counters */ 1186aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS)); 1187aae69bed019826ddec93f761514652a93d871e49Harald Welte 1188aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 11893ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 11903ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 1191aae69bed019826ddec93f761514652a93d871e49Harald Welte/* calculate offset and number for every rule in the cache */ 1192fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int iptcc_compile_chain_offsets(struct xtc_handle *h, struct chain_head *c, 1193efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte unsigned int *offset, unsigned int *num) 11943ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 1195aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1196aae69bed019826ddec93f761514652a93d871e49Harald Welte 1197aae69bed019826ddec93f761514652a93d871e49Harald Welte c->head_offset = *offset; 1198aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("%s: chain_head %u, offset=%u\n", c->name, *num, *offset); 1199aae69bed019826ddec93f761514652a93d871e49Harald Welte 1200aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 1201aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Chain has header */ 1202a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer *offset += sizeof(STRUCT_ENTRY) 1203aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(struct ipt_error_target)); 1204aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 1205aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1206aae69bed019826ddec93f761514652a93d871e49Harald Welte 1207aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 1208aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("rule %u, offset=%u, index=%u\n", *num, *offset, *num); 1209aae69bed019826ddec93f761514652a93d871e49Harald Welte r->offset = *offset; 1210aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index = *num; 1211aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += r->size; 1212aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 1213aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1214aae69bed019826ddec93f761514652a93d871e49Harald Welte 1215a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num, 1216aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset, *num); 1217aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_offset = *offset; 1218aae69bed019826ddec93f761514652a93d871e49Harald Welte c->foot_index = *num; 1219aae69bed019826ddec93f761514652a93d871e49Harald Welte *offset += sizeof(STRUCT_ENTRY) 1220aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 1221aae69bed019826ddec93f761514652a93d871e49Harald Welte (*num)++; 1222aae69bed019826ddec93f761514652a93d871e49Harald Welte 1223aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 12243ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 12253ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 1226aae69bed019826ddec93f761514652a93d871e49Harald Welte/* put the pieces back together again */ 1227fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int iptcc_compile_table_prep(struct xtc_handle *h, unsigned int *size) 1228aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1229aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1230aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset = 0, num = 0; 1231aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret = 0; 12323ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 1233aae69bed019826ddec93f761514652a93d871e49Harald Welte /* First pass: calculate offset for every rule */ 1234aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 1235aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = iptcc_compile_chain_offsets(h, c, &offset, &num); 1236aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 1237aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 1238aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1239aae69bed019826ddec93f761514652a93d871e49Harald Welte 1240aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Append one error rule at end of chain */ 1241aae69bed019826ddec93f761514652a93d871e49Harald Welte num++; 1242aae69bed019826ddec93f761514652a93d871e49Harald Welte offset += sizeof(STRUCT_ENTRY) 1243aae69bed019826ddec93f761514652a93d871e49Harald Welte + ALIGN(sizeof(struct ipt_error_target)); 1244aae69bed019826ddec93f761514652a93d871e49Harald Welte 1245aae69bed019826ddec93f761514652a93d871e49Harald Welte /* ruleset size is now in offset */ 1246aae69bed019826ddec93f761514652a93d871e49Harald Welte *size = offset; 1247aae69bed019826ddec93f761514652a93d871e49Harald Welte return num; 1248aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1249aae69bed019826ddec93f761514652a93d871e49Harald Welte 1250fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int iptcc_compile_table(struct xtc_handle *h, STRUCT_REPLACE *repl) 12510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 1252aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1253aae69bed019826ddec93f761514652a93d871e49Harald Welte struct iptcb_chain_error *error; 12540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1255aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Second pass: copy from cache to offsets, fill in jumps */ 1256aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(c, &h->chains, list) { 1257aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret = iptcc_compile_chain(h, repl, c); 1258aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) 1259aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 12600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 12610113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1262aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Append error rule at end of chain */ 1263aae69bed019826ddec93f761514652a93d871e49Harald Welte error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE; 1264aae69bed019826ddec93f761514652a93d871e49Harald Welte error->entry.target_offset = sizeof(STRUCT_ENTRY); 1265aae69bed019826ddec93f761514652a93d871e49Harald Welte error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE; 1266a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer error->target.t.u.user.target_size = 1267aae69bed019826ddec93f761514652a93d871e49Harald Welte ALIGN(sizeof(struct ipt_error_target)); 1268aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET); 1269aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy((char *)&error->target.error, "ERROR"); 1270aae69bed019826ddec93f761514652a93d871e49Harald Welte 1271aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 12720113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 1273e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1274aae69bed019826ddec93f761514652a93d871e49Harald Welte/********************************************************************** 1275aae69bed019826ddec93f761514652a93d871e49Harald Welte * EXTERNAL API (operates on cache only) 1276aae69bed019826ddec93f761514652a93d871e49Harald Welte **********************************************************************/ 1277aae69bed019826ddec93f761514652a93d871e49Harald Welte 1278e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Allocate handle of given size */ 1279fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic struct xtc_handle * 12800113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltealloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 1281e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1282e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher size_t len; 1283fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt struct xtc_handle *h; 1284e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1285aae69bed019826ddec93f761514652a93d871e49Harald Welte len = sizeof(STRUCT_TC_HANDLE) + size; 1286e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1287aae69bed019826ddec93f761514652a93d871e49Harald Welte h = malloc(sizeof(STRUCT_TC_HANDLE)); 1288aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h) { 1289e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1290e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1291e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1292aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(h, 0, sizeof(*h)); 1293aae69bed019826ddec93f761514652a93d871e49Harald Welte INIT_LIST_HEAD(&h->chains); 1294e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(h->info.name, tablename); 1295aae69bed019826ddec93f761514652a93d871e49Harald Welte 12960371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size); 1297aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h->entries) 1298aae69bed019826ddec93f761514652a93d871e49Harald Welte goto out_free_handle; 1299aae69bed019826ddec93f761514652a93d871e49Harald Welte 1300aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(h->entries->name, tablename); 13010371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries->size = size; 1302e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1303e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 1304aae69bed019826ddec93f761514652a93d871e49Harald Welte 1305aae69bed019826ddec93f761514652a93d871e49Harald Welteout_free_handle: 1306aae69bed019826ddec93f761514652a93d871e49Harald Welte free(h); 1307aae69bed019826ddec93f761514652a93d871e49Harald Welte 1308aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1309e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1310e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1311aae69bed019826ddec93f761514652a93d871e49Harald Welte 1312fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstruct xtc_handle * 131379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INIT(const char *tablename) 1314e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1315fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt struct xtc_handle *h; 131679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 1317efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte unsigned int tmp; 1318e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher socklen_t s; 1319175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt int sockfd; 1320e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 132179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INIT; 1322e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1323841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson if (strlen(tablename) >= TABLE_MAXNAMELEN) { 1324841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson errno = EINVAL; 1325841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson return NULL; 1326841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 1327175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt 1328175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 1329175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt if (sockfd < 0) 1330175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt return NULL; 1331175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt 13322f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardyretry: 1333e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher s = sizeof(info); 1334841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 1335e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(info.name, tablename); 1336664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) { 1337175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt close(sockfd); 1338e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1339664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 1340e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1341aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n", 1342aae69bed019826ddec93f761514652a93d871e49Harald Welte info.valid_hooks, info.num_entries, info.size); 1343aae69bed019826ddec93f761514652a93d871e49Harald Welte 13440113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((h = alloc_handle(info.name, info.size, info.num_entries)) 1345841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson == NULL) { 1346175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt close(sockfd); 1347e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1348841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 1349e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1350e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Initialize current state */ 1351175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt h->sockfd = sockfd; 1352e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->info = info; 13530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1354aae69bed019826ddec93f761514652a93d871e49Harald Welte h->entries->size = h->info.size; 1355e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 135679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 1357e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1358175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt if (getsockopt(h->sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries, 1359aae69bed019826ddec93f761514652a93d871e49Harald Welte &tmp) < 0) 1360aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 1361aae69bed019826ddec93f761514652a93d871e49Harald Welte 1362aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 1363aae69bed019826ddec93f761514652a93d871e49Harald Welte { 1364a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer int fd = open("/tmp/libiptc-so_get_entries.blob", 1365aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 1366aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 1367aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, h->entries, tmp); 1368aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 1369aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1370e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1371aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 1372aae69bed019826ddec93f761514652a93d871e49Harald Welte 1373aae69bed019826ddec93f761514652a93d871e49Harald Welte if (parse_table(h) < 0) 1374aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 13757e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1376e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(h); 1377e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 1378aae69bed019826ddec93f761514652a93d871e49Harald Welteerror: 13791c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt TC_FREE(h); 13802f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardy /* A different process changed the ruleset size, retry */ 13812f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardy if (errno == EAGAIN) 13822f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardy goto retry; 1383aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1384e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1385e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1386841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefssonvoid 13871c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_FREE(struct xtc_handle *h) 1388841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson{ 1389aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c, *tmp; 1390aae69bed019826ddec93f761514652a93d871e49Harald Welte 1391664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_FREE; 1392175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt close(h->sockfd); 1393aae69bed019826ddec93f761514652a93d871e49Harald Welte 13941c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt list_for_each_entry_safe(c, tmp, &h->chains, list) { 1395aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *rtmp; 1396aae69bed019826ddec93f761514652a93d871e49Harald Welte 1397aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, rtmp, &c->rules, list) { 1398aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 1399aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1400aae69bed019826ddec93f761514652a93d871e49Harald Welte 1401aae69bed019826ddec93f761514652a93d871e49Harald Welte free(c); 1402aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1403aae69bed019826ddec93f761514652a93d871e49Harald Welte 14041c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_index_free(h); 1405aae69bed019826ddec93f761514652a93d871e49Harald Welte 14061c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt free(h->entries); 14071c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt free(h); 1408841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson} 1409841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 1410e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 141179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellprint_match(const STRUCT_ENTRY_MATCH *m) 1412e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1413228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell printf("Match name: `%s'\n", m->u.user.name); 1414e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1415e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1416e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1417fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int dump_entry(STRUCT_ENTRY *e, struct xtc_handle *const handle); 1418a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 1419e6869a8f59d779ff4d5a0984c86d80db7078496Marc Bouchervoid 1420fd1873110f8e57be578df17fc9d03536b10f4f73Jan EngelhardtTC_DUMP_ENTRIES(struct xtc_handle *const handle) 1421e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1422664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_DUMP_ENTRIES; 1423e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(handle); 142497fb2f1579f0794377db1dca7c5bb07fade1a0dcPatrick McHardy 1425e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell printf("libiptc v%s. %u bytes.\n", 14268b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt XTABLES_VERSION, handle->entries->size); 1427e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Table `%s'\n", handle->info.name); 1428d73af64b9d28a5b0309104232c848e8ca8ab6956Jan Engelhardt printf("Hooks: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n", 142967088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_PRE_ROUTING], 143067088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_IN], 143167088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_FORWARD], 143267088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_OUT], 143367088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_POST_ROUTING]); 1434d73af64b9d28a5b0309104232c848e8ca8ab6956Jan Engelhardt printf("Underflows: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n", 143567088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_PRE_ROUTING], 143667088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_IN], 143767088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_FORWARD], 143867088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_OUT], 143967088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_POST_ROUTING]); 1440e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1441aae69bed019826ddec93f761514652a93d871e49Harald Welte ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size, 144279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell dump_entry, handle); 14430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 1444e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1445e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Does this chain exist? */ 1446fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtint TC_IS_CHAIN(const char *chain, struct xtc_handle *const handle) 1447e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1448664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_IS_CHAIN; 1449aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_find_label(chain, handle) != NULL; 1450e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1451e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1452fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic void iptcc_chain_iterator_advance(struct xtc_handle *handle) 1453aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1454aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = handle->chain_iterator_cur; 1455aae69bed019826ddec93f761514652a93d871e49Harald Welte 1456aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->list.next == &handle->chains) 1457aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->chain_iterator_cur = NULL; 1458aae69bed019826ddec93f761514652a93d871e49Harald Welte else 1459a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer handle->chain_iterator_cur = 1460aae69bed019826ddec93f761514652a93d871e49Harald Welte list_entry(c->list.next, struct chain_head, list); 1461aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1462e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 146330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. */ 1464e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 14651c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_FIRST_CHAIN(struct xtc_handle *handle) 1466e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 14671c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct chain_head *c = list_entry(handle->chains.next, 1468aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head, list); 1469aae69bed019826ddec93f761514652a93d871e49Harald Welte 1470aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_CHAIN; 1471aae69bed019826ddec93f761514652a93d871e49Harald Welte 1472aae69bed019826ddec93f761514652a93d871e49Harald Welte 14731c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (list_empty(&handle->chains)) { 1474aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no chains\n"); 14750113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 1476aae69bed019826ddec93f761514652a93d871e49Harald Welte } 14770113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 14781c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->chain_iterator_cur = c; 14791c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_iterator_advance(handle); 148030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1481aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 1482aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 148330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 148430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 148530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. Returns NULL at end. */ 148630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellconst char * 14871c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_NEXT_CHAIN(struct xtc_handle *handle) 148830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 14891c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct chain_head *c = handle->chain_iterator_cur; 1490aae69bed019826ddec93f761514652a93d871e49Harald Welte 1491aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_CHAIN; 149230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1493aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1494aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no more chains\n"); 149530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1496aae69bed019826ddec93f761514652a93d871e49Harald Welte } 149730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 14981c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_iterator_advance(handle); 1499a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 1500aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 1501aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 150230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 150330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 150430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Get first rule in the given chain: NULL for empty chain. */ 150579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 15061c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_FIRST_RULE(const char *chain, struct xtc_handle *handle) 150730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 1508aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1509aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1510aae69bed019826ddec93f761514652a93d871e49Harald Welte 1511aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_RULE; 151230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1513aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("first rule(%s): ", chain); 1514aae69bed019826ddec93f761514652a93d871e49Harald Welte 15151c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt c = iptcc_find_label(chain, handle); 151630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!c) { 151730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell errno = ENOENT; 151830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1519e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1520e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 152130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Empty chain: single return/policy rule */ 1522aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&c->rules)) { 1523aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("no rules, returning NULL\n"); 152430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1525aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1526aae69bed019826ddec93f761514652a93d871e49Harald Welte 1527aae69bed019826ddec93f761514652a93d871e49Harald Welte r = list_entry(c->rules.next, struct rule_head, list); 15281c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->rule_iterator_cur = r; 1529aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%p\n", r); 153030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1531aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 1532e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1533e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 153430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Returns NULL when rules run out. */ 153579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 15361c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_NEXT_RULE(const STRUCT_ENTRY *prev, struct xtc_handle *handle) 153730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 1538aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1539aae69bed019826ddec93f761514652a93d871e49Harald Welte 1540664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_NEXT_RULE; 15411c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt DEBUGP("rule_iterator_cur=%p...", handle->rule_iterator_cur); 1542aae69bed019826ddec93f761514652a93d871e49Harald Welte 15431c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (handle->rule_iterator_cur == NULL) { 1544aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning NULL\n"); 154530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1546aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1547a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 1548a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer r = list_entry(handle->rule_iterator_cur->list.next, 1549aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 155030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1551aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_RULE; 1552aae69bed019826ddec93f761514652a93d871e49Harald Welte 1553a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer DEBUGP_C("next=%p, head=%p...", &r->list, 15541c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt &handle->rule_iterator_cur->chain->rules); 1555aae69bed019826ddec93f761514652a93d871e49Harald Welte 15561c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (&r->list == &handle->rule_iterator_cur->chain->rules) { 15571c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->rule_iterator_cur = NULL; 1558aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("finished, returning NULL\n"); 1559aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1560aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1561aae69bed019826ddec93f761514652a93d871e49Harald Welte 15621c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->rule_iterator_cur = r; 1563aae69bed019826ddec93f761514652a93d871e49Harald Welte 1564aae69bed019826ddec93f761514652a93d871e49Harald Welte /* NOTE: prev is without any influence ! */ 1565aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning rule %p\n", r); 1566aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 156730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 156830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1569aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 157033690a1aec0b6309ff90066ca56285b6e43013f2Jan Engelhardtstatic const char *standard_target_map(int verdict) 1571e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1572aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (verdict) { 1573aae69bed019826ddec93f761514652a93d871e49Harald Welte case RETURN: 157479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_RETURN; 1575aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1576aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_ACCEPT-1: 157779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_ACCEPT; 1578aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1579aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_DROP-1: 1580aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_DROP; 1581aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1582aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_QUEUE-1: 1583aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_QUEUE; 1584aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1585aae69bed019826ddec93f761514652a93d871e49Harald Welte default: 1586aae69bed019826ddec93f761514652a93d871e49Harald Welte fprintf(stderr, "ERROR: %d not a valid target)\n", 1587aae69bed019826ddec93f761514652a93d871e49Harald Welte verdict); 1588aae69bed019826ddec93f761514652a93d871e49Harald Welte abort(); 1589aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1590e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1591aae69bed019826ddec93f761514652a93d871e49Harald Welte /* not reached */ 1592aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1593e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1594e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1595aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 1596aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char *TC_GET_TARGET(const STRUCT_ENTRY *ce, 15971c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 1598e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1599aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 1600e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell struct rule_head *r = container_of(e, struct rule_head, entry[0]); 160151651b64fffc58d4f58d005fa7dc0d9669147c57Jan Engelhardt const unsigned char *data; 1602e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1603aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_TARGET; 16040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1605aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(r->type) { 1606aae69bed019826ddec93f761514652a93d871e49Harald Welte int spos; 1607aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_FALLTHROUGH: 1608aae69bed019826ddec93f761514652a93d871e49Harald Welte return ""; 1609aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1610aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_JUMP: 1611aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name); 1612aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->jump->name; 1613aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1614aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_STANDARD: 161551651b64fffc58d4f58d005fa7dc0d9669147c57Jan Engelhardt data = GET_TARGET(e)->data; 161651651b64fffc58d4f58d005fa7dc0d9669147c57Jan Engelhardt spos = *(const int *)data; 1617aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, spos=%d'\n", r, spos); 1618aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(spos); 1619aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1620aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_MODULE: 1621aae69bed019826ddec93f761514652a93d871e49Harald Welte return GET_TARGET(e)->u.user.name; 1622aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 16230113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 1624aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1625aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1626aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Is this a built-in chain? Actually returns hook + 1. */ 1627aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1628fd1873110f8e57be578df17fc9d03536b10f4f73Jan EngelhardtTC_BUILTIN(const char *chain, struct xtc_handle *const handle) 1629aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1630aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1631a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 1632aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_BUILTIN; 16330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1634aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, handle); 1635aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1636aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1637b0f3d2d7261be3fe256a66abcc237241fea43a02Martin Josefsson return 0; 16380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 16390113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1640aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_is_builtin(c); 16410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 16420113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1643aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Get the policy of a given built-in chain */ 1644aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char * 1645aae69bed019826ddec93f761514652a93d871e49Harald WelteTC_GET_POLICY(const char *chain, 1646aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters, 16471c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 16480113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 1649aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 16500113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1651aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_POLICY; 1652fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte 1653aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("called for chain %s\n", chain); 16540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 16551c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt c = iptcc_find_label(chain, handle); 1656aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1657aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1658aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 16590113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 16600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1661aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) 1662aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 16630113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1664aae69bed019826ddec93f761514652a93d871e49Harald Welte *counters = c->counters; 16650113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1666aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(c->verdict); 16670113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 1668e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1669e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1670aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_standard_map(struct rule_head *r, int verdict) 1671e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1672aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 167379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 1674e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 167579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1676e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 167767088e73ce7707229c56987868f112051defca5aRusty Russell if (t->target.u.target_size 16788c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1679e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1680e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1681e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1682e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset for memcmp convenience on delete/replace */ 168379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 168479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell strcpy(t->target.u.user.name, STANDARD_TARGET); 1685e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = verdict; 1686e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1687aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_STANDARD; 1688aae69bed019826ddec93f761514652a93d871e49Harald Welte 1689e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1690e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 16917e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1692e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1693fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptcc_map_target(struct xtc_handle *const handle, 1694aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r) 1695e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1696aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 16970113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 1698e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1699e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's empty (=> fall through) */ 1700aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(t->u.user.name, "") == 0) { 1701aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_FALLTHROUGH; 1702aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1703aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1704e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's a standard target name... */ 170579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 1706aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_ACCEPT - 1); 170779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 1708aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_DROP - 1); 170967088e73ce7707229c56987868f112051defca5aRusty Russell else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 1710aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_QUEUE - 1); 171179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 1712aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, RETURN); 171379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (TC_BUILTIN(t->u.user.name, handle)) { 1714e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Can't jump to builtins. */ 1715e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1716e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1717e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 1718e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's an existing chain name. */ 1719aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1720aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("trying to find chain `%s': ", t->u.user.name); 1721aae69bed019826ddec93f761514652a93d871e49Harald Welte 1722aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(t->u.user.name, handle); 1723aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c) { 1724aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("found!\n"); 1725aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_JUMP; 1726aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump = c; 1727aae69bed019826ddec93f761514652a93d871e49Harald Welte c->references++; 1728aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1729aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1730aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("not found :(\n"); 1731e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1732e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1733e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Must be a module? If not, kernel will reject... */ 17343aef54dce4f9bbe0b466478fd33a1d3131efbbb8Rusty Russell /* memset to all 0 for your memcmp convenience: don't clear version */ 1735228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell memset(t->u.user.name + strlen(t->u.user.name), 1736e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 0, 17373aef54dce4f9bbe0b466478fd33a1d3131efbbb8Rusty Russell FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name)); 1738733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell r->type = IPTCC_R_MODULE; 1739aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(handle); 1740aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1741e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1742e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 17430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 1744e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 174579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 174679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 174779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 17481c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 1749e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1750aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1751eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson struct rule_head *r; 1752eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson struct list_head *prev; 1753e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 175479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INSERT_ENTRY; 1755aae69bed019826ddec93f761514652a93d871e49Harald Welte 17561c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 1757e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1758e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1759e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1760e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1761eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson /* first rulenum index = 0 1762eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson first c->num_rules index = 1 */ 1763eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson if (rulenum > c->num_rules) { 1764e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1765e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1766e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1767e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1768631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson /* If we are inserting at the end just take advantage of the 1769631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson double linked list, insert will happen before the entry 1770631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson prev points to. */ 1771631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson if (rulenum == c->num_rules) { 1772eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson prev = &c->rules; 1773a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else if (rulenum + 1 <= c->num_rules/2) { 1774631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson r = iptcc_get_rule_num(c, rulenum + 1); 1775a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson prev = &r->list; 1776a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else { 1777a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1778631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson prev = &r->list; 1779631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson } 1780eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson 1781aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1782aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1783aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1784aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1785aae69bed019826ddec93f761514652a93d871e49Harald Welte 1786aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1787aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1788aae69bed019826ddec93f761514652a93d871e49Harald Welte 17891c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!iptcc_map_target(handle, r)) { 1790aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 17910113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1792aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1793aae69bed019826ddec93f761514652a93d871e49Harald Welte 1794eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson list_add_tail(&r->list, prev); 1795aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1796aae69bed019826ddec93f761514652a93d871e49Harald Welte 17971c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 1798e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1799aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1800e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1801e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1802e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 1803e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 180479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 180579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 180679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 18071c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 1808e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1809aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1810aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *old; 1811e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 181279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_REPLACE_ENTRY; 1813e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18141c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 1815e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1816e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1817e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1818e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18190f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson if (rulenum >= c->num_rules) { 1820e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1821e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1822e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1823e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18240f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson /* Take advantage of the double linked list if possible. */ 18250f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson if (rulenum + 1 <= c->num_rules/2) { 18260f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson old = iptcc_get_rule_num(c, rulenum + 1); 18270f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson } else { 18280f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson old = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 18290f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson } 18300f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson 1831aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1832aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1833e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1834aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1835aae69bed019826ddec93f761514652a93d871e49Harald Welte 1836aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1837aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1838e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18391c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!iptcc_map_target(handle, r)) { 1840aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 18410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1842aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1843aae69bed019826ddec93f761514652a93d871e49Harald Welte 1844aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add(&r->list, &old->list); 1845aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(old); 18460113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 18471c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 1848aae69bed019826ddec93f761514652a93d871e49Harald Welte 1849aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1850e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1851e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Append entry `fw' to chain `chain'. Equivalent to insert with 1853e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher rulenum = length of chain. */ 1854e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 185579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 185679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 18571c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 1858e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1859aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1860aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1861e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 186279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_APPEND_ENTRY; 18631c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 1864aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to find chain `%s'\n", chain); 1865e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1866e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1867e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1868e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1869aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1870aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to allocate rule for chain `%s'\n", chain); 1871aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1872aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1873aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1874aae69bed019826ddec93f761514652a93d871e49Harald Welte 1875aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1876aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1877aae69bed019826ddec93f761514652a93d871e49Harald Welte 18781c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!iptcc_map_target(handle, r)) { 187912009531e6a96a62ee398eb0ab3e9ec0b3b57701Martin Josefsson DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1880aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 18810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1882aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1883aae69bed019826ddec93f761514652a93d871e49Harald Welte 1884aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &c->rules); 1885aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1886aae69bed019826ddec93f761514652a93d871e49Harald Welte 18871c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 18880113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1889aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1890e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1891e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1892e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 189379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellmatch_different(const STRUCT_ENTRY_MATCH *a, 1894edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *a_elems, 1895edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_elems, 1896edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned char **maskptr) 1897e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 189879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY_MATCH *b; 1899edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1900e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1901e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Offset of b is the same as a. */ 190230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell b = (void *)b_elems + ((unsigned char *)a - a_elems); 1903e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1904228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (a->u.match_size != b->u.match_size) 1905e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1906e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1907228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (strcmp(a->u.user.name, b->u.user.name) != 0) 1908e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1909e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 191073ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell *maskptr += ALIGN(sizeof(*a)); 1911edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 191273ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1913edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1914edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 1; 1915edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell *maskptr += i; 1916edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 0; 1917edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell} 1918edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 1919edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russellstatic inline int 1920733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russelltarget_same(struct rule_head *a, struct rule_head *b,const unsigned char *mask) 1921edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell{ 1922edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1923733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell STRUCT_ENTRY_TARGET *ta, *tb; 1924e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1925733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (a->type != b->type) 1926733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1927733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1928733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell ta = GET_TARGET(a->entry); 1929733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell tb = GET_TARGET(b->entry); 1930733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1931733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell switch (a->type) { 1932733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_FALLTHROUGH: 1933733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 1934733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_JUMP: 1935733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return a->jump == b->jump; 1936733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_STANDARD: 1937733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return ((STRUCT_STANDARD_TARGET *)ta)->verdict 1938733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell == ((STRUCT_STANDARD_TARGET *)tb)->verdict; 1939733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_MODULE: 1940733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (ta->u.target_size != tb->u.target_size) 1941733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1942733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (strcmp(ta->u.user.name, tb->u.user.name) != 0) 1943733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1944733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1945733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell for (i = 0; i < ta->u.target_size - sizeof(*ta); i++) 1946daade4452715cbd1feea05d5231c5e38e3b0b98bRusty Russell if (((ta->data[i] ^ tb->data[i]) & mask[i]) != 0) 1947733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1948733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 1949733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell default: 1950733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell fprintf(stderr, "ERROR: bad type %i\n", a->type); 1951733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell abort(); 1952733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell } 1953e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1954e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1955733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russellstatic unsigned char * 195679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellis_same(const STRUCT_ENTRY *a, 195779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *b, 195879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask); 1959e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1960d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek 1961d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek/* find the first rule in `chain' which matches `fw' and remove it unless dry_run is set */ 1962d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanekstatic int delete_entry(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, 1963d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek unsigned char *matchmask, struct xtc_handle *handle, 1964d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek bool dry_run) 1965e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1966aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1967e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell struct rule_head *r, *i; 1968e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 196979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_ENTRY; 19701c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 1971e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1972e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1973e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1974e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1975e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell /* Create a rule_head from origfw. */ 1976e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell r = iptcc_alloc_rule(c, origfw->next_offset); 1977e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell if (!r) { 19780113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = ENOMEM; 19790113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 19800113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 19810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1982e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell memcpy(r->entry, origfw, origfw->next_offset); 1983e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell r->counter_map.maptype = COUNTER_MAP_NOMAP; 19841c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!iptcc_map_target(handle, r)) { 1985e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1986e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell free(r); 1987e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell return 0; 198804a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer } else { 198904a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer /* iptcc_map_target increment target chain references 199004a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer * since this is a fake rule only used for matching 1991a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer * the chain references count is decremented again. 199204a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer */ 199304a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer if (r->type == IPTCC_R_JUMP 199404a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer && r->jump) 199504a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer r->jump->references--; 1996e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell } 1997fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 1998e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell list_for_each_entry(i, &c->rules, list) { 1999733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell unsigned char *mask; 2000733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 2001733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell mask = is_same(r->entry, i->entry, matchmask); 2002733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (!mask) 2003733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell continue; 2004733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 2005733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (!target_same(r, i, mask)) 2006733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell continue; 2007733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 2008d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek /* if we are just doing a dry run, we simply skip the rest */ 2009d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek if (dry_run) 2010d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek return 1; 2011d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek 2012733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell /* If we are about to delete the rule that is the 2013733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell * current iterator, move rule iterator back. next 2014733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell * pointer will then point to real next node */ 20151c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (i == handle->rule_iterator_cur) { 2016a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer handle->rule_iterator_cur = 20171c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt list_entry(handle->rule_iterator_cur->list.prev, 2018733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell struct rule_head, list); 2019733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell } 2020fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 2021733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell c->num_rules--; 2022733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell iptcc_delete_rule(i); 20232a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson 20241c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2025733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell free(r); 2026733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 2027e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2028e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2029e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell free(r); 2030e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2031e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 20327e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell} 2033aae69bed019826ddec93f761514652a93d871e49Harald Welte 2034d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek/* check whether a specified rule is present */ 2035d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanekint TC_CHECK_ENTRY(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, 2036d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek unsigned char *matchmask, struct xtc_handle *handle) 2037d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek{ 2038d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek /* do a dry-run delete to find out whether a matching rule exists */ 2039d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek return delete_entry(chain, origfw, matchmask, handle, true); 2040d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek} 2041d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek 2042d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek/* Delete the first rule in `chain' which matches `fw'. */ 2043d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanekint TC_DELETE_ENTRY(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, 2044d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek unsigned char *matchmask, struct xtc_handle *handle) 2045d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek{ 2046d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek return delete_entry(chain, origfw, matchmask, handle, false); 2047d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek} 2048e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2049e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Delete the rule in position `rulenum' in `chain'. */ 2050e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 205179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 205279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 20531c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 2054e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2055aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2056aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 2057e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 205879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_NUM_ENTRY; 2059aae69bed019826ddec93f761514652a93d871e49Harald Welte 20601c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2061e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2062e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2063e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2064e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2065a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson if (rulenum >= c->num_rules) { 2066631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson errno = E2BIG; 2067631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson return 0; 2068631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson } 2069631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson 2070631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson /* Take advantage of the double linked list if possible. */ 2071a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson if (rulenum + 1 <= c->num_rules/2) { 2072a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num(c, rulenum + 1); 2073a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else { 2074a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 2075e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2076e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2077aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the rule that is the current 2078aae69bed019826ddec93f761514652a93d871e49Harald Welte * iterator, move rule iterator back. next pointer will then 2079aae69bed019826ddec93f761514652a93d871e49Harald Welte * point to real next node */ 20801c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (r == handle->rule_iterator_cur) { 2081a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer handle->rule_iterator_cur = 20821c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt list_entry(handle->rule_iterator_cur->list.prev, 2083aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 20840113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 2085e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2086aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules--; 2087aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 2088aae69bed019826ddec93f761514652a93d871e49Harald Welte 20891c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 20902a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson 2091aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 2092e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2093e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2094e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Flushes the entries in the given chain (ie. empties chain). */ 2095e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 20961c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2097e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2098aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2099aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *tmp; 2100e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 21010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte iptc_fn = TC_FLUSH_ENTRIES; 21021c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2103e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2104e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2105e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2106e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2107aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, tmp, &c->rules, list) { 2108aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 2109aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2110aae69bed019826ddec93f761514652a93d871e49Harald Welte 2111aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules = 0; 2112aae69bed019826ddec93f761514652a93d871e49Harald Welte 21131c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2114aae69bed019826ddec93f761514652a93d871e49Harald Welte 2115aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 2116e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2117e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2118e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Zeroes the counters in a chain. */ 2119e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 21201c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2121e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2122aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2123aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 21247e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 2125664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_ZERO_ENTRIES; 21261c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2127e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2128e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2129e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2130e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2131e5bd1d779fab33353c1dc2d2fa49db639dcebd38Andy Gay if (c->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2132e5bd1d779fab33353c1dc2d2fa49db639dcebd38Andy Gay c->counter_map.maptype = COUNTER_MAP_ZEROED; 2133e5bd1d779fab33353c1dc2d2fa49db639dcebd38Andy Gay 2134aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 2135aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2136aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 2137e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2138aae69bed019826ddec93f761514652a93d871e49Harald Welte 21391c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2140e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2141e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2142e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2143e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 21441cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteSTRUCT_COUNTERS * 21451cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_READ_COUNTER(const IPT_CHAINLABEL chain, 21461cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 21471c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 21481cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 2149aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2150aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 21511cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21521cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_READ_COUNTER; 21531cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 21541cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21551c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 21561cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 21571cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return NULL; 21581cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 21591cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2160aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 21610113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 21620113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 21630113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 21640113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2165aae69bed019826ddec93f761514652a93d871e49Harald Welte return &r->entry[0].counters; 21661cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 21671cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21681cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 21691cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 21701cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 21711c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 21721cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 2173aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2174aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 2175a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 21761cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_ZERO_COUNTER; 21771c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt CHECK(handle); 21781cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21791c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 21801cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 21811cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 21821cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 21831cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2184aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 21850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 21860113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 21870113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 21880113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2189aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2190aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 21911cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21921c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 21931cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21941cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 21951cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 21961cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2197a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouerint 21981cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_SET_COUNTER(const IPT_CHAINLABEL chain, 21991cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 22001cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 22011c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 22021cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 2203aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2204aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 22051cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 22061cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 22071cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_SET_COUNTER; 22081c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt CHECK(handle); 22091cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 22101c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 22111cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 22121cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 22131cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 22140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2215aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 22160113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 22170113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 22180113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 22190113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2220aae69bed019826ddec93f761514652a93d871e49Harald Welte e = r->entry; 2221aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 22220113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 22230113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 22241cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 22251c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 22261cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 22271cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 22281cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 22291cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2230e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Creates a new chain. */ 2231e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* To create a chain, create two rules: error node and unconditional 2232e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * return. */ 2233e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 22341c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_CREATE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2235e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2236aae69bed019826ddec93f761514652a93d871e49Harald Welte static struct chain_head *c; 22371f23d3c2544f4329b31804392abc4eff434ba308Patrick McHardy int capacity; 22381f23d3c2544f4329b31804392abc4eff434ba308Patrick McHardy int exceeded; 2239e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 224079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_CREATE_CHAIN; 2241e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2242e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* find_label doesn't cover built-in targets: DROP, ACCEPT, 2243e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher QUEUE, RETURN. */ 22441c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (iptcc_find_label(chain, handle) 224579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_DROP) == 0 224679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_ACCEPT) == 0 224767088e73ce7707229c56987868f112051defca5aRusty Russell || strcmp(chain, LABEL_QUEUE) == 0 224879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_RETURN) == 0) { 2249aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain `%s' already exists\n", chain); 2250e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 2251e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2252e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2253e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 225479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 2255aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain name `%s' too long\n", chain); 2256e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 2257e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2258e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2259e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2260aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_alloc_chain_head(chain, 0); 2261aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 2262aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Cannot allocate memory for chain `%s'\n", chain); 2263aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 2264aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 2265e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2266aae69bed019826ddec93f761514652a93d871e49Harald Welte } 22671c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->num_chains++; /* New user defined chain */ 2268e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2269aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Creating chain `%s'\n", chain); 22701c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptc_insert_chain(handle, c); /* Insert sorted */ 2271e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 227201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Inserting chains don't change the correctness of the chain 227301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * index (except if its smaller than index[0], but that 227401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * handled by iptc_insert_chain). It only causes longer lists 227501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * in the buckets. Thus, only rebuild chain index when the 227601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * capacity is exceed with CHAIN_INDEX_INSERT_MAX chains. 227701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer */ 22781c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt capacity = handle->chain_index_sz * CHAIN_INDEX_BUCKET_LEN; 22791c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt exceeded = handle->num_chains - capacity; 228001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (exceeded > CHAIN_INDEX_INSERT_MAX) { 228101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("Capacity(%d) exceeded(%d) rebuild (chains:%d)\n", 22821c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt capacity, exceeded, handle->num_chains); 22831c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_index_rebuild(handle); 228401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 228501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 22861c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2287e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2288aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 2289e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2290e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2291e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get the number of references to this chain. */ 2292e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 229379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 22941c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 2295e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2296aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2297e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2298664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_GET_REFERENCES; 22991c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2300e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2301e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2302e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2303e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2304aae69bed019826ddec93f761514652a93d871e49Harald Welte *ref = c->references; 2305aae69bed019826ddec93f761514652a93d871e49Harald Welte 2306e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2307e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2308e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2309e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Deletes a chain. */ 2310e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 23111c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_DELETE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2312e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2313e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int references; 2314aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 23157e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 231679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_CHAIN; 2317e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 23181c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2319aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 2320aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 2321aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 2322aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2323aae69bed019826ddec93f761514652a93d871e49Harald Welte 23241c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (TC_BUILTIN(chain, handle)) { 2325aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot remove builtin chain `%s'\n", chain); 2326e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 2327e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2328e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2329e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2330aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!TC_GET_REFERENCES(&references, chain, handle)) { 2331aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot get references on chain `%s'\n", chain); 2332e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2333e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2334e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2335aae69bed019826ddec93f761514652a93d871e49Harald Welte if (references > 0) { 2336aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' still has references\n", chain); 2337aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EMLINK; 2338e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2339e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2340e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2341aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->num_rules) { 2342aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' is not empty\n", chain); 2343e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOTEMPTY; 2344e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2345e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2346e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2347aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the chain that is the current 234848bde40e73b45ad134d32cde88b779fe509faf64Jesper Dangaard Brouer * iterator, move chain iterator forward. */ 23491c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (c == handle->chain_iterator_cur) 23501c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_iterator_advance(handle); 2351aae69bed019826ddec93f761514652a93d871e49Harald Welte 23521c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->num_chains--; /* One user defined chain deleted */ 235348bde40e73b45ad134d32cde88b779fe509faf64Jesper Dangaard Brouer 235401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer //list_del(&c->list); /* Done in iptcc_chain_index_delete_chain() */ 23551c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_index_delete_chain(c, handle); 235601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer free(c); 235701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 2358aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' deleted\n", chain); 23590113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 23601c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2361aae69bed019826ddec93f761514652a93d871e49Harald Welte 2362aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 2363e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2364e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2365e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Renames a chain. */ 236679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 236779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL newname, 23681c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 2369e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2370aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 237179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_RENAME_CHAIN; 2372e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 23731de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte /* find_label doesn't cover built-in targets: DROP, ACCEPT, 23741de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte QUEUE, RETURN. */ 23751c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (iptcc_find_label(newname, handle) 237679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_DROP) == 0 237779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_ACCEPT) == 0 23781de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte || strcmp(newname, LABEL_QUEUE) == 0 237979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_RETURN) == 0) { 2380e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 2381e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2382e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2383e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 23841c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(oldname, handle)) 23851c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt || TC_BUILTIN(oldname, handle)) { 2386e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2387e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2388e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2389e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 239079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 2391e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 2392e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2393e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2394e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 239564ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer /* This only unlinks "c" from the list, thus no free(c) */ 239664ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer iptcc_chain_index_delete_chain(c, handle); 239764ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer 239864ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer /* Change the name of the chain */ 2399aae69bed019826ddec93f761514652a93d871e49Harald Welte strncpy(c->name, newname, sizeof(IPT_CHAINLABEL)); 240064ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer 240164ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer /* Insert sorted into to list again */ 240264ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer iptc_insert_chain(handle, c); 240364ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer 24041c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 24050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2406e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2407e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2408e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2409e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Sets the policy on a built-in chain. */ 2410e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 241179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_SET_POLICY(const IPT_CHAINLABEL chain, 241279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL policy, 24131cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 24141c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 2415e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2416aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2417e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 241879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_SET_POLICY; 2419aae69bed019826ddec93f761514652a93d871e49Harald Welte 24201c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2421aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 2422c8264991454b5e77279830736f80ea3153b6f814Marc Boucher errno = ENOENT; 2423e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2424aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2425e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2426aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 2427aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain); 2428aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 24299e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte return 0; 24309e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte } 24319e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 243279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(policy, LABEL_ACCEPT) == 0) 2433aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_ACCEPT - 1; 243479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(policy, LABEL_DROP) == 0) 2435aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_DROP - 1; 2436e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else { 2437e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 2438e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2439e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 24401cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 24411cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (counters) { 24421cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte /* set byte and packet counters */ 2443aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS)); 2444aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_SET; 24451cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } else { 2446aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_NOMAP; 24471cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 24481cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 24491c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2450e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2451e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2452e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2453e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2454e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Without this, on gcc 2.7.2.3, we get: 245579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell libiptc.c: In function `TC_COMMIT': 2456e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher libiptc.c:833: fixed or forbidden register was spilled. 2457e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher This may be due to a compiler bug or to impossible asm 2458e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher statements or clauses. 2459e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher*/ 2460e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 246179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellsubtract_counters(STRUCT_COUNTERS *answer, 246279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *a, 246379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *b) 2464e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2465e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->pcnt = a->pcnt - b->pcnt; 2466e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->bcnt = a->bcnt - b->bcnt; 2467e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2468e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2469aae69bed019826ddec93f761514652a93d871e49Harald Welte 2470dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardtstatic void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, unsigned int idx) 2471aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 2472dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt newcounters->counters[idx] = ((STRUCT_COUNTERS) { 0, 0}); 2473aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NOMAP => zero\n"); 2474aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2475aae69bed019826ddec93f761514652a93d871e49Harald Welte 2476aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters, 2477dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt STRUCT_REPLACE *repl, unsigned int idx, 2478aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int mappos) 2479aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 2480aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 2481aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 2482aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 2483aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: X + Y + Z. 2484aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in X + Y 2485aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in replacement read. 2486aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 2487dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt newcounters->counters[idx] = repl->counters[mappos]; 2488aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos); 2489aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2490aae69bed019826ddec93f761514652a93d871e49Harald Welte 2491aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters, 2492dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt STRUCT_REPLACE *repl, unsigned int idx, 2493dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt unsigned int mappos, STRUCT_COUNTERS *counters) 2494aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 2495aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 2496aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 2497aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 2498aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: Y + Z. 2499aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in Y. 2500aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in (replacement read - original read). 2501aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 2502dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt subtract_counters(&newcounters->counters[idx], 2503aae69bed019826ddec93f761514652a93d871e49Harald Welte &repl->counters[mappos], 2504aae69bed019826ddec93f761514652a93d871e49Harald Welte counters); 2505aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("ZEROED => mappos %u\n", mappos); 2506aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2507aae69bed019826ddec93f761514652a93d871e49Harald Welte 2508aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_set(STRUCT_COUNTERS_INFO *newcounters, 2509dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt unsigned int idx, STRUCT_COUNTERS *counters) 2510aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 2511aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Want to set counter (iptables-restore) */ 2512aae69bed019826ddec93f761514652a93d871e49Harald Welte 2513dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt memcpy(&newcounters->counters[idx], counters, 2514aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(STRUCT_COUNTERS)); 2515aae69bed019826ddec93f761514652a93d871e49Harald Welte 2516aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("SET\n"); 2517aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2518aae69bed019826ddec93f761514652a93d871e49Harald Welte 2519aae69bed019826ddec93f761514652a93d871e49Harald Welte 2520e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 25211c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_COMMIT(struct xtc_handle *handle) 2522e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2523e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Replace, then map back the counters. */ 252479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_REPLACE *repl; 252579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_COUNTERS_INFO *newcounters; 2526aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2527aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 2528841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson size_t counterlen; 2529aae69bed019826ddec93f761514652a93d871e49Harald Welte int new_number; 2530aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int new_size; 2531e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2532664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_COMMIT; 2533e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 2534841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 2535e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Don't commit if nothing changed. */ 25361c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!handle->changed) 2537e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher goto finished; 2538e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 25391c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt new_number = iptcc_compile_table_prep(handle, &new_size); 2540aae69bed019826ddec93f761514652a93d871e49Harald Welte if (new_number < 0) { 2541aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 2542d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_zero; 2543aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2544aae69bed019826ddec93f761514652a93d871e49Harald Welte 2545aae69bed019826ddec93f761514652a93d871e49Harald Welte repl = malloc(sizeof(*repl) + new_size); 2546e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl) { 2547e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2548d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_zero; 2549e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2550ad3b4f9973ac15981b98b8fc4d364ef1ce524212Martin Josefsson memset(repl, 0, sizeof(*repl) + new_size); 2551aae69bed019826ddec93f761514652a93d871e49Harald Welte 2552e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell#if 0 2553e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell TC_DUMP_ENTRIES(*handle); 2554e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell#endif 2555e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell 2556aae69bed019826ddec93f761514652a93d871e49Harald Welte counterlen = sizeof(STRUCT_COUNTERS_INFO) 2557aae69bed019826ddec93f761514652a93d871e49Harald Welte + sizeof(STRUCT_COUNTERS) * new_number; 2558e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2559e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the old counters we will get from kernel */ 256079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell repl->counters = malloc(sizeof(STRUCT_COUNTERS) 25611c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt * handle->info.num_entries); 2562e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl->counters) { 2563e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2564d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_repl; 2565e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2566e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the counters we're going to put back, later. */ 2567e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters = malloc(counterlen); 2568e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!newcounters) { 2569e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2570d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_repl_counters; 2571e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2572aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(newcounters, 0, counterlen); 2573e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 25741c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt strcpy(repl->name, handle->info.name); 2575aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries = new_number; 2576aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->size = new_size; 2577aae69bed019826ddec93f761514652a93d871e49Harald Welte 25781c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt repl->num_counters = handle->info.num_entries; 25791c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt repl->valid_hooks = handle->info.valid_hooks; 2580aae69bed019826ddec93f761514652a93d871e49Harald Welte 2581aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("num_entries=%u, size=%u, num_counters=%u\n", 2582aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries, repl->size, repl->num_counters); 2583aae69bed019826ddec93f761514652a93d871e49Harald Welte 25841c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt ret = iptcc_compile_table(handle, repl); 2585aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) { 2586aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ret; 2587d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_newcounters; 2588aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2589aae69bed019826ddec93f761514652a93d871e49Harald Welte 2590aae69bed019826ddec93f761514652a93d871e49Harald Welte 2591aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 2592aae69bed019826ddec93f761514652a93d871e49Harald Welte { 2593a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer int fd = open("/tmp/libiptc-so_set_replace.blob", 2594aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 2595aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 2596aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, repl, sizeof(*repl) + repl->size); 2597aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 2598aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2599aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2600aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2601e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2602175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 2603d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte sizeof(*repl) + repl->size); 2604e0865ad29d53b0d3d34b5cc8b5e023eb593172a8Patrick McHardy if (ret < 0) 2605d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_newcounters; 2606e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2607e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Put counters back. */ 26081c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt strcpy(newcounters->name, handle->info.name); 2609aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->num_counters = new_number; 2610aae69bed019826ddec93f761514652a93d871e49Harald Welte 26111c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt list_for_each_entry(c, &handle->chains, list) { 2612aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 2613aae69bed019826ddec93f761514652a93d871e49Harald Welte 2614aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Builtin chains have their own counters */ 2615aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_is_builtin(c)) { 2616aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for chain-index %u: ", c->foot_index); 2617aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(c->counter_map.maptype) { 2618aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2619aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, c->foot_index); 2620aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2621aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2622aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2623a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer c->foot_index, 2624aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos); 2625aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2626aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2627aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2628a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer c->foot_index, 2629aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos, 2630aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2631aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2632aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2633aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, c->foot_index, 2634aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2635aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2636aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2637aae69bed019826ddec93f761514652a93d871e49Harald Welte } 26381cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2639aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 2640aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for index %u: ", r->index); 2641aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (r->counter_map.maptype) { 2642aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2643aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, r->index); 2644aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2645aae69bed019826ddec93f761514652a93d871e49Harald Welte 2646aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2647aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2648a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer r->index, 2649aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos); 2650aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2651aae69bed019826ddec93f761514652a93d871e49Harald Welte 2652aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2653aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2654aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index, 2655aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos, 2656aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2657aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2658aae69bed019826ddec93f761514652a93d871e49Harald Welte 2659aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2660aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, r->index, 2661aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2662aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2663aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2664e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2665e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 266662527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell 2667aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 2668aae69bed019826ddec93f761514652a93d871e49Harald Welte { 2669a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer int fd = open("/tmp/libiptc-so_set_add_counters.blob", 2670aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 2671aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 2672aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, newcounters, counterlen); 2673aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 2674aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2675aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2676aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2677aae69bed019826ddec93f761514652a93d871e49Harald Welte 2678175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 2679d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte newcounters, counterlen); 2680e0865ad29d53b0d3d34b5cc8b5e023eb593172a8Patrick McHardy if (ret < 0) 2681d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_newcounters; 2682e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2683e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2684e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2685e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2686e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2687d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Weltefinished: 2688e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2689d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte 2690d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_free_newcounters: 2691d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte free(newcounters); 2692d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_free_repl_counters: 2693d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte free(repl->counters); 2694d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_free_repl: 2695d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte free(repl); 2696d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_zero: 2697d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte return 0; 2698e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2699e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2700e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Translates errno numbers into more human-readable form than strerror. */ 2701e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 270279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_STRERROR(int err) 2703e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2704e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 2705e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct table_struct { 2706e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher void *fn; 2707e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int err; 2708e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char *message; 2709e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } table [] = 27104ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 271179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INIT, EINVAL, "Module is wrong version" }, 2712a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer { TC_INIT, ENOENT, 27134ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Table does not exist (do you need to insmod?)" }, 271479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 271579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 271679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EMLINK, 2717e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher "Can't delete chain with references left" }, 271879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 271979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 272079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 272179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 27221cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 27231cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 272479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 272579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 2726e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* ENOENT for DELETE probably means no matching rule */ 272779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_ENTRY, ENOENT, 2728c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad rule (does a matching rule exist in that chain?)" }, 272979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, ENOENT, 2730c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad built-in chain name" }, 273179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, EINVAL, 2732c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad policy name" }, 27334ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte 27344ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, 0, "Incompatible with this kernel" }, 27354ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 27364ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 27374ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOMEM, "Memory allocation problem" }, 27384ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOENT, "No chain/target/match by that name" }, 2739e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher }; 2740e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2741e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 2742e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((!table[i].fn || table[i].fn == iptc_fn) 2743e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && table[i].err == err) 2744e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return table[i].message; 2745e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2746e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2747e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return strerror(err); 2748e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2749