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{ 6117d91a2accc92d13bb32bf881831e9c9a8b4d7734Jan Engelhardt struct list_head *index_ptr, *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); 6317d91a2accc92d13bb32bf881831e9c9a8b4d7734Jan Engelhardt 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{ 1282fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt struct xtc_handle *h; 1283e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1284aae69bed019826ddec93f761514652a93d871e49Harald Welte h = malloc(sizeof(STRUCT_TC_HANDLE)); 1285aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h) { 1286e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1287e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1288e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1289aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(h, 0, sizeof(*h)); 1290aae69bed019826ddec93f761514652a93d871e49Harald Welte INIT_LIST_HEAD(&h->chains); 1291e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(h->info.name, tablename); 1292aae69bed019826ddec93f761514652a93d871e49Harald Welte 12930371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size); 1294aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h->entries) 1295aae69bed019826ddec93f761514652a93d871e49Harald Welte goto out_free_handle; 1296aae69bed019826ddec93f761514652a93d871e49Harald Welte 1297aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(h->entries->name, tablename); 12980371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte h->entries->size = size; 1299e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1300e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 1301aae69bed019826ddec93f761514652a93d871e49Harald Welte 1302aae69bed019826ddec93f761514652a93d871e49Harald Welteout_free_handle: 1303aae69bed019826ddec93f761514652a93d871e49Harald Welte free(h); 1304aae69bed019826ddec93f761514652a93d871e49Harald Welte 1305aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1306e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1307e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1308aae69bed019826ddec93f761514652a93d871e49Harald Welte 1309fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstruct xtc_handle * 131079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INIT(const char *tablename) 1311e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1312fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt struct xtc_handle *h; 131379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 1314efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte unsigned int tmp; 1315e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher socklen_t s; 1316175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt int sockfd; 1317e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 131879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INIT; 1319e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1320841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson if (strlen(tablename) >= TABLE_MAXNAMELEN) { 1321841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson errno = EINVAL; 1322841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson return NULL; 1323841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 1324175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt 1325175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 1326175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt if (sockfd < 0) 1327175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt return NULL; 1328175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt 13292f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardyretry: 1330e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher s = sizeof(info); 1331841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 1332e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(info.name, tablename); 1333664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) { 1334175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt close(sockfd); 1335e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1336664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 1337e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1338aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n", 1339aae69bed019826ddec93f761514652a93d871e49Harald Welte info.valid_hooks, info.num_entries, info.size); 1340aae69bed019826ddec93f761514652a93d871e49Harald Welte 13410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((h = alloc_handle(info.name, info.size, info.num_entries)) 1342841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson == NULL) { 1343175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt close(sockfd); 1344e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1345841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 1346e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1347e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Initialize current state */ 1348175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt h->sockfd = sockfd; 1349e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->info = info; 13500113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1351aae69bed019826ddec93f761514652a93d871e49Harald Welte h->entries->size = h->info.size; 1352e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 135379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 1354e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1355175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt if (getsockopt(h->sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries, 1356aae69bed019826ddec93f761514652a93d871e49Harald Welte &tmp) < 0) 1357aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 1358aae69bed019826ddec93f761514652a93d871e49Harald Welte 1359aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 1360aae69bed019826ddec93f761514652a93d871e49Harald Welte { 1361a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer int fd = open("/tmp/libiptc-so_get_entries.blob", 1362aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 1363aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 1364aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, h->entries, tmp); 1365aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 1366aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1367e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1368aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 1369aae69bed019826ddec93f761514652a93d871e49Harald Welte 1370aae69bed019826ddec93f761514652a93d871e49Harald Welte if (parse_table(h) < 0) 1371aae69bed019826ddec93f761514652a93d871e49Harald Welte goto error; 13727e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1373e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(h); 1374e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 1375aae69bed019826ddec93f761514652a93d871e49Harald Welteerror: 13761c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt TC_FREE(h); 13772f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardy /* A different process changed the ruleset size, retry */ 13782f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardy if (errno == EAGAIN) 13792f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardy goto retry; 1380aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1381e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1382e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1383841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefssonvoid 13841c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_FREE(struct xtc_handle *h) 1385841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson{ 1386aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c, *tmp; 1387aae69bed019826ddec93f761514652a93d871e49Harald Welte 1388664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_FREE; 1389175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt close(h->sockfd); 1390aae69bed019826ddec93f761514652a93d871e49Harald Welte 13911c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt list_for_each_entry_safe(c, tmp, &h->chains, list) { 1392aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *rtmp; 1393aae69bed019826ddec93f761514652a93d871e49Harald Welte 1394aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, rtmp, &c->rules, list) { 1395aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 1396aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1397aae69bed019826ddec93f761514652a93d871e49Harald Welte 1398aae69bed019826ddec93f761514652a93d871e49Harald Welte free(c); 1399aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1400aae69bed019826ddec93f761514652a93d871e49Harald Welte 14011c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_index_free(h); 1402aae69bed019826ddec93f761514652a93d871e49Harald Welte 14031c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt free(h->entries); 14041c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt free(h); 1405841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson} 1406841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 1407e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 140879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellprint_match(const STRUCT_ENTRY_MATCH *m) 1409e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1410228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell printf("Match name: `%s'\n", m->u.user.name); 1411e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1412e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1413e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1414fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic int dump_entry(STRUCT_ENTRY *e, struct xtc_handle *const handle); 1415a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 1416e6869a8f59d779ff4d5a0984c86d80db7078496Marc Bouchervoid 1417fd1873110f8e57be578df17fc9d03536b10f4f73Jan EngelhardtTC_DUMP_ENTRIES(struct xtc_handle *const handle) 1418e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1419664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_DUMP_ENTRIES; 1420e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(handle); 142197fb2f1579f0794377db1dca7c5bb07fade1a0dcPatrick McHardy 1422e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell printf("libiptc v%s. %u bytes.\n", 14238b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt XTABLES_VERSION, handle->entries->size); 1424e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Table `%s'\n", handle->info.name); 1425d73af64b9d28a5b0309104232c848e8ca8ab6956Jan Engelhardt printf("Hooks: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n", 142667088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_PRE_ROUTING], 142767088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_IN], 142867088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_FORWARD], 142967088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_OUT], 143067088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_POST_ROUTING]); 1431d73af64b9d28a5b0309104232c848e8ca8ab6956Jan Engelhardt printf("Underflows: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n", 143267088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_PRE_ROUTING], 143367088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_IN], 143467088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_FORWARD], 143567088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_OUT], 143667088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_POST_ROUTING]); 1437e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1438aae69bed019826ddec93f761514652a93d871e49Harald Welte ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size, 143979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell dump_entry, handle); 14400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 1441e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1442e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Does this chain exist? */ 1443fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtint TC_IS_CHAIN(const char *chain, struct xtc_handle *const handle) 1444e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1445664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_IS_CHAIN; 1446aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_find_label(chain, handle) != NULL; 1447e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1448e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1449fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtstatic void iptcc_chain_iterator_advance(struct xtc_handle *handle) 1450aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1451aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c = handle->chain_iterator_cur; 1452aae69bed019826ddec93f761514652a93d871e49Harald Welte 1453aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->list.next == &handle->chains) 1454aae69bed019826ddec93f761514652a93d871e49Harald Welte handle->chain_iterator_cur = NULL; 1455aae69bed019826ddec93f761514652a93d871e49Harald Welte else 1456a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer handle->chain_iterator_cur = 1457aae69bed019826ddec93f761514652a93d871e49Harald Welte list_entry(c->list.next, struct chain_head, list); 1458aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1459e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 146030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. */ 1461e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 14621c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_FIRST_CHAIN(struct xtc_handle *handle) 1463e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 14641c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct chain_head *c = list_entry(handle->chains.next, 1465aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head, list); 1466aae69bed019826ddec93f761514652a93d871e49Harald Welte 1467aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_CHAIN; 1468aae69bed019826ddec93f761514652a93d871e49Harald Welte 1469aae69bed019826ddec93f761514652a93d871e49Harald Welte 14701c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (list_empty(&handle->chains)) { 1471aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no chains\n"); 14720113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 1473aae69bed019826ddec93f761514652a93d871e49Harald Welte } 14740113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 14751c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->chain_iterator_cur = c; 14761c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_iterator_advance(handle); 147730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1478aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 1479aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 148030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 148130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 148230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. Returns NULL at end. */ 148330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellconst char * 14841c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_NEXT_CHAIN(struct xtc_handle *handle) 148530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 14861c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct chain_head *c = handle->chain_iterator_cur; 1487aae69bed019826ddec93f761514652a93d871e49Harald Welte 1488aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_CHAIN; 148930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1490aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1491aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": no more chains\n"); 149230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1493aae69bed019826ddec93f761514652a93d871e49Harald Welte } 149430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 14951c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_iterator_advance(handle); 1496a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 1497aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP(": returning `%s'\n", c->name); 1498aae69bed019826ddec93f761514652a93d871e49Harald Welte return c->name; 149930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 150030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 150130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Get first rule in the given chain: NULL for empty chain. */ 150279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 15031c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_FIRST_RULE(const char *chain, struct xtc_handle *handle) 150430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 1505aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1506aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1507aae69bed019826ddec93f761514652a93d871e49Harald Welte 1508aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_FIRST_RULE; 150930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1510aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("first rule(%s): ", chain); 1511aae69bed019826ddec93f761514652a93d871e49Harald Welte 15121c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt c = iptcc_find_label(chain, handle); 151330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!c) { 151430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell errno = ENOENT; 151530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1516e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1517e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 151830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Empty chain: single return/policy rule */ 1519aae69bed019826ddec93f761514652a93d871e49Harald Welte if (list_empty(&c->rules)) { 1520aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("no rules, returning NULL\n"); 152130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1522aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1523aae69bed019826ddec93f761514652a93d871e49Harald Welte 1524aae69bed019826ddec93f761514652a93d871e49Harald Welte r = list_entry(c->rules.next, struct rule_head, list); 15251c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->rule_iterator_cur = r; 1526aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("%p\n", r); 152730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1528aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 1529e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1530e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 153130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Returns NULL when rules run out. */ 153279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 15331c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_NEXT_RULE(const STRUCT_ENTRY *prev, struct xtc_handle *handle) 153430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 1535aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1536aae69bed019826ddec93f761514652a93d871e49Harald Welte 1537664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_NEXT_RULE; 15381c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt DEBUGP("rule_iterator_cur=%p...", handle->rule_iterator_cur); 1539aae69bed019826ddec93f761514652a93d871e49Harald Welte 15401c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (handle->rule_iterator_cur == NULL) { 1541aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning NULL\n"); 154230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 1543aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1544a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 1545a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer r = list_entry(handle->rule_iterator_cur->list.next, 1546aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 154730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1548aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_NEXT_RULE; 1549aae69bed019826ddec93f761514652a93d871e49Harald Welte 1550a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer DEBUGP_C("next=%p, head=%p...", &r->list, 15511c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt &handle->rule_iterator_cur->chain->rules); 1552aae69bed019826ddec93f761514652a93d871e49Harald Welte 15531c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (&r->list == &handle->rule_iterator_cur->chain->rules) { 15541c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->rule_iterator_cur = NULL; 1555aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("finished, returning NULL\n"); 1556aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1557aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1558aae69bed019826ddec93f761514652a93d871e49Harald Welte 15591c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->rule_iterator_cur = r; 1560aae69bed019826ddec93f761514652a93d871e49Harald Welte 1561aae69bed019826ddec93f761514652a93d871e49Harald Welte /* NOTE: prev is without any influence ! */ 1562aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("returning rule %p\n", r); 1563aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->entry; 156430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 156530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1566aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 156733690a1aec0b6309ff90066ca56285b6e43013f2Jan Engelhardtstatic const char *standard_target_map(int verdict) 1568e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1569aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (verdict) { 1570aae69bed019826ddec93f761514652a93d871e49Harald Welte case RETURN: 157179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_RETURN; 1572aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1573aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_ACCEPT-1: 157479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_ACCEPT; 1575aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1576aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_DROP-1: 1577aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_DROP; 1578aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1579aae69bed019826ddec93f761514652a93d871e49Harald Welte case -NF_QUEUE-1: 1580aae69bed019826ddec93f761514652a93d871e49Harald Welte return LABEL_QUEUE; 1581aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1582aae69bed019826ddec93f761514652a93d871e49Harald Welte default: 1583aae69bed019826ddec93f761514652a93d871e49Harald Welte fprintf(stderr, "ERROR: %d not a valid target)\n", 1584aae69bed019826ddec93f761514652a93d871e49Harald Welte verdict); 1585aae69bed019826ddec93f761514652a93d871e49Harald Welte abort(); 1586aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1587e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1588aae69bed019826ddec93f761514652a93d871e49Harald Welte /* not reached */ 1589aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1590e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1591e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1592aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Returns a pointer to the target name of this position. */ 1593aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char *TC_GET_TARGET(const STRUCT_ENTRY *ce, 15941c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 1595e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1596aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 1597e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell struct rule_head *r = container_of(e, struct rule_head, entry[0]); 159851651b64fffc58d4f58d005fa7dc0d9669147c57Jan Engelhardt const unsigned char *data; 1599e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1600aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_TARGET; 16010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1602aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(r->type) { 1603aae69bed019826ddec93f761514652a93d871e49Harald Welte int spos; 1604aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_FALLTHROUGH: 1605aae69bed019826ddec93f761514652a93d871e49Harald Welte return ""; 1606aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1607aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_JUMP: 1608aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name); 1609aae69bed019826ddec93f761514652a93d871e49Harald Welte return r->jump->name; 1610aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1611aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_STANDARD: 161251651b64fffc58d4f58d005fa7dc0d9669147c57Jan Engelhardt data = GET_TARGET(e)->data; 161351651b64fffc58d4f58d005fa7dc0d9669147c57Jan Engelhardt spos = *(const int *)data; 1614aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("r=%p, spos=%d'\n", r, spos); 1615aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(spos); 1616aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1617aae69bed019826ddec93f761514652a93d871e49Harald Welte case IPTCC_R_MODULE: 1618aae69bed019826ddec93f761514652a93d871e49Harald Welte return GET_TARGET(e)->u.user.name; 1619aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 16200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 1621aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1622aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1623aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Is this a built-in chain? Actually returns hook + 1. */ 1624aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1625fd1873110f8e57be578df17fc9d03536b10f4f73Jan EngelhardtTC_BUILTIN(const char *chain, struct xtc_handle *const handle) 1626aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1627aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1628a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 1629aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_BUILTIN; 16300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1631aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(chain, handle); 1632aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1633aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1634b0f3d2d7261be3fe256a66abcc237241fea43a02Martin Josefsson return 0; 16350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 16360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1637aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_is_builtin(c); 16380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 16390113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1640aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Get the policy of a given built-in chain */ 1641aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char * 1642aae69bed019826ddec93f761514652a93d871e49Harald WelteTC_GET_POLICY(const char *chain, 1643aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_COUNTERS *counters, 16441c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 16450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 1646aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 16470113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1648aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = TC_GET_POLICY; 1649fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte 1650aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("called for chain %s\n", chain); 16510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 16521c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt c = iptcc_find_label(chain, handle); 1653aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 1654aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1655aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 16560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 16570113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1658aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) 1659aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 16600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1661aae69bed019826ddec93f761514652a93d871e49Harald Welte *counters = c->counters; 16620113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1663aae69bed019826ddec93f761514652a93d871e49Harald Welte return standard_target_map(c->verdict); 16640113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 1665e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1666e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1667aae69bed019826ddec93f761514652a93d871e49Harald Welteiptcc_standard_map(struct rule_head *r, int verdict) 1668e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1669aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 167079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 1671e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 167279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1673e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 167467088e73ce7707229c56987868f112051defca5aRusty Russell if (t->target.u.target_size 16758c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1676e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1677e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1678e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1679e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset for memcmp convenience on delete/replace */ 168079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 168179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell strcpy(t->target.u.user.name, STANDARD_TARGET); 1682e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = verdict; 1683e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1684aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_STANDARD; 1685aae69bed019826ddec93f761514652a93d871e49Harald Welte 1686e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1687e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 16887e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1689e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1690fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptcc_map_target(struct xtc_handle *const handle, 1691aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r) 1692e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1693aae69bed019826ddec93f761514652a93d871e49Harald Welte STRUCT_ENTRY *e = r->entry; 16940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 1695e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1696e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's empty (=> fall through) */ 1697aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(t->u.user.name, "") == 0) { 1698aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_FALLTHROUGH; 1699aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1700aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1701e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's a standard target name... */ 170279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 1703aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_ACCEPT - 1); 170479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 1705aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_DROP - 1); 170667088e73ce7707229c56987868f112051defca5aRusty Russell else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 1707aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, -NF_QUEUE - 1); 170879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 1709aae69bed019826ddec93f761514652a93d871e49Harald Welte return iptcc_standard_map(r, RETURN); 171079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (TC_BUILTIN(t->u.user.name, handle)) { 1711e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Can't jump to builtins. */ 1712e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1713e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1714e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 1715e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's an existing chain name. */ 1716aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1717aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("trying to find chain `%s': ", t->u.user.name); 1718aae69bed019826ddec93f761514652a93d871e49Harald Welte 1719aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_find_label(t->u.user.name, handle); 1720aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c) { 1721aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("found!\n"); 1722aae69bed019826ddec93f761514652a93d871e49Harald Welte r->type = IPTCC_R_JUMP; 1723aae69bed019826ddec93f761514652a93d871e49Harald Welte r->jump = c; 1724aae69bed019826ddec93f761514652a93d871e49Harald Welte c->references++; 1725aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1726aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1727aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("not found :(\n"); 1728e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1729e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1730e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Must be a module? If not, kernel will reject... */ 17313aef54dce4f9bbe0b466478fd33a1d3131efbbb8Rusty Russell /* memset to all 0 for your memcmp convenience: don't clear version */ 1732228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell memset(t->u.user.name + strlen(t->u.user.name), 1733e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 0, 17343aef54dce4f9bbe0b466478fd33a1d3131efbbb8Rusty Russell FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name)); 1735733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell r->type = IPTCC_R_MODULE; 1736aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(handle); 1737aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1738e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1739e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 17400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 1741e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 174279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 174379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 174479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 17451c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 1746e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1747aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1748eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson struct rule_head *r; 1749eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson struct list_head *prev; 1750e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 175179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INSERT_ENTRY; 1752aae69bed019826ddec93f761514652a93d871e49Harald Welte 17531c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 1754e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1755e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1756e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1757e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1758eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson /* first rulenum index = 0 1759eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson first c->num_rules index = 1 */ 1760eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson if (rulenum > c->num_rules) { 1761e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1762e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1763e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1764e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1765631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson /* If we are inserting at the end just take advantage of the 1766631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson double linked list, insert will happen before the entry 1767631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson prev points to. */ 1768631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson if (rulenum == c->num_rules) { 1769eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson prev = &c->rules; 1770a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else if (rulenum + 1 <= c->num_rules/2) { 1771631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson r = iptcc_get_rule_num(c, rulenum + 1); 1772a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson prev = &r->list; 1773a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else { 1774a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1775631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson prev = &r->list; 1776631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson } 1777eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson 1778aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1779aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1780aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1781aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1782aae69bed019826ddec93f761514652a93d871e49Harald Welte 1783aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1784aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1785aae69bed019826ddec93f761514652a93d871e49Harald Welte 17861c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!iptcc_map_target(handle, r)) { 1787aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 17880113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1789aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1790aae69bed019826ddec93f761514652a93d871e49Harald Welte 1791eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson list_add_tail(&r->list, prev); 1792aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1793aae69bed019826ddec93f761514652a93d871e49Harald Welte 17941c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 1795e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1796aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1797e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1798e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1799e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 1800e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 180179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 180279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 180379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 18041c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 1805e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1806aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1807aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *old; 1808e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 180979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_REPLACE_ENTRY; 1810e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18111c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 1812e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1813e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1814e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1815e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18160f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson if (rulenum >= c->num_rules) { 1817e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1818e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1819e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1820e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18210f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson /* Take advantage of the double linked list if possible. */ 18220f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson if (rulenum + 1 <= c->num_rules/2) { 18230f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson old = iptcc_get_rule_num(c, rulenum + 1); 18240f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson } else { 18250f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson old = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 18260f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson } 18270f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson 1828aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1829aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1830e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1831aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1832aae69bed019826ddec93f761514652a93d871e49Harald Welte 1833aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1834aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1835e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18361c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!iptcc_map_target(handle, r)) { 1837aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 18380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1839aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1840aae69bed019826ddec93f761514652a93d871e49Harald Welte 1841aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add(&r->list, &old->list); 1842aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(old); 18430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 18441c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 1845aae69bed019826ddec93f761514652a93d871e49Harald Welte 1846aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1847e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1848e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Append entry `fw' to chain `chain'. Equivalent to insert with 1850e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher rulenum = length of chain. */ 1851e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 185279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 185379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 18541c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 1855e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1856aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1857aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 1858e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 185979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_APPEND_ENTRY; 18601c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 1861aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to find chain `%s'\n", chain); 1862e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1863e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1864e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1865e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1866aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1867aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("unable to allocate rule for chain `%s'\n", chain); 1868aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1869aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1870aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1871aae69bed019826ddec93f761514652a93d871e49Harald Welte 1872aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(r->entry, e, e->next_offset); 1873aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 1874aae69bed019826ddec93f761514652a93d871e49Harald Welte 18751c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!iptcc_map_target(handle, r)) { 187612009531e6a96a62ee398eb0ab3e9ec0b3b57701Martin Josefsson DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1877aae69bed019826ddec93f761514652a93d871e49Harald Welte free(r); 18780113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1879aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1880aae69bed019826ddec93f761514652a93d871e49Harald Welte 1881aae69bed019826ddec93f761514652a93d871e49Harald Welte list_add_tail(&r->list, &c->rules); 1882aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules++; 1883aae69bed019826ddec93f761514652a93d871e49Harald Welte 18841c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 18850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1886aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1887e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1888e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1889e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 189079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellmatch_different(const STRUCT_ENTRY_MATCH *a, 1891edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *a_elems, 1892edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_elems, 1893edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned char **maskptr) 1894e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 189579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY_MATCH *b; 1896edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1897e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1898e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Offset of b is the same as a. */ 189930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell b = (void *)b_elems + ((unsigned char *)a - a_elems); 1900e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1901228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (a->u.match_size != b->u.match_size) 1902e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1903e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1904228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (strcmp(a->u.user.name, b->u.user.name) != 0) 1905e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1906e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 190773ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell *maskptr += ALIGN(sizeof(*a)); 1908edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 190973ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1910edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1911edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 1; 1912edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell *maskptr += i; 1913edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 0; 1914edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell} 1915edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 1916edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russellstatic inline int 1917733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russelltarget_same(struct rule_head *a, struct rule_head *b,const unsigned char *mask) 1918edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell{ 1919edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1920733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell STRUCT_ENTRY_TARGET *ta, *tb; 1921e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1922733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (a->type != b->type) 1923733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1924733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1925733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell ta = GET_TARGET(a->entry); 1926733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell tb = GET_TARGET(b->entry); 1927733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1928733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell switch (a->type) { 1929733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_FALLTHROUGH: 1930733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 1931733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_JUMP: 1932733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return a->jump == b->jump; 1933733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_STANDARD: 1934733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return ((STRUCT_STANDARD_TARGET *)ta)->verdict 1935733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell == ((STRUCT_STANDARD_TARGET *)tb)->verdict; 1936733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell case IPTCC_R_MODULE: 1937733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (ta->u.target_size != tb->u.target_size) 1938733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1939733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (strcmp(ta->u.user.name, tb->u.user.name) != 0) 1940733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1941733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1942733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell for (i = 0; i < ta->u.target_size - sizeof(*ta); i++) 1943daade4452715cbd1feea05d5231c5e38e3b0b98bRusty Russell if (((ta->data[i] ^ tb->data[i]) & mask[i]) != 0) 1944733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 0; 1945733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 1946733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell default: 1947733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell fprintf(stderr, "ERROR: bad type %i\n", a->type); 1948733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell abort(); 1949733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell } 1950e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1951e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1952733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russellstatic unsigned char * 195379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellis_same(const STRUCT_ENTRY *a, 195479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *b, 195579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask); 1956e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1957d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek 1958d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek/* find the first rule in `chain' which matches `fw' and remove it unless dry_run is set */ 1959d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanekstatic int delete_entry(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, 1960d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek unsigned char *matchmask, struct xtc_handle *handle, 1961d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek bool dry_run) 1962e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1963aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 1964e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell struct rule_head *r, *i; 1965e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 196679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_ENTRY; 19671c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 1968e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1969e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1970e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1971e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1972e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell /* Create a rule_head from origfw. */ 1973e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell r = iptcc_alloc_rule(c, origfw->next_offset); 1974e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell if (!r) { 19750113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = ENOMEM; 19760113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 19770113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 19780113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1979e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell memcpy(r->entry, origfw, origfw->next_offset); 1980e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell r->counter_map.maptype = COUNTER_MAP_NOMAP; 19811c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!iptcc_map_target(handle, r)) { 1982e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1983e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell free(r); 1984e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell return 0; 198504a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer } else { 198604a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer /* iptcc_map_target increment target chain references 198704a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer * since this is a fake rule only used for matching 1988a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer * the chain references count is decremented again. 198904a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer */ 199004a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer if (r->type == IPTCC_R_JUMP 199104a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer && r->jump) 199204a1e4cabd185d7a93bea1ece276343044d9ecd4Patrick McHardyJesper Brouer r->jump->references--; 1993e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell } 1994fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 1995e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell list_for_each_entry(i, &c->rules, list) { 1996733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell unsigned char *mask; 1997733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 1998733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell mask = is_same(r->entry, i->entry, matchmask); 1999733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (!mask) 2000733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell continue; 2001733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 2002733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (!target_same(r, i, mask)) 2003733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell continue; 2004733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell 2005d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek /* if we are just doing a dry run, we simply skip the rest */ 2006d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek if (dry_run) 2007d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek return 1; 2008d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek 2009733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell /* If we are about to delete the rule that is the 2010733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell * current iterator, move rule iterator back. next 2011733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell * pointer will then point to real next node */ 20121c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (i == handle->rule_iterator_cur) { 2013a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer handle->rule_iterator_cur = 20141c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt list_entry(handle->rule_iterator_cur->list.prev, 2015733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell struct rule_head, list); 2016733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell } 2017fe53707285c250c6bb1e434ea6f8271cf061c67bHarald Welte 2018733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell c->num_rules--; 2019733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell iptcc_delete_rule(i); 20202a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson 20211c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2022733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell free(r); 2023733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell return 1; 2024e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2025e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2026e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell free(r); 2027e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2028e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 20297e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell} 2030aae69bed019826ddec93f761514652a93d871e49Harald Welte 2031d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek/* check whether a specified rule is present */ 2032d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanekint TC_CHECK_ENTRY(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, 2033d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek unsigned char *matchmask, struct xtc_handle *handle) 2034d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek{ 2035d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek /* do a dry-run delete to find out whether a matching rule exists */ 2036d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek return delete_entry(chain, origfw, matchmask, handle, true); 2037d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek} 2038d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek 2039d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek/* Delete the first rule in `chain' which matches `fw'. */ 2040d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanekint TC_DELETE_ENTRY(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, 2041d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek unsigned char *matchmask, struct xtc_handle *handle) 2042d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek{ 2043d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek return delete_entry(chain, origfw, matchmask, handle, false); 2044d59b9db031abee37a9aa9776662dd15370faabf4Stefan Tomanek} 2045e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2046e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Delete the rule in position `rulenum' in `chain'. */ 2047e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 204879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 204979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 20501c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 2051e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2052aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2053aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 2054e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 205579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_NUM_ENTRY; 2056aae69bed019826ddec93f761514652a93d871e49Harald Welte 20571c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2058e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2059e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2060e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2061e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2062a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson if (rulenum >= c->num_rules) { 2063631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson errno = E2BIG; 2064631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson return 0; 2065631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson } 2066631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson 2067631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson /* Take advantage of the double linked list if possible. */ 2068a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson if (rulenum + 1 <= c->num_rules/2) { 2069a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num(c, rulenum + 1); 2070a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else { 2071a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 2072e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2073e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2074aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the rule that is the current 2075aae69bed019826ddec93f761514652a93d871e49Harald Welte * iterator, move rule iterator back. next pointer will then 2076aae69bed019826ddec93f761514652a93d871e49Harald Welte * point to real next node */ 20771c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (r == handle->rule_iterator_cur) { 2078a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer handle->rule_iterator_cur = 20791c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt list_entry(handle->rule_iterator_cur->list.prev, 2080aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head, list); 20810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 2082e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2083aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules--; 2084aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 2085aae69bed019826ddec93f761514652a93d871e49Harald Welte 20861c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 20872a5dbbb883fb0cc8a122b47a5d8e08ef3e6ff5bcMartin Josefsson 2088aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 2089e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2090e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2091e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Flushes the entries in the given chain (ie. empties chain). */ 2092e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 20931c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2094e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2095aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2096aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r, *tmp; 2097e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 20980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte iptc_fn = TC_FLUSH_ENTRIES; 20991c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2100e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2101e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2102e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2103e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2104aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry_safe(r, tmp, &c->rules, list) { 2105aae69bed019826ddec93f761514652a93d871e49Harald Welte iptcc_delete_rule(r); 2106aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2107aae69bed019826ddec93f761514652a93d871e49Harald Welte 2108aae69bed019826ddec93f761514652a93d871e49Harald Welte c->num_rules = 0; 2109aae69bed019826ddec93f761514652a93d871e49Harald Welte 21101c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2111aae69bed019826ddec93f761514652a93d871e49Harald Welte 2112aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 2113e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2114e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2115e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Zeroes the counters in a chain. */ 2116e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 21171c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2118e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2119aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2120aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 21217e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 2122664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_ZERO_ENTRIES; 21231c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2124e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2125e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2126e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2127e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2128e5bd1d779fab33353c1dc2d2fa49db639dcebd38Andy Gay if (c->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2129e5bd1d779fab33353c1dc2d2fa49db639dcebd38Andy Gay c->counter_map.maptype = COUNTER_MAP_ZEROED; 2130e5bd1d779fab33353c1dc2d2fa49db639dcebd38Andy Gay 2131aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 2132aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2133aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 2134e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2135aae69bed019826ddec93f761514652a93d871e49Harald Welte 21361c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2137e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2138e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2139e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2140e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 21411cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteSTRUCT_COUNTERS * 21421cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_READ_COUNTER(const IPT_CHAINLABEL chain, 21431cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 21441c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 21451cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 2146aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2147aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 21481cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21491cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_READ_COUNTER; 21501cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 21511cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21521c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 21531cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 21541cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return NULL; 21551cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 21561cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2157aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 21580113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 21590113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 21600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 21610113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2162aae69bed019826ddec93f761514652a93d871e49Harald Welte return &r->entry[0].counters; 21631cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 21641cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21651cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 21661cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 21671cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 21681c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 21691cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 2170aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2171aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 2172a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer 21731cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_ZERO_COUNTER; 21741c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt CHECK(handle); 21751cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21761c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 21771cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 21781cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 21791cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 21801cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2181aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 21820113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 21830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 21840113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 21850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2186aae69bed019826ddec93f761514652a93d871e49Harald Welte if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2187aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_ZEROED; 21881cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21891c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 21901cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 21911cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 21921cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 21931cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2194a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouerint 21951cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_SET_COUNTER(const IPT_CHAINLABEL chain, 21961cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 21971cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 21981c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 21991cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 2200aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2201aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 22021cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 22031cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 22041cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_SET_COUNTER; 22051c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt CHECK(handle); 22061cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 22071c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 22081cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 22091cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 22101cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 22110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2212aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(r = iptcc_get_rule_num(c, rulenum))) { 22130113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 22140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 22150113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 22160113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2217aae69bed019826ddec93f761514652a93d871e49Harald Welte e = r->entry; 2218aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.maptype = COUNTER_MAP_SET; 22190113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 22200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 22211cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 22221c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 22231cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 22241cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 22251cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 22261cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2227e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Creates a new chain. */ 2228e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* To create a chain, create two rules: error node and unconditional 2229e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * return. */ 2230e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 22311c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_CREATE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2232e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2233aae69bed019826ddec93f761514652a93d871e49Harald Welte static struct chain_head *c; 22341f23d3c2544f4329b31804392abc4eff434ba308Patrick McHardy int capacity; 22351f23d3c2544f4329b31804392abc4eff434ba308Patrick McHardy int exceeded; 2236e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 223779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_CREATE_CHAIN; 2238e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2239e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* find_label doesn't cover built-in targets: DROP, ACCEPT, 2240e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher QUEUE, RETURN. */ 22411c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (iptcc_find_label(chain, handle) 224279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_DROP) == 0 224379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_ACCEPT) == 0 224467088e73ce7707229c56987868f112051defca5aRusty Russell || strcmp(chain, LABEL_QUEUE) == 0 224579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_RETURN) == 0) { 2246aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain `%s' already exists\n", chain); 2247e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 2248e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2249e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2250e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 225179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 2252aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Chain name `%s' too long\n", chain); 2253e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 2254e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2255e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2256e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2257aae69bed019826ddec93f761514652a93d871e49Harald Welte c = iptcc_alloc_chain_head(chain, 0); 2258aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!c) { 2259aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Cannot allocate memory for chain `%s'\n", chain); 2260aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 2261aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 2262e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2263aae69bed019826ddec93f761514652a93d871e49Harald Welte } 22641c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->num_chains++; /* New user defined chain */ 2265e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2266aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("Creating chain `%s'\n", chain); 22671c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptc_insert_chain(handle, c); /* Insert sorted */ 2268e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 226901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Inserting chains don't change the correctness of the chain 227001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * index (except if its smaller than index[0], but that 227101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * handled by iptc_insert_chain). It only causes longer lists 227201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * in the buckets. Thus, only rebuild chain index when the 227301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer * capacity is exceed with CHAIN_INDEX_INSERT_MAX chains. 227401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer */ 22751c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt capacity = handle->chain_index_sz * CHAIN_INDEX_BUCKET_LEN; 22761c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt exceeded = handle->num_chains - capacity; 227701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (exceeded > CHAIN_INDEX_INSERT_MAX) { 227801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer debug("Capacity(%d) exceeded(%d) rebuild (chains:%d)\n", 22791c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt capacity, exceeded, handle->num_chains); 22801c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_index_rebuild(handle); 228101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 228201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 22831c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2284e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2285aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 2286e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2287e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2288e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get the number of references to this chain. */ 2289e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 229079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 22911c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 2292e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2293aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2294e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2295664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_GET_REFERENCES; 22961c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2297e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2298e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2299e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2300e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2301aae69bed019826ddec93f761514652a93d871e49Harald Welte *ref = c->references; 2302aae69bed019826ddec93f761514652a93d871e49Harald Welte 2303e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2304e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2305e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2306e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Deletes a chain. */ 2307e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 23081c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_DELETE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2309e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2310e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int references; 2311aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 23127e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 231379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_CHAIN; 2314e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 23151c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2316aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 2317aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 2318aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 2319aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2320aae69bed019826ddec93f761514652a93d871e49Harald Welte 23211c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (TC_BUILTIN(chain, handle)) { 2322aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot remove builtin chain `%s'\n", chain); 2323e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 2324e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2325e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2326e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2327aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!TC_GET_REFERENCES(&references, chain, handle)) { 2328aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot get references on chain `%s'\n", chain); 2329e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2330e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2331e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2332aae69bed019826ddec93f761514652a93d871e49Harald Welte if (references > 0) { 2333aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' still has references\n", chain); 2334aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EMLINK; 2335e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2336e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2337e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2338aae69bed019826ddec93f761514652a93d871e49Harald Welte if (c->num_rules) { 2339aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' is not empty\n", chain); 2340e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOTEMPTY; 2341e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2342e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2343e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2344aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If we are about to delete the chain that is the current 234548bde40e73b45ad134d32cde88b779fe509faf64Jesper Dangaard Brouer * iterator, move chain iterator forward. */ 23461c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (c == handle->chain_iterator_cur) 23471c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_iterator_advance(handle); 2348aae69bed019826ddec93f761514652a93d871e49Harald Welte 23491c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt handle->num_chains--; /* One user defined chain deleted */ 235048bde40e73b45ad134d32cde88b779fe509faf64Jesper Dangaard Brouer 235101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer //list_del(&c->list); /* Done in iptcc_chain_index_delete_chain() */ 23521c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt iptcc_chain_index_delete_chain(c, handle); 235301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer free(c); 235401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 2355aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("chain `%s' deleted\n", chain); 23560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 23571c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2358aae69bed019826ddec93f761514652a93d871e49Harald Welte 2359aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 2360e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2361e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2362e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Renames a chain. */ 236379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 236479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL newname, 23651c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 2366e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2367aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 236879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_RENAME_CHAIN; 2369e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 23701de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte /* find_label doesn't cover built-in targets: DROP, ACCEPT, 23711de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte QUEUE, RETURN. */ 23721c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (iptcc_find_label(newname, handle) 237379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_DROP) == 0 237479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_ACCEPT) == 0 23751de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte || strcmp(newname, LABEL_QUEUE) == 0 237679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_RETURN) == 0) { 2377e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 2378e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2379e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2380e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 23811c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(oldname, handle)) 23821c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt || TC_BUILTIN(oldname, handle)) { 2383e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 2384e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2385e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2386e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 238779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 2388e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 2389e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2390e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2391e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 239264ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer /* This only unlinks "c" from the list, thus no free(c) */ 239364ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer iptcc_chain_index_delete_chain(c, handle); 239464ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer 239564ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer /* Change the name of the chain */ 2396aae69bed019826ddec93f761514652a93d871e49Harald Welte strncpy(c->name, newname, sizeof(IPT_CHAINLABEL)); 239764ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer 239864ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer /* Insert sorted into to list again */ 239964ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer iptc_insert_chain(handle, c); 240064ff47cde38e48b621883947fd61b9b1357f9451Jesper Dangaard Brouer 24011c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 24020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2403e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2404e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2405e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2406e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Sets the policy on a built-in chain. */ 2407e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 240879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_SET_POLICY(const IPT_CHAINLABEL chain, 240979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL policy, 24101cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 24111c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct xtc_handle *handle) 2412e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2413aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2414e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 241579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_SET_POLICY; 2416aae69bed019826ddec93f761514652a93d871e49Harald Welte 24171c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!(c = iptcc_find_label(chain, handle))) { 2418aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot find chain `%s'\n", chain); 2419c8264991454b5e77279830736f80ea3153b6f814Marc Boucher errno = ENOENT; 2420e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2421aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2422e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2423aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptcc_is_builtin(c)) { 2424aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain); 2425aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 24269e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte return 0; 24279e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte } 24289e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 242979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(policy, LABEL_ACCEPT) == 0) 2430aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_ACCEPT - 1; 243179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(policy, LABEL_DROP) == 0) 2432aae69bed019826ddec93f761514652a93d871e49Harald Welte c->verdict = -NF_DROP - 1; 2433e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else { 2434e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 2435e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 2436e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 24371cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 24381cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (counters) { 24391cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte /* set byte and packet counters */ 2440aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS)); 2441aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_SET; 24421cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } else { 2443aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.maptype = COUNTER_MAP_NOMAP; 24441cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 24451cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 24461c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt set_changed(handle); 2447e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2448e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2449e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2450e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2451e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Without this, on gcc 2.7.2.3, we get: 245279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell libiptc.c: In function `TC_COMMIT': 2453e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher libiptc.c:833: fixed or forbidden register was spilled. 2454e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher This may be due to a compiler bug or to impossible asm 2455e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher statements or clauses. 2456e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher*/ 2457e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 245879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellsubtract_counters(STRUCT_COUNTERS *answer, 245979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *a, 246079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *b) 2461e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2462e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->pcnt = a->pcnt - b->pcnt; 2463e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->bcnt = a->bcnt - b->bcnt; 2464e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2465e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2466aae69bed019826ddec93f761514652a93d871e49Harald Welte 2467dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardtstatic void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, unsigned int idx) 2468aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 2469dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt newcounters->counters[idx] = ((STRUCT_COUNTERS) { 0, 0}); 2470aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NOMAP => zero\n"); 2471aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2472aae69bed019826ddec93f761514652a93d871e49Harald Welte 2473aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters, 2474dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt STRUCT_REPLACE *repl, unsigned int idx, 2475aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int mappos) 2476aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 2477aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 2478aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 2479aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 2480aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: X + Y + Z. 2481aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in X + Y 2482aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in replacement read. 2483aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 2484dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt newcounters->counters[idx] = repl->counters[mappos]; 2485aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos); 2486aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2487aae69bed019826ddec93f761514652a93d871e49Harald Welte 2488aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters, 2489dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt STRUCT_REPLACE *repl, unsigned int idx, 2490dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt unsigned int mappos, STRUCT_COUNTERS *counters) 2491aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 2492aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 2493aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 2494aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 2495aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: Y + Z. 2496aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in Y. 2497aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in (replacement read - original read). 2498aae69bed019826ddec93f761514652a93d871e49Harald Welte */ 2499dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt subtract_counters(&newcounters->counters[idx], 2500aae69bed019826ddec93f761514652a93d871e49Harald Welte &repl->counters[mappos], 2501aae69bed019826ddec93f761514652a93d871e49Harald Welte counters); 2502aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("ZEROED => mappos %u\n", mappos); 2503aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2504aae69bed019826ddec93f761514652a93d871e49Harald Welte 2505aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void counters_map_set(STRUCT_COUNTERS_INFO *newcounters, 2506dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt unsigned int idx, STRUCT_COUNTERS *counters) 2507aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 2508aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Want to set counter (iptables-restore) */ 2509aae69bed019826ddec93f761514652a93d871e49Harald Welte 2510dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt memcpy(&newcounters->counters[idx], counters, 2511aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(STRUCT_COUNTERS)); 2512aae69bed019826ddec93f761514652a93d871e49Harald Welte 2513aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP_C("SET\n"); 2514aae69bed019826ddec93f761514652a93d871e49Harald Welte} 2515aae69bed019826ddec93f761514652a93d871e49Harald Welte 2516aae69bed019826ddec93f761514652a93d871e49Harald Welte 2517e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 25181c9015b2cb483678f153121255e10ec0bbfde3e6Jan EngelhardtTC_COMMIT(struct xtc_handle *handle) 2519e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2520e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Replace, then map back the counters. */ 252179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_REPLACE *repl; 252279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_COUNTERS_INFO *newcounters; 2523aae69bed019826ddec93f761514652a93d871e49Harald Welte struct chain_head *c; 2524aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 2525841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson size_t counterlen; 2526aae69bed019826ddec93f761514652a93d871e49Harald Welte int new_number; 2527aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int new_size; 2528e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2529664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates iptc_fn = TC_COMMIT; 2530e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 2531841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 2532e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Don't commit if nothing changed. */ 25331c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!handle->changed) 2534e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher goto finished; 2535e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 25361c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt new_number = iptcc_compile_table_prep(handle, &new_size); 2537aae69bed019826ddec93f761514652a93d871e49Harald Welte if (new_number < 0) { 2538aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 2539d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_zero; 2540aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2541aae69bed019826ddec93f761514652a93d871e49Harald Welte 2542aae69bed019826ddec93f761514652a93d871e49Harald Welte repl = malloc(sizeof(*repl) + new_size); 2543e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl) { 2544e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2545d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_zero; 2546e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2547ad3b4f9973ac15981b98b8fc4d364ef1ce524212Martin Josefsson memset(repl, 0, sizeof(*repl) + new_size); 2548aae69bed019826ddec93f761514652a93d871e49Harald Welte 2549e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell#if 0 2550e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell TC_DUMP_ENTRIES(*handle); 2551e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell#endif 2552e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell 2553aae69bed019826ddec93f761514652a93d871e49Harald Welte counterlen = sizeof(STRUCT_COUNTERS_INFO) 2554aae69bed019826ddec93f761514652a93d871e49Harald Welte + sizeof(STRUCT_COUNTERS) * new_number; 2555e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2556e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the old counters we will get from kernel */ 255779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell repl->counters = malloc(sizeof(STRUCT_COUNTERS) 25581c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt * handle->info.num_entries); 2559e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl->counters) { 2560e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2561d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_repl; 2562e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2563e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the counters we're going to put back, later. */ 2564e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters = malloc(counterlen); 2565e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!newcounters) { 2566e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 2567d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_repl_counters; 2568e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2569aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(newcounters, 0, counterlen); 2570e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 25711c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt strcpy(repl->name, handle->info.name); 2572aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries = new_number; 2573aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->size = new_size; 2574aae69bed019826ddec93f761514652a93d871e49Harald Welte 25751c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt repl->num_counters = handle->info.num_entries; 25761c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt repl->valid_hooks = handle->info.valid_hooks; 2577aae69bed019826ddec93f761514652a93d871e49Harald Welte 2578aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("num_entries=%u, size=%u, num_counters=%u\n", 2579aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries, repl->size, repl->num_counters); 2580aae69bed019826ddec93f761514652a93d871e49Harald Welte 25811c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt ret = iptcc_compile_table(handle, repl); 2582aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ret < 0) { 2583aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ret; 2584d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_newcounters; 2585aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2586aae69bed019826ddec93f761514652a93d871e49Harald Welte 2587aae69bed019826ddec93f761514652a93d871e49Harald Welte 2588aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 2589aae69bed019826ddec93f761514652a93d871e49Harald Welte { 2590a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer int fd = open("/tmp/libiptc-so_set_replace.blob", 2591aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 2592aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 2593aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, repl, sizeof(*repl) + repl->size); 2594aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 2595aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2596aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2597aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2598e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2599175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 2600d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte sizeof(*repl) + repl->size); 2601e0865ad29d53b0d3d34b5cc8b5e023eb593172a8Patrick McHardy if (ret < 0) 2602d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_newcounters; 2603e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2604e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Put counters back. */ 26051c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt strcpy(newcounters->name, handle->info.name); 2606aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->num_counters = new_number; 2607aae69bed019826ddec93f761514652a93d871e49Harald Welte 26081c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt list_for_each_entry(c, &handle->chains, list) { 2609aae69bed019826ddec93f761514652a93d871e49Harald Welte struct rule_head *r; 2610aae69bed019826ddec93f761514652a93d871e49Harald Welte 2611aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Builtin chains have their own counters */ 2612aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptcc_is_builtin(c)) { 2613aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for chain-index %u: ", c->foot_index); 2614aae69bed019826ddec93f761514652a93d871e49Harald Welte switch(c->counter_map.maptype) { 2615aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2616aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, c->foot_index); 2617aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2618aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2619aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2620a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer c->foot_index, 2621aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos); 2622aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2623aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2624aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2625a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer c->foot_index, 2626aae69bed019826ddec93f761514652a93d871e49Harald Welte c->counter_map.mappos, 2627aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2628aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2629aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2630aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, c->foot_index, 2631aae69bed019826ddec93f761514652a93d871e49Harald Welte &c->counters); 2632aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2633aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2634aae69bed019826ddec93f761514652a93d871e49Harald Welte } 26351cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 2636aae69bed019826ddec93f761514652a93d871e49Harald Welte list_for_each_entry(r, &c->rules, list) { 2637aae69bed019826ddec93f761514652a93d871e49Harald Welte DEBUGP("counter for index %u: ", r->index); 2638aae69bed019826ddec93f761514652a93d871e49Harald Welte switch (r->counter_map.maptype) { 2639aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NOMAP: 2640aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_nomap(newcounters, r->index); 2641aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2642aae69bed019826ddec93f761514652a93d871e49Harald Welte 2643aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 2644aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_normal_map(newcounters, repl, 2645a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer r->index, 2646aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos); 2647aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2648aae69bed019826ddec93f761514652a93d871e49Harald Welte 2649aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_ZEROED: 2650aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_zeroed(newcounters, repl, 2651aae69bed019826ddec93f761514652a93d871e49Harald Welte r->index, 2652aae69bed019826ddec93f761514652a93d871e49Harald Welte r->counter_map.mappos, 2653aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2654aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2655aae69bed019826ddec93f761514652a93d871e49Harald Welte 2656aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_SET: 2657aae69bed019826ddec93f761514652a93d871e49Harald Welte counters_map_set(newcounters, r->index, 2658aae69bed019826ddec93f761514652a93d871e49Harald Welte &r->entry->counters); 2659aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 2660aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2661e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2662e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 266362527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell 2664aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifdef IPTC_DEBUG2 2665aae69bed019826ddec93f761514652a93d871e49Harald Welte { 2666a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer int fd = open("/tmp/libiptc-so_set_add_counters.blob", 2667aae69bed019826ddec93f761514652a93d871e49Harald Welte O_CREAT|O_WRONLY); 2668aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fd >= 0) { 2669aae69bed019826ddec93f761514652a93d871e49Harald Welte write(fd, newcounters, counterlen); 2670aae69bed019826ddec93f761514652a93d871e49Harald Welte close(fd); 2671aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2672aae69bed019826ddec93f761514652a93d871e49Harald Welte } 2673aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 2674aae69bed019826ddec93f761514652a93d871e49Harald Welte 2675175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 2676d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte newcounters, counterlen); 2677e0865ad29d53b0d3d34b5cc8b5e023eb593172a8Patrick McHardy if (ret < 0) 2678d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte goto out_free_newcounters; 2679e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2680e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 2681e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 2682e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 2683e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2684d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Weltefinished: 2685e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 2686d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte 2687d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_free_newcounters: 2688d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte free(newcounters); 2689d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_free_repl_counters: 2690d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte free(repl->counters); 2691d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_free_repl: 2692d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte free(repl); 2693d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welteout_zero: 2694d6ba6f57658ee2fee7cf763259e8a0c601479989Harald Welte return 0; 2695e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2696e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2697e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Translates errno numbers into more human-readable form than strerror. */ 2698e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 269979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_STRERROR(int err) 2700e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 2701e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 2702e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct table_struct { 2703e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher void *fn; 2704e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int err; 2705e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char *message; 2706e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } table [] = 27074ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 270879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INIT, EINVAL, "Module is wrong version" }, 2709a9fe5b3d62e4e974e9517b23d0bf7f0f146ed11eJesper Dangaard Brouer { TC_INIT, ENOENT, 27104ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Table does not exist (do you need to insmod?)" }, 271179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 271279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 271379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EMLINK, 2714e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher "Can't delete chain with references left" }, 271579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 271679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 271779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 271879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 27191cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 27201cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 272179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 272279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 2723e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* ENOENT for DELETE probably means no matching rule */ 272479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_ENTRY, ENOENT, 2725c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad rule (does a matching rule exist in that chain?)" }, 272679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, ENOENT, 2727c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad built-in chain name" }, 272879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, EINVAL, 2729c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad policy name" }, 27304ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte 27314ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, 0, "Incompatible with this kernel" }, 27324ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 27334ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 27344ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOMEM, "Memory allocation problem" }, 27354ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOENT, "No chain/target/match by that name" }, 2736e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher }; 2737e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2738e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 2739e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((!table[i].fn || table[i].fn == iptc_fn) 2740e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && table[i].err == err) 2741e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return table[i].message; 2742e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2743e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2744e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return strerror(err); 2745e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 2746