libiptc.c revision 7cd002826d0f329620cb738bc4dc4760ef5e084a
17cd002826d0f329620cb738bc4dc4760ef5e084aStephane Ouellette/* Library which manipulates firewall rules. Version $Revision: 1.44 $ */ 2e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 3e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Architecture of firewall rules is as follows: 4e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * 5e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Chains go INPUT, FORWARD, OUTPUT then user chains. 6e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Each user chain starts with an ERROR node. 7e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Every chain ends with an unconditional jump: a RETURN for user chains, 8e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * and a POLICY for built-ins. 9e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher */ 10e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 113ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte/* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See 123ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte * COPYING for details). 133ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte * (C) 2000-2003 by the Netfilter Core Team <coreteam@netfilter.org> 143ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte * 15fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte * 2003-Jun-20: Harald Welte <laforge@netfilter.org>: 163ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte * - Reimplementation of chain cache to use offsets instead of entries 17fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte * 2003-Jun-23: Harald Welte <laforge@netfilter.org>: 180113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * - performance optimization, sponsored by Astaro AG (http://www.astaro.com/) 19fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte * don't rebuild the chain cache after every operation, instead fix it 20fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte * up after a ruleset change. 213ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte */ 22e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 237cd002826d0f329620cb738bc4dc4760ef5e084aStephane Ouellette#include<sys/types.h> 247cd002826d0f329620cb738bc4dc4760ef5e084aStephane Ouellette#include<sys/socket.h> 257cd002826d0f329620cb738bc4dc4760ef5e084aStephane Ouellette 26e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#ifndef IPT_LIB_DIR 27e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#define IPT_LIB_DIR "/usr/local/lib/iptables" 28e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#endif 29e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte#ifndef __OPTIMIZE__ 310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald WelteSTRUCT_ENTRY_TARGET * 320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald WelteGET_TARGET(STRUCT_ENTRY *e) 330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return (void *)e + e->target_offset; 350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte#endif 370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 38e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int sockfd = -1; 39e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void *iptc_fn = NULL; 40e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 41e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic const char *hooknames[] 4279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell= { [HOOK_PRE_ROUTING] "PREROUTING", 4379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_LOCAL_IN] "INPUT", 4479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_FORWARD] "FORWARD", 4579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_LOCAL_OUT] "OUTPUT", 4610758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell [HOOK_POST_ROUTING] "POSTROUTING", 4710758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell#ifdef HOOK_DROPPING 4810758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell [HOOK_DROPPING] "DROPPING" 4910758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell#endif 50e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 51e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 52e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstruct counter_map 53e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 54e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher enum { 55e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_NOMAP, 56e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_NORMAL_MAP, 571cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte COUNTER_MAP_ZEROED, 581cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte COUNTER_MAP_SET 59e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } maptype; 60e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int mappos; 61e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 62e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 63e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Convenience structures */ 64e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstruct ipt_error_target 65e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 6679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET t; 6779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell char error[TABLE_MAXNAMELEN]; 68e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 69e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 700113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestruct chain_cache 7130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 7279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell char name[TABLE_MAXNAMELEN]; 730113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* This is the first rule in chain. */ 740113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int start_off; 750113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Last rule in chain */ 760113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int end_off; 7730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell}; 7830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 7979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellSTRUCT_TC_HANDLE 80e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 81e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Have changes been made? */ 82e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int changed; 830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Size in here reflects original state. */ 8479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 85e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 860113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct counter_map *counter_map; 87e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Array of hook names */ 88e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char **hooknames; 89e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 9030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Cached position of chain heads (NULL = no cache). */ 9130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int cache_num_chains; 9230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int cache_num_builtins; 9330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *cache_chain_heads; 9430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 9530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Chain iterator: current chain cache entry. */ 9630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *cache_chain_iteration; 9730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 9830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Rule iterator: terminal rule */ 9979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *cache_rule_end; 100175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 101e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Number in here reflects current state. */ 102e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int new_number; 10379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GET_ENTRIES entries; 104e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 105e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 106175f64177743e5a417e98d483ef995bf7151f3bcRusty Russellstatic void 10779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellset_changed(TC_HANDLE_T h) 108175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell{ 109175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell h->changed = 1; 110175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell} 111175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 112380ba5f3074a16fbaa8869d9594962d58b5f8608Harald Welte#ifdef IPTC_DEBUG 11379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic void do_check(TC_HANDLE_T h, unsigned int line); 114849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell#define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0) 11530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#else 11630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#define CHECK(h) 11730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#endif 118e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 119e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 12079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellget_number(const STRUCT_ENTRY *i, 12179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *seek, 122e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int *pos) 123e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 124e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (i == seek) 125e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 126e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*pos)++; 127e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 128e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 129e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 130e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic unsigned int 13179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellentry2index(const TC_HANDLE_T h, const STRUCT_ENTRY *seek) 132e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 133e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int pos = 0; 134e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 135725d97a79cf0b332ed45cb7d254915178328427dRusty Russell if (ENTRY_ITERATE(h->entries.entrytable, h->entries.size, 13679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell get_number, seek, &pos) == 0) { 137e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher fprintf(stderr, "ERROR: offset %i not an entry!\n", 138725d97a79cf0b332ed45cb7d254915178328427dRusty Russell (char *)seek - (char *)h->entries.entrytable); 139e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 140e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 141e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return pos; 142e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 143e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 144e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 14579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellget_entry_n(STRUCT_ENTRY *i, 146e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int number, 147e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int *pos, 14879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY **pe) 149e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 150e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (*pos == number) { 151e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *pe = i; 152e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 153e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 154e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*pos)++; 155e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 156e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 157e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 15879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic STRUCT_ENTRY * 15979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellindex2entry(TC_HANDLE_T h, unsigned int index) 160e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 161e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int pos = 0; 16279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *ret = NULL; 163e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 164725d97a79cf0b332ed45cb7d254915178328427dRusty Russell ENTRY_ITERATE(h->entries.entrytable, h->entries.size, 16579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell get_entry_n, index, &pos, &ret); 166e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 167e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ret; 168e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 169e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1700113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic inline STRUCT_ENTRY * 1710113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welteget_entry(TC_HANDLE_T h, unsigned int offset) 172e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1730113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return (STRUCT_ENTRY *)((char *)h->entries.entrytable + offset); 174e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 175e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1760113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic inline unsigned long 1770113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welteentry2offset(const TC_HANDLE_T h, const STRUCT_ENTRY *e) 178e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1790113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return (void *)e - (void *)h->entries.entrytable; 1800113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 1819e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 1820113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic inline unsigned long 1830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welteindex2offset(TC_HANDLE_T h, unsigned int index) 1840113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 1850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return entry2offset(h, index2entry(h, index)); 186e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 187e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1883ea8f40262386e6b1445a617841f28702fe74d9dHarald Weltestatic inline STRUCT_ENTRY * 1893ea8f40262386e6b1445a617841f28702fe74d9dHarald Welteoffset2entry(TC_HANDLE_T h, unsigned int offset) 1903ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 1913ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte return (STRUCT_ENTRY *) ((void *)h->entries.entrytable+offset); 1923ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 1933ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 1943ea8f40262386e6b1445a617841f28702fe74d9dHarald Weltestatic inline unsigned int 1953ea8f40262386e6b1445a617841f28702fe74d9dHarald Welteoffset2index(const TC_HANDLE_T h, unsigned int offset) 1963ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte{ 1973ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte return entry2index(h, offset2entry(h, offset)); 1983ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte} 1993ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 2003ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 2010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic const char * 2020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welteget_errorlabel(TC_HANDLE_T h, unsigned int offset) 2030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 2040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY *e; 2050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2060113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte e = get_entry(h, offset); 2070113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) != 0) { 2080113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte fprintf(stderr, "ERROR: offset %u not an error node!\n", 2090113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte offset); 2100113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte abort(); 2110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 2120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 2130113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return (const char *)GET_TARGET(e)->data; 2140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 215e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 216e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Allocate handle of given size */ 21779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic TC_HANDLE_T 2180113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltealloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 219e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 220e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher size_t len; 22179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 222e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 22379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell len = sizeof(STRUCT_TC_HANDLE) 224e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher + size 225e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher + num_rules * sizeof(struct counter_map); 226e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 227e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((h = malloc(len)) == NULL) { 228e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 229e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 230e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 231e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 232e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->changed = 0; 2330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_num_chains = 0; 2340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_chain_heads = NULL; 2350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->counter_map = (void *)h 2360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte + sizeof(STRUCT_TC_HANDLE) 2370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte + size; 238e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(h->info.name, tablename); 239e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(h->entries.name, tablename); 240e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 241e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 242e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 243e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 24479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_HANDLE_T 24579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INIT(const char *tablename) 246e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 24779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 24879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 2490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int i; 250e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int tmp; 251e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher socklen_t s; 252e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 25379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INIT; 254e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 255e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson if (sockfd != -1) { 256366454bc69f781fdafc3a30eb6dd77155ee4efb6Harald Welte close(sockfd); 257e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 258e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson } 259366454bc69f781fdafc3a30eb6dd77155ee4efb6Harald Welte 260841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson if (strlen(tablename) >= TABLE_MAXNAMELEN) { 261841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson errno = EINVAL; 262841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson return NULL; 263841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 264841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 26579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 266e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (sockfd < 0) 267e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 268e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 269e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher s = sizeof(info); 270841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 271e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(info.name, tablename); 27279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) 273e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 274e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 2750113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((h = alloc_handle(info.name, info.size, info.num_entries)) 276841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson == NULL) { 277841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson close(sockfd); 278e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 279e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 280841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 281e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 282e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Too hard --RR */ 283e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#if 0 284e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher sprintf(pathname, "%s/%s", IPT_LIB_DIR, info.name); 285e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher dynlib = dlopen(pathname, RTLD_NOW); 286e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!dynlib) { 287e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 288e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 289e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 290e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->hooknames = dlsym(dynlib, "hooknames"); 291e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!h->hooknames) { 292e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 293e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 294e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 295e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#else 296e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->hooknames = hooknames; 297e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#endif 298e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 299e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Initialize current state */ 300e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->info = info; 3010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->new_number = h->info.num_entries; 3020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte for (i = 0; i < h->info.num_entries; i++) 3030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->counter_map[i] 3040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte = ((struct counter_map){COUNTER_MAP_NORMAL_MAP, i}); 3050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 306e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->entries.size = h->info.size; 307e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 30879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 309e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 31079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, &h->entries, 311e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher &tmp) < 0) { 312841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson close(sockfd); 313e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 314e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(h); 315e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 316e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 3177e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 318e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(h); 319e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 320e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 321e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 322841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefssonvoid 323841e4aed2349046eb2c0b1375139c06569a93bd0Martin JosefssonTC_FREE(TC_HANDLE_T *h) 324841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson{ 325841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson close(sockfd); 326e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 3270113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((*h)->cache_chain_heads) 3280113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte free((*h)->cache_chain_heads); 329841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson free(*h); 330841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson *h = NULL; 331841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson} 332841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 333e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 33479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellprint_match(const STRUCT_ENTRY_MATCH *m) 335e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 336228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell printf("Match name: `%s'\n", m->u.user.name); 337e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 338e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 339e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 34079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle); 34179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell 342e6869a8f59d779ff4d5a0984c86d80db7078496Marc Bouchervoid 34379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DUMP_ENTRIES(const TC_HANDLE_T handle) 344e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 345e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(handle); 346e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 347e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("libiptc v%s. %u entries, %u bytes.\n", 34880fe35d6339b53a12ddaec41885613e4e37ed031Harald Welte IPTABLES_VERSION, 349e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher handle->new_number, handle->entries.size); 350e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Table `%s'\n", handle->info.name); 351e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 35267088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_PRE_ROUTING], 35367088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_IN], 35467088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_FORWARD], 35567088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_OUT], 35667088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_POST_ROUTING]); 357e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 35867088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_PRE_ROUTING], 35967088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_IN], 36067088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_FORWARD], 36167088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_OUT], 36267088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_POST_ROUTING]); 363e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 364725d97a79cf0b332ed45cb7d254915178328427dRusty Russell ENTRY_ITERATE(handle->entries.entrytable, handle->entries.size, 36579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell dump_entry, handle); 366e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 367e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 36830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Returns 0 if not hook entry, else hooknumber + 1 */ 36930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellstatic inline unsigned int 37079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellis_hook_entry(STRUCT_ENTRY *e, TC_HANDLE_T h) 37130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 37230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int i; 37330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 37479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell for (i = 0; i < NUMHOOKS; i++) { 37530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if ((h->info.valid_hooks & (1 << i)) 37630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell && get_entry(h, h->info.hook_entry[i]) == e) 37730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return i+1; 37830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell } 37930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return 0; 38030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 38130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 3820113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic inline int 3830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welteadd_chain(STRUCT_ENTRY *e, TC_HANDLE_T h, STRUCT_ENTRY **prev) 3840113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 3850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int builtin; 3860113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 3870113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Last entry. End it. */ 3880113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (entry2offset(h, e) + e->next_offset == h->entries.size) { 3890113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* This is the ERROR node at end of the table */ 3900113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_chain_heads[h->cache_num_chains-1].end_off = 3910113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte entry2offset(h, *prev); 3920113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 3930113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 3940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 3950113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* We know this is the start of a new chain if it's an ERROR 3960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte target, or a hook entry point */ 3970113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) { 3980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* prev was last entry in previous chain */ 3990113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_chain_heads[h->cache_num_chains-1].end_off 4000113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte = entry2offset(h, *prev); 4010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte strcpy(h->cache_chain_heads[h->cache_num_chains].name, 4030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (const char *)GET_TARGET(e)->data); 4040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_chain_heads[h->cache_num_chains].start_off 4050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte = entry2offset(h, (void *)e + e->next_offset); 4060113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_num_chains++; 4070113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } else if ((builtin = is_hook_entry(e, h)) != 0) { 4080113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (h->cache_num_chains > 0) 4090113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* prev was last entry in previous chain */ 4100113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_chain_heads[h->cache_num_chains-1].end_off 4110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte = entry2offset(h, *prev); 4120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4130113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte strcpy(h->cache_chain_heads[h->cache_num_chains].name, 4140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->hooknames[builtin-1]); 4150113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_chain_heads[h->cache_num_chains].start_off 4160113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte = entry2offset(h, (void *)e); 4170113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_num_chains++; 4180113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 4190113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte *prev = e; 4210113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 4220113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 423e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 42430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellstatic int alphasort(const void *a, const void *b) 42530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 42630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return strcmp(((struct chain_cache *)a)->name, 42730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell ((struct chain_cache *)b)->name); 42830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 4290113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic int populate_cache(TC_HANDLE_T h) 4310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 4320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int i; 4330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY *prev; 4340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* # chains < # rules / 2 + num builtins - 1 */ 4360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_chain_heads = malloc((h->new_number / 2 + 4) 4370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * sizeof(struct chain_cache)); 4380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!h->cache_chain_heads) { 4390113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = ENOMEM; 4400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 4410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 4420113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_num_chains = 0; 4440113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_num_builtins = 0; 4450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4460113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Count builtins */ 4470113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte for (i = 0; i < NUMHOOKS; i++) { 4480113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (h->info.valid_hooks & (1 << i)) 4490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_num_builtins++; 4500113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 4510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte prev = NULL; 4530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte ENTRY_ITERATE(h->entries.entrytable, h->entries.size, 4540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte add_chain, h, &prev); 4550113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte qsort(h->cache_chain_heads + h->cache_num_builtins, 4570113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_num_chains - h->cache_num_builtins, 4580113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte sizeof(struct chain_cache), alphasort); 4590113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 1; 4610113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 4620113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4630113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic int 4640113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltecorrect_cache(TC_HANDLE_T h, unsigned int offset, int delta) 4650113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 4660113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte int i; /* needs to be signed because deleting first 4670113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte chain can make it drop to -1 */ 4680113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4690113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!delta) 4700113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 1; 4710113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4720113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte for (i = 0; i < h->cache_num_chains; i++) { 4730113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *cc = &h->cache_chain_heads[i]; 4740113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4750113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (delta < 0) { 4760113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* take care about deleted chains */ 4770113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (cc->start_off > offset+delta 4780113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte && cc->end_off < offset) { 4790113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* this chain is within the deleted range, 4800113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * let's remove it from the cache */ 4810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte void *start; 4820113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int size; 4830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4840113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_num_chains--; 4850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4860113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* no need for memmove since we are 4870113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * removing the last entry */ 4880113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (i >= h->cache_num_chains) 4890113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte continue; 4900113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4910113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte start = &h->cache_chain_heads[i+1]; 4920113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte size = (h->cache_num_chains-i) 4930113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * sizeof(struct chain_cache); 4940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memmove(cc, start, size); 4950113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 4960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* iterate over same index again, since 4970113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * it is now a different chain */ 4980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte i--; 4990113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte continue; 5000113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 5010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 5020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (cc->start_off > offset) 5040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte cc->start_off += delta; 5050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5060113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (cc->end_off >= offset) 5070113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte cc->end_off += delta; 5080113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 5090113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* HW_FIXME: sorting might be needed, but just in case a new chain was 5100113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * added */ 5110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 1; 5130113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 5140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5150113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic int 5160113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welteadd_chain_cache(TC_HANDLE_T h, const char *name, unsigned int start_off, 5170113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int end_off) 5180113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 5190113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *ccs = realloc(h->cache_chain_heads, 5200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (h->new_number / 2 + 4 + 1) 5210113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * sizeof(struct chain_cache)); 5220113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *newcc; 5230113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5240113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!ccs) 5250113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 5260113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5270113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_chain_heads = ccs; 5280113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newcc = &h->cache_chain_heads[h->cache_num_chains]; 5290113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte h->cache_num_chains++; 5300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte strncpy(newcc->name, name, TABLE_MAXNAMELEN-1); 532073df8feb0a8c4023ce40138e519ac9b341b1ca2Karsten Desler newcc->name[TABLE_MAXNAMELEN-1] = '\0'; 5330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newcc->start_off = start_off; 5340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newcc->end_off = end_off; 5350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 1; 5370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 5380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5390113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Returns cache ptr if found, otherwise NULL. */ 5400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic struct chain_cache * 5410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltefind_label(const char *name, TC_HANDLE_T handle) 5420113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 5430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int i; 5440113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (handle->cache_chain_heads == NULL 5460113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte && !populate_cache(handle)) 5470113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 5480113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* FIXME: Linear search through builtins, then binary --RR */ 5500113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte for (i = 0; i < handle->cache_num_chains; i++) { 5510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (strcmp(handle->cache_chain_heads[i].name, name) == 0) 5520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return &handle->cache_chain_heads[i]; 5530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 5540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 5550113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 5560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 557e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 558e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Does this chain exist? */ 55979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle) 560e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 56130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return find_label(chain, handle) != NULL; 562e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 563e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 564e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Returns the position of the final (ie. unconditional) element. */ 565e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic unsigned int 56679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellget_chain_end(const TC_HANDLE_T handle, unsigned int start) 567e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 568e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int last_off, off; 56979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e; 570e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 571e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher last_off = start; 572e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e = get_entry(handle, start); 573e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 574e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Terminate when we meet a error label or a hook entry. */ 575e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (off = start + e->next_offset; 576e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher off < handle->entries.size; 577e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher last_off = off, off += e->next_offset) { 57879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET *t; 579e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 580e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 581e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e = get_entry(handle, off); 582e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 583e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* We hit an entry point. */ 58479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell for (i = 0; i < NUMHOOKS; i++) { 585e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((handle->info.valid_hooks & (1 << i)) 586e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && off == handle->info.hook_entry[i]) 587e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return last_off; 588e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 589e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 590e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* We hit a user chain label */ 59179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = GET_TARGET(e); 59267088e73ce7707229c56987868f112051defca5aRusty Russell if (strcmp(t->u.user.name, ERROR_TARGET) == 0) 593e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return last_off; 594e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 595e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* SHOULD NEVER HAPPEN */ 596e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher fprintf(stderr, "ERROR: Off end (%u) of chain from %u!\n", 597e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher handle->entries.size, off); 598e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 599e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 600e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 60130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. */ 602e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 6038c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_CHAIN(TC_HANDLE_T *handle) 604e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 6050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((*handle)->cache_chain_heads == NULL 6060113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte && !populate_cache(*handle)) 6070113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 6080113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 6090113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->cache_chain_iteration 6100113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte = &(*handle)->cache_chain_heads[0]; 61130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 6120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return (*handle)->cache_chain_iteration->name; 61330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 61430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 61530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. Returns NULL at end. */ 61630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellconst char * 61779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NEXT_CHAIN(TC_HANDLE_T *handle) 61830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 6190113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->cache_chain_iteration++; 62030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 6210113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((*handle)->cache_chain_iteration - (*handle)->cache_chain_heads 6220113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte == (*handle)->cache_num_chains) 62330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 62430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 6250113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return (*handle)->cache_chain_iteration->name; 62630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 62730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 62830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Get first rule in the given chain: NULL for empty chain. */ 62979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 6308c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_RULE(const char *chain, TC_HANDLE_T *handle) 63130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 6320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 63330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 63430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell c = find_label(chain, *handle); 63530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!c) { 63630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell errno = ENOENT; 63730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 638e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 639e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 64030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Empty chain: single return/policy rule */ 6410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (c->start_off == c->end_off) 64230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 64330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 6440113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->cache_rule_end = offset2entry(*handle, c->end_off); 6450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return offset2entry(*handle, c->start_off); 646e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 647e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 64830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Returns NULL when rules run out. */ 64979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 6508c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle) 65130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 6520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((void *)prev + prev->next_offset 6530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte == (void *)(*handle)->cache_rule_end) 65430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 65530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 6560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return (void *)prev + prev->next_offset; 65730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 65830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 65930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#if 0 660e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* How many rules in this chain? */ 661e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherunsigned int 66279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NUM_RULES(const char *chain, TC_HANDLE_T *handle) 663e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 664e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int off = 0; 66579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *start, *end; 666e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 667e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 668e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!find_label(&off, chain, *handle)) { 669e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 670e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return (unsigned int)-1; 671e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 672e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 673e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher start = get_entry(*handle, off); 674e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher end = get_entry(*handle, get_chain_end(*handle, off)); 675e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 676e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return entry2index(*handle, end) - entry2index(*handle, start); 677e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 678e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 679e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get n'th rule in this chain. */ 68079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY *TC_GET_RULE(const char *chain, 68179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int n, 68279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 683e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 684e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int pos = 0, chainindex; 685e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 686e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 687e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!find_label(&pos, chain, *handle)) { 688e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 689e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 690e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 691e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 692e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher chainindex = entry2index(*handle, get_entry(*handle, pos)); 693e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 694e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return index2entry(*handle, chainindex + n); 695e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 69630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#endif 697e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 69830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellstatic const char * 69979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russelltarget_name(TC_HANDLE_T handle, const STRUCT_ENTRY *ce) 700e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 701e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int spos; 7020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int labelidx; 7030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY *jumpto; 704e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 70530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* To avoid const warnings */ 70679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 70730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 70879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET) != 0) 70979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return GET_TARGET(e)->u.user.name; 710e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 711e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Standard target: evaluate */ 71279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell spos = *(int *)GET_TARGET(e)->data; 713e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (spos < 0) { 71479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (spos == RETURN) 71579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_RETURN; 716e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else if (spos == -NF_ACCEPT-1) 71779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_ACCEPT; 718e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else if (spos == -NF_DROP-1) 71979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_DROP; 7202f4e5d92c73906e0dc2ae42fee5c05740528e92bJames Morris else if (spos == -NF_QUEUE-1) 72167088e73ce7707229c56987868f112051defca5aRusty Russell return LABEL_QUEUE; 722e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 7230113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte fprintf(stderr, "ERROR: off %lu/%u not a valid target (%i)\n", 7240113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte entry2offset(handle, e), handle->entries.size, 7250113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte spos); 726e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 727e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 728e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 7290113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte jumpto = get_entry(handle, spos); 730e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 731e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Fall through rule */ 732e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (jumpto == (void *)e + e->next_offset) 733e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ""; 734e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 735e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Must point to head of a chain: ie. after error rule */ 736e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher labelidx = entry2index(handle, jumpto) - 1; 737e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return get_errorlabel(handle, index2offset(handle, labelidx)); 738e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 739e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 740e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Returns a pointer to the target name of this position. */ 74179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst char *TC_GET_TARGET(const STRUCT_ENTRY *e, 74279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 743e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 744e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return target_name(*handle, e); 745e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 746e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 747e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Is this a built-in chain? Actually returns hook + 1. */ 748e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 74979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_BUILTIN(const char *chain, const TC_HANDLE_T handle) 750e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 751e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 752e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 75379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell for (i = 0; i < NUMHOOKS; i++) { 754e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((handle->info.valid_hooks & (1 << i)) 755e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && handle->hooknames[i] 756e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && strcmp(handle->hooknames[i], chain) == 0) 757e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return i+1; 758e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 759e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 760e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 761e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 762e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get the policy of a given built-in chain */ 763e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 76479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_POLICY(const char *chain, 76579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_COUNTERS *counters, 76679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 767e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 7680113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int start; 76979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e; 770e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int hook; 771e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 77279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell hook = TC_BUILTIN(chain, *handle); 7730113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (hook != 0) 7740113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte start = (*handle)->info.hook_entry[hook-1]; 7750113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte else 7769e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte return NULL; 7779e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 7780113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte e = get_entry(*handle, get_chain_end(*handle, start)); 779e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *counters = e->counters; 780e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 781e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return target_name(*handle, e); 782e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 783e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 7840113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic inline int 78579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellcorrect_verdict(STRUCT_ENTRY *e, 786725d97a79cf0b332ed45cb7d254915178328427dRusty Russell char *base, 787e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int offset, int delta_offset) 788e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 78979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t = (void *)GET_TARGET(e); 790725d97a79cf0b332ed45cb7d254915178328427dRusty Russell unsigned int curr = (char *)e - base; 791e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 792e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Trap: insert of fall-through rule. Don't change fall-through 793e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher verdict to jump-over-next-rule. */ 79479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(t->target.u.user.name, STANDARD_TARGET) == 0 795e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && t->verdict > (int)offset 796e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && !(curr == offset && 797e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict == curr + e->next_offset)) { 798e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict += delta_offset; 799e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 800e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 801e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 802e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 803e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 804e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Adjusts standard verdict jump positions after an insertion/deletion. */ 805e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 80679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellset_verdict(unsigned int offset, int delta_offset, TC_HANDLE_T *handle) 807e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 808725d97a79cf0b332ed45cb7d254915178328427dRusty Russell ENTRY_ITERATE((*handle)->entries.entrytable, 80979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell (*handle)->entries.size, 810725d97a79cf0b332ed45cb7d254915178328427dRusty Russell correct_verdict, (char *)(*handle)->entries.entrytable, 81179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell offset, delta_offset); 812e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 813175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 814e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 815e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 816e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 8170113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* If prepend is set, then we are prepending to a chain: if the 8180113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * insertion position is an entry point, keep the entry point. */ 8190113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic int 8200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welteinsert_rules(unsigned int num_rules, unsigned int rules_size, 8210113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte const STRUCT_ENTRY *insert, 8220113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int offset, unsigned int num_rules_offset, 8230113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte int prepend, 8240113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte TC_HANDLE_T *handle) 8250113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 8260113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte TC_HANDLE_T newh; 8270113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_GETINFO newinfo; 8280113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int i; 8290113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 8300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (offset >= (*handle)->entries.size) { 8310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = EINVAL; 8320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 8330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 8340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 8350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newinfo = (*handle)->info; 8360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 8370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Fix up entry points. */ 8380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte for (i = 0; i < NUMHOOKS; i++) { 8390113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Entry points to START of chain, so keep same if 8400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte inserting on at that point. */ 8410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((*handle)->info.hook_entry[i] > offset) 8420113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newinfo.hook_entry[i] += rules_size; 8430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 8440113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Underflow always points to END of chain (policy), 8450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte so if something is inserted at same point, it 8460113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte should be advanced. */ 8470113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((*handle)->info.underflow[i] >= offset) 8480113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newinfo.underflow[i] += rules_size; 8490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 8500113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 8510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newh = alloc_handle((*handle)->info.name, 8520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->entries.size + rules_size, 8530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->new_number + num_rules); 8540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!newh) 8550113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 8560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newh->info = newinfo; 8570113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 8580113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Copy pre... */ 8590113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(newh->entries.entrytable, (*handle)->entries.entrytable,offset); 8600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* ... Insert new ... */ 8610113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy((char *)newh->entries.entrytable + offset, insert, rules_size); 8620113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* ... copy post */ 8630113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy((char *)newh->entries.entrytable + offset + rules_size, 8640113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (char *)(*handle)->entries.entrytable + offset, 8650113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->entries.size - offset); 8660113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 8670113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Move counter map. */ 8680113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Copy pre... */ 8690113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(newh->counter_map, (*handle)->counter_map, 8700113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte sizeof(struct counter_map) * num_rules_offset); 8710113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* ... copy post */ 8720113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(newh->counter_map + num_rules_offset + num_rules, 8730113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->counter_map + num_rules_offset, 8740113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte sizeof(struct counter_map) * ((*handle)->new_number 8750113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte - num_rules_offset)); 8760113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Set intermediates to no counter copy */ 8770113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte for (i = 0; i < num_rules; i++) 8780113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newh->counter_map[num_rules_offset+i] 8790113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte = ((struct counter_map){ COUNTER_MAP_SET, 0 }); 8800113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 8810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newh->new_number = (*handle)->new_number + num_rules; 8820113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newh->entries.size = (*handle)->entries.size + rules_size; 8830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newh->hooknames = (*handle)->hooknames; 8840113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 8850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newh->cache_chain_heads = (*handle)->cache_chain_heads; 8860113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newh->cache_num_builtins = (*handle)->cache_num_builtins; 8870113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newh->cache_num_chains = (*handle)->cache_num_chains; 8880113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newh->cache_rule_end = (*handle)->cache_rule_end; 8890113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newh->cache_chain_iteration = (*handle)->cache_chain_iteration; 8900113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!correct_cache(newh, offset, rules_size)) { 8910113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte free(newh); 8920113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 8930113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 8940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 8950113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte free(*handle); 8960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte *handle = newh; 8970113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 8980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return set_verdict(offset, rules_size, handle); 8990113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 9000113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 9010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltestatic int 9020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltedelete_rules(unsigned int num_rules, unsigned int rules_size, 9030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int offset, unsigned int num_rules_offset, 9040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte TC_HANDLE_T *handle) 9050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 9060113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int i; 9070113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 9080113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (offset + rules_size > (*handle)->entries.size) { 9090113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = EINVAL; 9100113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 9110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 912fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte 9130113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Fix up entry points. */ 9140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte for (i = 0; i < NUMHOOKS; i++) { 9150113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* In practice, we never delete up to a hook entry, 9160113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte since the built-in chains are always first, 9170113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte so these two are never equal */ 9180113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((*handle)->info.hook_entry[i] >= offset + rules_size) 9190113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->info.hook_entry[i] -= rules_size; 9200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte else if ((*handle)->info.hook_entry[i] > offset) { 9210113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte fprintf(stderr, "ERROR: Deleting entry %u %u %u\n", 9220113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte i, (*handle)->info.hook_entry[i], offset); 9230113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte abort(); 9240113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 9250113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 9260113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Underflow points to policy (terminal) rule in 9270113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte built-in, so sequality is valid here (when deleting 9280113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte the last rule). */ 9290113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((*handle)->info.underflow[i] >= offset + rules_size) 9300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->info.underflow[i] -= rules_size; 9310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte else if ((*handle)->info.underflow[i] > offset) { 9320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte fprintf(stderr, "ERROR: Deleting uflow %u %u %u\n", 9330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte i, (*handle)->info.underflow[i], offset); 9340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte abort(); 9350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 9360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 9370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 9380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Move the rules down. */ 9390113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memmove((char *)(*handle)->entries.entrytable + offset, 9400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (char *)(*handle)->entries.entrytable + offset + rules_size, 9410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->entries.size - (offset + rules_size)); 9420113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 9430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Move the counter map down. */ 9440113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memmove(&(*handle)->counter_map[num_rules_offset], 9450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte &(*handle)->counter_map[num_rules_offset + num_rules], 9460113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte sizeof(struct counter_map) 9470113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * ((*handle)->new_number - (num_rules + num_rules_offset))); 9480113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 9490113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Fix numbers */ 9500113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->new_number -= num_rules; 9510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->entries.size -= rules_size; 9520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 9530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Fix the chain cache */ 9540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!correct_cache(*handle, offset+rules_size, -(int)rules_size)) 9550113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 9560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 9570113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return set_verdict(offset, -(int)rules_size, handle); 9580113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte} 959e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 960e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 96179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstandard_map(STRUCT_ENTRY *e, int verdict) 962e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 96379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 964e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 96579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 966e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 96767088e73ce7707229c56987868f112051defca5aRusty Russell if (t->target.u.target_size 9688c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 969e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 970e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 971e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 972e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset for memcmp convenience on delete/replace */ 97379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 97479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell strcpy(t->target.u.user.name, STANDARD_TARGET); 975e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = verdict; 976e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 977e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 978e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 9797e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 980e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 98179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellmap_target(const TC_HANDLE_T handle, 98279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e, 983e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int offset, 98479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET *old) 985e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 9860113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 987e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 988e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Save old target (except data, which we don't change, except for 989e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher standard case, where we don't care). */ 990e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *old = *t; 991e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 992e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's empty (=> fall through) */ 993228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (strcmp(t->u.user.name, "") == 0) 994e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return standard_map(e, offset + e->next_offset); 995e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's a standard target name... */ 99679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 997e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return standard_map(e, -NF_ACCEPT - 1); 99879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 999e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return standard_map(e, -NF_DROP - 1); 100067088e73ce7707229c56987868f112051defca5aRusty Russell else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 1001e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return standard_map(e, -NF_QUEUE - 1); 100279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 100379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return standard_map(e, RETURN); 100479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (TC_BUILTIN(t->u.user.name, handle)) { 1005e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Can't jump to builtins. */ 1006e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1007e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1008e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 1009e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's an existing chain name. */ 10100113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 1011e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1012228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell c = find_label(t->u.user.name, handle); 101330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (c) 10143ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte return standard_map(e, c->start_off); 1015e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1016e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1017e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Must be a module? If not, kernel will reject... */ 1018e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset to all 0 for your memcmp convenience. */ 1019228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell memset(t->u.user.name + strlen(t->u.user.name), 1020e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 0, 102179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell FUNCTION_MAXNAMELEN - strlen(t->u.user.name)); 1022e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1023e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1024e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1025e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 102679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellunmap_target(STRUCT_ENTRY *e, STRUCT_ENTRY_TARGET *old) 1027e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 102879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 1029e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1030e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Save old target (except data, which we don't change, except for 1031e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher standard case, where we don't care). */ 1032e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *t = *old; 1033e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1034e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 10350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 1036e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 103779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 103879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 103979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 104079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1041e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 10420113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int chainindex, offset; 10430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY_TARGET old; 10440113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 10450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY *tmp; 10460113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte int ret; 1047e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 104879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INSERT_ENTRY; 104930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1050e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1051e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1052e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1053e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 10540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte chainindex = offset2index(*handle, c->start_off); 10550113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 10560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte tmp = index2entry(*handle, chainindex + rulenum); 10570113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!tmp || tmp > offset2entry(*handle, c->end_off)) { 1058e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1059e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1060e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 10610113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte offset = index2offset(*handle, chainindex + rulenum); 1062e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 10630113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Mapping target actually alters entry, but that's 10640113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte transparent to the caller. */ 10650113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!map_target(*handle, (STRUCT_ENTRY *)e, offset, &old)) 10660113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1067e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 10680113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte ret = insert_rules(1, e->next_offset, e, offset, 10690113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte chainindex + rulenum, rulenum == 0, handle); 10700113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unmap_target((STRUCT_ENTRY *)e, &old); 10710113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return ret; 1072e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1073e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1074e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 1075e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 107679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 107779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 107879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 107979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1080e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 10810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int chainindex, offset; 10820113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY_TARGET old; 10830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 10840113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY *tmp; 10850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte int ret; 1086e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 108779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_REPLACE_ENTRY; 1088e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 108930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1090e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1091e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1092e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1093e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 10940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte chainindex = offset2index(*handle, c->start_off); 10950113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 10960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte tmp = index2entry(*handle, chainindex + rulenum); 10970113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!tmp || tmp >= offset2entry(*handle, c->end_off)) { 1098e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1099e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1100e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1101e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 11020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte offset = index2offset(*handle, chainindex + rulenum); 11030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Replace = delete and insert. */ 11040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!delete_rules(1, get_entry(*handle, offset)->next_offset, 11050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte offset, chainindex + rulenum, handle)) 1106e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1107e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 11080113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!map_target(*handle, (STRUCT_ENTRY *)e, offset, &old)) 11090113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 11100113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 11110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte ret = insert_rules(1, e->next_offset, e, offset, 11120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte chainindex + rulenum, 1, handle); 11130113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unmap_target((STRUCT_ENTRY *)e, &old); 11140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return ret; 1115e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1116e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 11170113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Append entry `fw' to chain `chain'. Equivalent to insert with 1118e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher rulenum = length of chain. */ 1119e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 112079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 112179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 112279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1123e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 11240113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 11250113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY_TARGET old; 11260113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte int ret; 1127e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 112879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_APPEND_ENTRY; 112930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1130e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1131e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1132e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1133e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 11340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!map_target(*handle, (STRUCT_ENTRY *)e, 11350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte c->end_off, &old)) 11360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 11370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 11380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte ret = insert_rules(1, e->next_offset, e, c->end_off, 11390113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte offset2index(*handle, c->end_off), 0, handle); 11400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unmap_target((STRUCT_ENTRY *)e, &old); 11410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return ret; 1142e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1143e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1144e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 114579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellmatch_different(const STRUCT_ENTRY_MATCH *a, 1146edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *a_elems, 1147edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_elems, 1148edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned char **maskptr) 1149e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 115079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY_MATCH *b; 1151edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1152e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1153e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Offset of b is the same as a. */ 115430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell b = (void *)b_elems + ((unsigned char *)a - a_elems); 1155e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1156228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (a->u.match_size != b->u.match_size) 1157e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1158e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1159228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (strcmp(a->u.user.name, b->u.user.name) != 0) 1160e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1161e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 116273ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell *maskptr += ALIGN(sizeof(*a)); 1163edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 116473ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1165edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1166edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 1; 1167edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell *maskptr += i; 1168edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 0; 1169edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell} 1170edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 1171edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russellstatic inline int 1172edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russelltarget_different(const unsigned char *a_targdata, 1173edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_targdata, 1174edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int tdatasize, 1175edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *mask) 1176edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell{ 1177edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1178edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell for (i = 0; i < tdatasize; i++) 1179edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a_targdata[i] ^ b_targdata[i]) & mask[i]) != 0) 118090e712a00913fe2a2f885142439c392392dc08a8Rusty Russell return 1; 1181e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1182e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1183e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1184e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 118579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic int 118679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellis_same(const STRUCT_ENTRY *a, 118779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *b, 118879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask); 1189e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 11900113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte/* Delete the first rule in `chain' which matches `fw'. */ 1191e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 119279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_ENTRY(const IPT_CHAINLABEL chain, 119379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *origfw, 119479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask, 119579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1196e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 11970113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int offset; 11980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 11990113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY *e, *fw; 1200e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 120179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_ENTRY; 120230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1203e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1204e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1205e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1206e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 12070113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte fw = malloc(origfw->next_offset); 12080113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (fw == NULL) { 12090113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = ENOMEM; 12100113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 12110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 12120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 12130113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte for (offset = c->start_off; offset < c->end_off; 12140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte offset += e->next_offset) { 12150113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY_TARGET discard; 12160113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 12170113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(fw, origfw, origfw->next_offset); 12180113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 12190113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* FIXME: handle this in is_same --RR */ 12200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!map_target(*handle, fw, offset, &discard)) { 12210113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte free(fw); 12220113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 12230113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 12240113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte e = get_entry(*handle, offset); 12250113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 12260113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte#if 0 12270113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte printf("Deleting:\n"); 12280113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte dump_entry(newe); 12290113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte#endif 12300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (is_same(e, fw, matchmask)) { 12310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte int ret; 12320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte ret = delete_rules(1, e->next_offset, 12330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte offset, entry2index(*handle, e), 12340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte handle); 12350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte free(fw); 12360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return ret; 1237e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1238e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1239e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 12400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte free(fw); 1241e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1242e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 12437e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell} 1244e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1245e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Delete the rule in position `rulenum' in `chain'. */ 1246e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 124779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 124879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 124979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1250e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 12510113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int index; 12520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte int ret; 12530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY *e; 12540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 1255e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 125679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_NUM_ENTRY; 12570113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!(c = find_label(chain, *handle))) { 1258e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1259e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1260e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1261e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 12620113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte index = offset2index(*handle, c->start_off) + rulenum; 12630113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 12640113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (index >= offset2index(*handle, c->end_off)) { 1265e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1266e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1267e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1268e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 12690113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte e = index2entry(*handle, index); 12700113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (e == NULL) { 12710113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = EINVAL; 12720113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 12730113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 1274e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 12750113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte ret = delete_rules(1, e->next_offset, entry2offset(*handle, e), 12760113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte index, handle); 12770113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return ret; 1278e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1279e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1280e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Check the packet `fw' on chain `chain'. Returns the verdict, or 1281e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher NULL and sets errno. */ 1282e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 128379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CHECK_PACKET(const IPT_CHAINLABEL chain, 128479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *entry, 128579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1286e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1287e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOSYS; 1288e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1289e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1290e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1291e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Flushes the entries in the given chain (ie. empties chain). */ 1292e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 129379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1294e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 12950113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int startindex, endindex; 12960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY *startentry, *endentry; 12970113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 12980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte int ret; 1299e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13000113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte iptc_fn = TC_FLUSH_ENTRIES; 13010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!(c = find_label(chain, *handle))) { 1302e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1303e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1304e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 13050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte startindex = offset2index(*handle, c->start_off); 13060113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte endindex = offset2index(*handle, c->end_off); 13070113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte startentry = offset2entry(*handle, c->start_off); 13080113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte endentry = offset2entry(*handle, c->end_off); 1309e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13100113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte ret = delete_rules(endindex - startindex, 13110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (char *)endentry - (char *)startentry, 13120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte c->start_off, startindex, 13130113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte handle); 13140113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return ret; 1315e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1316e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1317e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Zeroes the counters in a chain. */ 1318e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 131979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1320e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 13210113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int i, end; 13220113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 13237e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 132430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1325e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1326e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1327e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1328e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13290113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte i = offset2index(*handle, c->start_off); 13300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte end = offset2index(*handle, c->end_off); 13310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 13320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte for (; i <= end; i++) { 13330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((*handle)->counter_map[i].maptype ==COUNTER_MAP_NORMAL_MAP) 13340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->counter_map[i].maptype = COUNTER_MAP_ZEROED; 1335e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1336175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1337e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1338e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1339e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1340e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 13411cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteSTRUCT_COUNTERS * 13421cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_READ_COUNTER(const IPT_CHAINLABEL chain, 13431cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 13441cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 13451cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 13461cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 13470113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 13480113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int chainindex, end; 13491cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13501cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_READ_COUNTER; 13511cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 13521cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!(c = find_label(chain, *handle))) { 13541cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 13551cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return NULL; 13561cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 13571cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13580113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte chainindex = offset2index(*handle, c->start_off); 13590113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte end = offset2index(*handle, c->end_off); 13600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 13610113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (chainindex + rulenum > end) { 13620113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 13630113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return NULL; 13640113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 13650113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 13660113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte e = index2entry(*handle, chainindex + rulenum); 13670113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 13680113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return &e->counters; 13691cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 13701cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13711cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 13721cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 13731cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 13741cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 13751cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 13761cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 13770113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 13780113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int chainindex, end; 13791cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13801cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_ZERO_COUNTER; 13811cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 13821cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!(c = find_label(chain, *handle))) { 13841cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 13851cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 13861cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 13871cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13880113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte chainindex = offset2index(*handle, c->start_off); 13890113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte end = offset2index(*handle, c->end_off); 13900113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 13910113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (chainindex + rulenum > end) { 13920113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 13930113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 13940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 13950113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 13960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte e = index2entry(*handle, chainindex + rulenum); 13970113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 13980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if ((*handle)->counter_map[chainindex + rulenum].maptype 13990113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte == COUNTER_MAP_NORMAL_MAP) { 14000113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->counter_map[chainindex + rulenum].maptype 14010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte = COUNTER_MAP_ZEROED; 14020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 14031cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 14041cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 14051cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 14061cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 14071cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 14081cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 14091cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 14101cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_SET_COUNTER(const IPT_CHAINLABEL chain, 14111cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 14121cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 14131cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 14141cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 14151cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 14160113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 14170113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int chainindex, end; 14181cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 14191cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_SET_COUNTER; 14201cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 14211cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 14220113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!(c = find_label(chain, *handle))) { 14231cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 14241cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 14251cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 14260113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 14270113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte chainindex = offset2index(*handle, c->start_off); 14280113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte end = offset2index(*handle, c->end_off); 14290113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 14300113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (chainindex + rulenum > end) { 14310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte errno = E2BIG; 14320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 14330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } 14340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 14350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte e = index2entry(*handle, chainindex + rulenum); 14360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 14370113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->counter_map[chainindex + rulenum].maptype 14380113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte = COUNTER_MAP_SET; 14390113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 14400113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 14411cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 14421cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 14431cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 14441cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 14451cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 14461cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1447e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Creates a new chain. */ 1448e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* To create a chain, create two rules: error node and unconditional 1449e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * return. */ 1450e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 145179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1452e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1453e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int ret; 14540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct { 145579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY head; 1456e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_error_target name; 145779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY ret; 145879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET target; 14590113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte } newc; 14600113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int destination; 1461e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 146279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_CREATE_CHAIN; 1463e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1464e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* find_label doesn't cover built-in targets: DROP, ACCEPT, 1465e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher QUEUE, RETURN. */ 146630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (find_label(chain, *handle) 146779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_DROP) == 0 146879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_ACCEPT) == 0 146967088e73ce7707229c56987868f112051defca5aRusty Russell || strcmp(chain, LABEL_QUEUE) == 0 147079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_RETURN) == 0) { 1471e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1472e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1473e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1474e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 147579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 1476e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1477e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1478e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1479e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 14800113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memset(&newc, 0, sizeof(newc)); 14810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newc.head.target_offset = sizeof(STRUCT_ENTRY); 14820113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newc.head.next_offset 148367088e73ce7707229c56987868f112051defca5aRusty Russell = sizeof(STRUCT_ENTRY) 14848c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell + ALIGN(sizeof(struct ipt_error_target)); 14850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte strcpy(newc.name.t.u.user.name, ERROR_TARGET); 14860113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newc.name.t.u.target_size = ALIGN(sizeof(struct ipt_error_target)); 14870113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte strcpy(newc.name.error, chain); 1488e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 14890113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newc.ret.target_offset = sizeof(STRUCT_ENTRY); 14900113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newc.ret.next_offset 149167088e73ce7707229c56987868f112051defca5aRusty Russell = sizeof(STRUCT_ENTRY) 14928c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell + ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 14930113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte strcpy(newc.target.target.u.user.name, STANDARD_TARGET); 14940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newc.target.target.u.target_size 14958c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell = ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 14960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte newc.target.verdict = RETURN; 1497fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte 14980113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte destination = index2offset(*handle, (*handle)->new_number -1); 1499fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte 15000113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Add just before terminal entry */ 15010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte ret = insert_rules(2, sizeof(newc), &newc.head, 15020113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte destination, 15030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->new_number - 1, 15040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 0, handle); 15050113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 15060113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte set_changed(*handle); 15070113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 15080113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* add chain cache info for this chain */ 15090113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte add_chain_cache(*handle, chain, 15100113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte destination+newc.head.next_offset, 15110113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte destination+newc.head.next_offset); 15120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 15130113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return ret; 1514e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1515e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1516e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 151779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellcount_ref(STRUCT_ENTRY *e, unsigned int offset, unsigned int *ref) 1518e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 151979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 1520e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 152179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET) == 0) { 152279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1523e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1524e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (t->verdict == offset) 1525e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*ref)++; 1526e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1527e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1528e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1529e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1530e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1531e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get the number of references to this chain. */ 1532e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 153379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 153479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1535e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 153630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 1537e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 153830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1539e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1540e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1541e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1542e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1543e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *ref = 0; 1544725d97a79cf0b332ed45cb7d254915178328427dRusty Russell ENTRY_ITERATE((*handle)->entries.entrytable, 154579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell (*handle)->entries.size, 15463ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte count_ref, c->start_off, ref); 1547e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1548e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1549e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1550e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Deletes a chain. */ 1551e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 155279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1553e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 15540113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int labelidx, labeloff; 1555e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int references; 15560113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 15570113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte int ret; 15580113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte STRUCT_ENTRY *start; 1559e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 156079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (!TC_GET_REFERENCES(&references, chain, handle)) 1561e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 15627e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 156379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_CHAIN; 1564e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 156579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (TC_BUILTIN(chain, *handle)) { 1566e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1567e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1568e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1569e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1570e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (references > 0) { 1571e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EMLINK; 1572e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1573e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1574e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 15750113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (!(c = find_label(chain, *handle))) { 1576e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1577e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1578e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1579e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 15800113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (c->start_off != c->end_off) { 1581e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOTEMPTY; 1582e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1583e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1584e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 15850113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Need label index: preceeds chain start */ 15860113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte labelidx = offset2index(*handle, c->start_off) - 1; 15870113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte labeloff = index2offset(*handle, labelidx); 15880113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 15890113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte start = offset2entry(*handle, c->start_off); 15900113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 15910113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte ret = delete_rules(2, 15920113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte get_entry(*handle, labeloff)->next_offset 15930113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte + start->next_offset, 15940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte labeloff, labelidx, handle); 15950113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return ret; 1596e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1597e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1598e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Renames a chain. */ 159979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 160079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL newname, 160179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1602e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 16030113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int labeloff, labelidx; 16040113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct chain_cache *c; 1605e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_error_target *t; 1606e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 160779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_RENAME_CHAIN; 1608e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 16091de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte /* find_label doesn't cover built-in targets: DROP, ACCEPT, 16101de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte QUEUE, RETURN. */ 161130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (find_label(newname, *handle) 161279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_DROP) == 0 161379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_ACCEPT) == 0 16141de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte || strcmp(newname, LABEL_QUEUE) == 0 161579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_RETURN) == 0) { 1616e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1617e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1618e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1619e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 162030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(oldname, *handle)) 162179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || TC_BUILTIN(oldname, *handle)) { 1622e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1623e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1624e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1625e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 162679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 1627e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1628e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1629e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1630e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 16310113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* Need label index: preceeds chain start */ 16320113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte labelidx = offset2index(*handle, c->start_off) - 1; 16330113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte labeloff = index2offset(*handle, labelidx); 1634e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1635e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t = (struct ipt_error_target *) 16360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte GET_TARGET(get_entry(*handle, labeloff)); 1637e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1638e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memset(t->error, 0, sizeof(t->error)); 1639e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(t->error, newname); 1640fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte 16410113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte /* update chain cache */ 16420113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte memset(c->name, 0, sizeof(c->name)); 16430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte strcpy(c->name, newname); 16440113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 16450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte set_changed(*handle); 16460113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1647e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1648e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1649e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1650e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Sets the policy on a built-in chain. */ 1651e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 165279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_SET_POLICY(const IPT_CHAINLABEL chain, 165379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL policy, 16541cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 165579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1656e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1657e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int hook; 16580113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte unsigned int policyoff, ctrindex; 165979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e; 166079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 1661e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 166279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_SET_POLICY; 1663e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Figure out which chain. */ 166479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell hook = TC_BUILTIN(chain, *handle); 1665e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (hook == 0) { 1666c8264991454b5e77279830736f80ea3153b6f814Marc Boucher errno = ENOENT; 1667e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1668e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else 1669e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher hook--; 1670e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 16710113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte policyoff = get_chain_end(*handle, (*handle)->info.hook_entry[hook]); 16720113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte if (policyoff != (*handle)->info.underflow[hook]) { 16730113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte printf("ERROR: Policy for `%s' offset %u != underflow %u\n", 16740113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte chain, policyoff, (*handle)->info.underflow[hook]); 16759e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte return 0; 16769e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte } 16779e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte 16780113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte e = get_entry(*handle, policyoff); 16790113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1680e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 168179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(policy, LABEL_ACCEPT) == 0) 1682e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = -NF_ACCEPT - 1; 168379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(policy, LABEL_DROP) == 0) 1684e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = -NF_DROP - 1; 1685e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else { 1686e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1687e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1688e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 16891cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16901cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte ctrindex = entry2index(*handle, e); 16911cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16921cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (counters) { 16931cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte /* set byte and packet counters */ 16941cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 16951cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->counter_map[ctrindex].maptype 16970113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte = COUNTER_MAP_SET; 16981cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16991cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } else { 17000113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte (*handle)->counter_map[ctrindex] 17010113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte = ((struct counter_map){ COUNTER_MAP_NOMAP, 0 }); 17021cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 17031cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1704175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1705e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1706e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1707e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1708e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1709e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Without this, on gcc 2.7.2.3, we get: 171079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell libiptc.c: In function `TC_COMMIT': 1711e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher libiptc.c:833: fixed or forbidden register was spilled. 1712e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher This may be due to a compiler bug or to impossible asm 1713e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher statements or clauses. 1714e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher*/ 1715e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 171679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellsubtract_counters(STRUCT_COUNTERS *answer, 171779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *a, 171879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *b) 1719e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1720e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->pcnt = a->pcnt - b->pcnt; 1721e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->bcnt = a->bcnt - b->bcnt; 1722e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1723e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1724e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 172579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_COMMIT(TC_HANDLE_T *handle) 1726e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1727e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Replace, then map back the counters. */ 172879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_REPLACE *repl; 172979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_COUNTERS_INFO *newcounters; 1730e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 1731841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson size_t counterlen; 1732e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1733e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1734841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 1735841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson counterlen = sizeof(STRUCT_COUNTERS_INFO) 1736841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson + sizeof(STRUCT_COUNTERS) * (*handle)->new_number; 1737841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 1738e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#if 0 173954c307e0ff401f40a6fe382af4ae5bff0f5b40baRusty Russell TC_DUMP_ENTRIES(*handle); 1740e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#endif 1741e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1742e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Don't commit if nothing changed. */ 1743e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!(*handle)->changed) 1744e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher goto finished; 1745e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1746e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl = malloc(sizeof(*repl) + (*handle)->entries.size); 1747e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl) { 1748e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1749e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1750e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1751e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1752e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the old counters we will get from kernel */ 175379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell repl->counters = malloc(sizeof(STRUCT_COUNTERS) 1754e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * (*handle)->info.num_entries); 1755e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl->counters) { 1756e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1757e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1758e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1759e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 17607e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1761e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the counters we're going to put back, later. */ 1762e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters = malloc(counterlen); 1763e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!newcounters) { 1764e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 1765e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1766e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1767e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1768e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1769e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1770e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(repl->name, (*handle)->info.name); 1771e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->num_entries = (*handle)->new_number; 1772e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->size = (*handle)->entries.size; 1773e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memcpy(repl->hook_entry, (*handle)->info.hook_entry, 1774e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher sizeof(repl->hook_entry)); 1775e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memcpy(repl->underflow, (*handle)->info.underflow, 1776e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher sizeof(repl->underflow)); 1777e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->num_counters = (*handle)->info.num_entries; 1778e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->valid_hooks = (*handle)->info.valid_hooks; 1779725d97a79cf0b332ed45cb7d254915178328427dRusty Russell memcpy(repl->entries, (*handle)->entries.entrytable, 1780e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->entries.size); 1781e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 178279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 1783e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher sizeof(*repl) + (*handle)->entries.size) < 0) { 1784e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 1785e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1786e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 1787e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1788e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1789e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1790e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Put counters back. */ 1791e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(newcounters->name, (*handle)->info.name); 1792e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters->num_counters = (*handle)->new_number; 1793e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < (*handle)->new_number; i++) { 1794e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int mappos = (*handle)->counter_map[i].mappos; 1795e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher switch ((*handle)->counter_map[i].maptype) { 1796e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher case COUNTER_MAP_NOMAP: 1797e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters->counters[i] 179879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell = ((STRUCT_COUNTERS){ 0, 0 }); 1799e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher break; 1800e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1801e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher case COUNTER_MAP_NORMAL_MAP: 1802e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Original read: X. 1803e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Atomic read on replacement: X + Y. 1804e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Currently in kernel: Z. 1805e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Want in kernel: X + Y + Z. 1806e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * => Add in X + Y 1807e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * => Add in replacement read. 1808e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher */ 1809e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters->counters[i] = repl->counters[mappos]; 1810e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher break; 1811e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1812e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher case COUNTER_MAP_ZEROED: 1813e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Original read: X. 1814e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Atomic read on replacement: X + Y. 1815e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Currently in kernel: Z. 1816e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Want in kernel: Y + Z. 1817e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * => Add in Y. 1818e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * => Add in (replacement read - original read). 1819e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher */ 1820e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher subtract_counters(&newcounters->counters[i], 1821e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher &repl->counters[mappos], 1822e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher &index2entry(*handle, i)->counters); 1823e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher break; 18241cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 18251cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte case COUNTER_MAP_SET: 18261cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte /* Want to set counter (iptables-restore) */ 18271cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 18281cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte memcpy(&newcounters->counters[i], 18291cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte &index2entry(*handle, i)->counters, 18301cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte sizeof(STRUCT_COUNTERS)); 18311cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 18321cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte break; 1833e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1834e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 183562527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell 183662527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell#ifdef KERNEL_64_USERSPACE_32 183762527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell { 183862527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell /* Kernel will think that pointer should be 64-bits, and get 183962527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell padding. So we accomodate here (assumption: alignment of 184062527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell `counters' is on 64-bit boundary). */ 184162527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell u_int64_t *kernptr = (u_int64_t *)&newcounters->counters; 184262527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell if ((unsigned long)&newcounters->counters % 8 != 0) { 184362527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell fprintf(stderr, 184462527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell "counters alignment incorrect! Mail rusty!\n"); 184562527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell abort(); 184662527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell } 184762527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell *kernptr = newcounters->counters; 184854c307e0ff401f40a6fe382af4ae5bff0f5b40baRusty Russell } 184962527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell#endif /* KERNEL_64_USERSPACE_32 */ 1850e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 185179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 185279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell newcounters, counterlen) < 0) { 1853e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 1854e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1855e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 1856e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1857e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1858e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1859e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 1860e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1861e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 1862e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1863e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher finished: 1864841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson TC_FREE(handle); 1865e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1866e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1867e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1868e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get raw socket. */ 1869e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 187079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_RAW_SOCKET() 1871e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1872e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return sockfd; 1873e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1874e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1875e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Translates errno numbers into more human-readable form than strerror. */ 1876e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 187779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_STRERROR(int err) 1878e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1879e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 1880e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct table_struct { 1881e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher void *fn; 1882e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int err; 1883e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char *message; 1884e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } table [] = 18854ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 188679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INIT, EINVAL, "Module is wrong version" }, 18874ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_INIT, ENOENT, 18884ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Table does not exist (do you need to insmod?)" }, 188979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 189079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 189179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EMLINK, 1892e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher "Can't delete chain with references left" }, 189379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 189479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 189579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 189679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 18971cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 18981cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 189979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 190079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 1901e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* EINVAL for CHECK probably means bad interface. */ 190279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CHECK_PACKET, EINVAL, 1903c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad arguments (does that interface exist?)" }, 19044ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_CHECK_PACKET, ENOSYS, 19054ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Checking will most likely never get implemented" }, 1906e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* ENOENT for DELETE probably means no matching rule */ 190779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_ENTRY, ENOENT, 1908c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad rule (does a matching rule exist in that chain?)" }, 190979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, ENOENT, 1910c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad built-in chain name" }, 191179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, EINVAL, 1912c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad policy name" }, 19134ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte 19144ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, 0, "Incompatible with this kernel" }, 19154ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 19164ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 19174ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOMEM, "Memory allocation problem" }, 19184ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOENT, "No chain/target/match by that name" }, 1919e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher }; 1920e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1921e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 1922e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((!table[i].fn || table[i].fn == iptc_fn) 1923e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && table[i].err == err) 1924e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return table[i].message; 1925e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1926e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1927e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return strerror(err); 1928e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1929