libiptc.c revision e560fd604284180f3ab522993c5b8e6f424ef1d9
1e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson/* Library which manipulates firewall rules. Version $Revision: 1.37 $ */ 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 11e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See 12e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COPYING for details). */ 13e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 14e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#ifndef IPT_LIB_DIR 15e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#define IPT_LIB_DIR "/usr/local/lib/iptables" 16e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#endif 17e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 184e242f822ef0add1359c540ed0cf3acdf74c63f3Rusty Russell#ifndef __OPTIMIZE__ 19ec81ca7e5e5939eb0bfa4776c5c0c585efdfd1bbHarald WelteSTRUCT_ENTRY_TARGET * 2079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellGET_TARGET(STRUCT_ENTRY *e) 2130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 2230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return (void *)e + e->target_offset; 2330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 2430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#endif 2530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 26e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int sockfd = -1; 27e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void *iptc_fn = NULL; 28e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 29e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic const char *hooknames[] 3079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell= { [HOOK_PRE_ROUTING] "PREROUTING", 3179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_LOCAL_IN] "INPUT", 3279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_FORWARD] "FORWARD", 3379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell [HOOK_LOCAL_OUT] "OUTPUT", 3410758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell [HOOK_POST_ROUTING] "POSTROUTING", 3510758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell#ifdef HOOK_DROPPING 3610758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell [HOOK_DROPPING] "DROPPING" 3710758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell#endif 38e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 39e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 40e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstruct counter_map 41e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 42e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher enum { 43e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_NOMAP, 44e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_NORMAL_MAP, 451cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte COUNTER_MAP_ZEROED, 461cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte COUNTER_MAP_SET 47e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } maptype; 48e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int mappos; 49e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 50e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 51e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Convenience structures */ 52e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstruct ipt_error_target 53e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 5479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET t; 5579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell char error[TABLE_MAXNAMELEN]; 56e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 57e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 5830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellstruct chain_cache 5930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 6079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell char name[TABLE_MAXNAMELEN]; 6130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* This is the first rule in chain. */ 6279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *start; 6330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Last rule in chain */ 6479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *end; 6530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell}; 6630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 6779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellSTRUCT_TC_HANDLE 68e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 69e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Have changes been made? */ 70e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int changed; 71e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Size in here reflects original state. */ 7279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 73e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 74e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct counter_map *counter_map; 75e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Array of hook names */ 76e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char **hooknames; 77e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 7830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Cached position of chain heads (NULL = no cache). */ 7930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int cache_num_chains; 8030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int cache_num_builtins; 8130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *cache_chain_heads; 8230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 8330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Chain iterator: current chain cache entry. */ 8430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *cache_chain_iteration; 8530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 8630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Rule iterator: terminal rule */ 8779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *cache_rule_end; 88175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 89e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Number in here reflects current state. */ 90e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int new_number; 9179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GET_ENTRIES entries; 92e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 93e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 94175f64177743e5a417e98d483ef995bf7151f3bcRusty Russellstatic void 9579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellset_changed(TC_HANDLE_T h) 96175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell{ 9730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (h->cache_chain_heads) { 9830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell free(h->cache_chain_heads); 9930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_chain_heads = NULL; 10030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_num_chains = 0; 10130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_chain_iteration = NULL; 10230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_rule_end = NULL; 10330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell } 104175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell h->changed = 1; 105175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell} 106175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 107380ba5f3074a16fbaa8869d9594962d58b5f8608Harald Welte#ifdef IPTC_DEBUG 10879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic void do_check(TC_HANDLE_T h, unsigned int line); 109849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell#define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0) 11030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#else 11130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#define CHECK(h) 11230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#endif 113e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 114e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 11579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellget_number(const STRUCT_ENTRY *i, 11679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *seek, 117e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int *pos) 118e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 119e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (i == seek) 120e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 121e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*pos)++; 122e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 123e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 124e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 125e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic unsigned int 12679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellentry2index(const TC_HANDLE_T h, const STRUCT_ENTRY *seek) 127e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 128e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int pos = 0; 129e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 130725d97a79cf0b332ed45cb7d254915178328427dRusty Russell if (ENTRY_ITERATE(h->entries.entrytable, h->entries.size, 13179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell get_number, seek, &pos) == 0) { 132e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher fprintf(stderr, "ERROR: offset %i not an entry!\n", 133725d97a79cf0b332ed45cb7d254915178328427dRusty Russell (char *)seek - (char *)h->entries.entrytable); 134e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 135e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 136e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return pos; 137e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 138e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 139e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 14079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellget_entry_n(STRUCT_ENTRY *i, 141e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int number, 142e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int *pos, 14379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY **pe) 144e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 145e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (*pos == number) { 146e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *pe = i; 147e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 148e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 149e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*pos)++; 150e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 151e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 152e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 15379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic STRUCT_ENTRY * 15479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellindex2entry(TC_HANDLE_T h, unsigned int index) 155e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 156e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int pos = 0; 15779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *ret = NULL; 158e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 159725d97a79cf0b332ed45cb7d254915178328427dRusty Russell ENTRY_ITERATE(h->entries.entrytable, h->entries.size, 16079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell get_entry_n, index, &pos, &ret); 161e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 162e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ret; 163e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 164e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 16579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic inline STRUCT_ENTRY * 16679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellget_entry(TC_HANDLE_T h, unsigned int offset) 167e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 168725d97a79cf0b332ed45cb7d254915178328427dRusty Russell return (STRUCT_ENTRY *)((char *)h->entries.entrytable + offset); 169e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 170e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 171e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline unsigned long 17279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellentry2offset(const TC_HANDLE_T h, const STRUCT_ENTRY *e) 173e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 174725d97a79cf0b332ed45cb7d254915178328427dRusty Russell return (char *)e - (char *)h->entries.entrytable; 175e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 176e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 177e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic unsigned long 17879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellindex2offset(TC_HANDLE_T h, unsigned int index) 179e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 180e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return entry2offset(h, index2entry(h, index)); 181e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 182e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 183e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic const char * 18479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellget_errorlabel(TC_HANDLE_T h, unsigned int offset) 185e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 18679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e; 187e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 188e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e = get_entry(h, offset); 18967088e73ce7707229c56987868f112051defca5aRusty Russell if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) != 0) { 190e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher fprintf(stderr, "ERROR: offset %u not an error node!\n", 191e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher offset); 192e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 193e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 194e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 19579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return (const char *)GET_TARGET(e)->data; 196e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 197e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 198e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Allocate handle of given size */ 19979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic TC_HANDLE_T 200e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucheralloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 201e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 202e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher size_t len; 20379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 204e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 20579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell len = sizeof(STRUCT_TC_HANDLE) 206e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher + size 207e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher + num_rules * sizeof(struct counter_map); 208e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 209e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((h = malloc(len)) == NULL) { 210e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 211e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 212e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 213e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 214e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->changed = 0; 21530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_num_chains = 0; 21630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_chain_heads = NULL; 217e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->counter_map = (void *)h 21879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell + sizeof(STRUCT_TC_HANDLE) 219e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher + size; 220e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(h->info.name, tablename); 221e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(h->entries.name, tablename); 222e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 223e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 224e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 225e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 22679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_HANDLE_T 22779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INIT(const char *tablename) 228e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 22979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T h; 23079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO info; 231e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 232e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int tmp; 233e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher socklen_t s; 234e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 23579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INIT; 236e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 237e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson if (sockfd != -1) { 238366454bc69f781fdafc3a30eb6dd77155ee4efb6Harald Welte close(sockfd); 239e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 240e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson } 241366454bc69f781fdafc3a30eb6dd77155ee4efb6Harald Welte 242841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson if (strlen(tablename) >= TABLE_MAXNAMELEN) { 243841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson errno = EINVAL; 244841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson return NULL; 245841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 246841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 24779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 248e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (sockfd < 0) 249e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 250e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 251e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher s = sizeof(info); 252841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 253e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(info.name, tablename); 25479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) 255e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 256e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 257e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((h = alloc_handle(info.name, info.size, info.num_entries)) 258841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson == NULL) { 259841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson close(sockfd); 260e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 261e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 262841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 263e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 264e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Too hard --RR */ 265e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#if 0 266e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher sprintf(pathname, "%s/%s", IPT_LIB_DIR, info.name); 267e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher dynlib = dlopen(pathname, RTLD_NOW); 268e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!dynlib) { 269e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 270e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 271e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 272e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->hooknames = dlsym(dynlib, "hooknames"); 273e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!h->hooknames) { 274e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 275e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 276e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 277e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#else 278e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->hooknames = hooknames; 279e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#endif 280e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 281e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Initialize current state */ 282e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->info = info; 283e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->new_number = h->info.num_entries; 284e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < h->info.num_entries; i++) 285e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->counter_map[i] 286e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher = ((struct counter_map){COUNTER_MAP_NORMAL_MAP, i}); 287e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 288e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->entries.size = h->info.size; 289e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 29079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 291e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 29279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, &h->entries, 293e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher &tmp) < 0) { 294841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson close(sockfd); 295e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 296e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(h); 297e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 298e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 2997e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 300e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(h); 301e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return h; 302e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 303e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 304841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefssonvoid 305841e4aed2349046eb2c0b1375139c06569a93bd0Martin JosefssonTC_FREE(TC_HANDLE_T *h) 306841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson{ 307841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson close(sockfd); 308e560fd604284180f3ab522993c5b8e6f424ef1d9Martin Josefsson sockfd = -1; 309841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson if ((*h)->cache_chain_heads) 310841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson free((*h)->cache_chain_heads); 311841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson free(*h); 312841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson *h = NULL; 313841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson} 314841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 315e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 31679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellprint_match(const STRUCT_ENTRY_MATCH *m) 317e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 318228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell printf("Match name: `%s'\n", m->u.user.name); 319e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 320e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 321e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 32279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle); 32379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell 324e6869a8f59d779ff4d5a0984c86d80db7078496Marc Bouchervoid 32579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DUMP_ENTRIES(const TC_HANDLE_T handle) 326e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 327e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(handle); 328e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 329e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("libiptc v%s. %u entries, %u bytes.\n", 33080fe35d6339b53a12ddaec41885613e4e37ed031Harald Welte IPTABLES_VERSION, 331e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher handle->new_number, handle->entries.size); 332e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Table `%s'\n", handle->info.name); 333e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 33467088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_PRE_ROUTING], 33567088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_IN], 33667088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_FORWARD], 33767088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_LOCAL_OUT], 33867088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.hook_entry[HOOK_POST_ROUTING]); 339e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 34067088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_PRE_ROUTING], 34167088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_IN], 34267088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_FORWARD], 34367088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_LOCAL_OUT], 34467088e73ce7707229c56987868f112051defca5aRusty Russell handle->info.underflow[HOOK_POST_ROUTING]); 345e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 346725d97a79cf0b332ed45cb7d254915178328427dRusty Russell ENTRY_ITERATE(handle->entries.entrytable, handle->entries.size, 34779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell dump_entry, handle); 348e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 349e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 35030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Returns 0 if not hook entry, else hooknumber + 1 */ 35130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellstatic inline unsigned int 35279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellis_hook_entry(STRUCT_ENTRY *e, TC_HANDLE_T h) 35330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 35430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int i; 35530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 35679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell for (i = 0; i < NUMHOOKS; i++) { 35730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if ((h->info.valid_hooks & (1 << i)) 35830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell && get_entry(h, h->info.hook_entry[i]) == e) 35930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return i+1; 36030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell } 36130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return 0; 36230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 36330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 364e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 36579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russelladd_chain(STRUCT_ENTRY *e, TC_HANDLE_T h, STRUCT_ENTRY **prev) 366e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 36730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int builtin; 368e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 36930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Last entry. End it. */ 37030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (entry2offset(h, e) + e->next_offset == h->entries.size) { 37130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* This is the ERROR node at end of the table */ 37230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_chain_heads[h->cache_num_chains-1].end = *prev; 37330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return 0; 37430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell } 375e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 37630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* We know this is the start of a new chain if it's an ERROR 37730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell target, or a hook entry point */ 37867088e73ce7707229c56987868f112051defca5aRusty Russell if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) { 37930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* prev was last entry in previous chain */ 38030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_chain_heads[h->cache_num_chains-1].end 38130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell = *prev; 38230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 38330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell strcpy(h->cache_chain_heads[h->cache_num_chains].name, 38479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell (const char *)GET_TARGET(e)->data); 38530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_chain_heads[h->cache_num_chains].start 38630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell = (void *)e + e->next_offset; 38730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_num_chains++; 38830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell } else if ((builtin = is_hook_entry(e, h)) != 0) { 38930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (h->cache_num_chains > 0) 39030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* prev was last entry in previous chain */ 39130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_chain_heads[h->cache_num_chains-1].end 39230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell = *prev; 39330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 39430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell strcpy(h->cache_chain_heads[h->cache_num_chains].name, 39530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->hooknames[builtin-1]); 39630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_chain_heads[h->cache_num_chains].start 39730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell = (void *)e; 39830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_num_chains++; 39930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell } 40030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 40130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell *prev = e; 402e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 403e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 404e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 40530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellstatic int alphasort(const void *a, const void *b) 40630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 40730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return strcmp(((struct chain_cache *)a)->name, 40830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell ((struct chain_cache *)b)->name); 40930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 41030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 41179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic int populate_cache(TC_HANDLE_T h) 412e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 413e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 41479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *prev; 415e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 41630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* # chains < # rules / 2 + num builtins - 1 */ 41730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_chain_heads = malloc((h->new_number / 2 + 4) 41830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell * sizeof(struct chain_cache)); 41930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!h->cache_chain_heads) { 42030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell errno = ENOMEM; 42130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return 0; 422175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell } 423175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 42430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_num_chains = 0; 42530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_num_builtins = 0; 42630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 42730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Count builtins */ 42879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell for (i = 0; i < NUMHOOKS; i++) { 42930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (h->info.valid_hooks & (1 << i)) 43030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_num_builtins++; 431e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 432e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 43330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell prev = NULL; 434725d97a79cf0b332ed45cb7d254915178328427dRusty Russell ENTRY_ITERATE(h->entries.entrytable, h->entries.size, 43579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell add_chain, h, &prev); 43630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 43730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell qsort(h->cache_chain_heads + h->cache_num_builtins, 43830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_num_chains - h->cache_num_builtins, 43930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell sizeof(struct chain_cache), alphasort); 44030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 44130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return 1; 44230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 44330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 44430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Returns cache ptr if found, otherwise NULL. */ 44530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellstatic struct chain_cache * 44679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellfind_label(const char *name, TC_HANDLE_T handle) 44730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 448849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell unsigned int i; 44930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 45030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (handle->cache_chain_heads == NULL 45130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell && !populate_cache(handle)) 45230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 45330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 454849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell /* FIXME: Linear search through builtins, then binary --RR */ 455849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell for (i = 0; i < handle->cache_num_chains; i++) { 456849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell if (strcmp(handle->cache_chain_heads[i].name, name) == 0) 457849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell return &handle->cache_chain_heads[i]; 458e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 459e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 460849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell return NULL; 461e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 462e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 463e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Does this chain exist? */ 46479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle) 465e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 46630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return find_label(chain, handle) != NULL; 467e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 468e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 469e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Returns the position of the final (ie. unconditional) element. */ 470e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic unsigned int 47179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellget_chain_end(const TC_HANDLE_T handle, unsigned int start) 472e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 473e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int last_off, off; 47479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e; 475e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 476e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher last_off = start; 477e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e = get_entry(handle, start); 478e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 479e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Terminate when we meet a error label or a hook entry. */ 480e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (off = start + e->next_offset; 481e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher off < handle->entries.size; 482e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher last_off = off, off += e->next_offset) { 48379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET *t; 484e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 485e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 486e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e = get_entry(handle, off); 487e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 488e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* We hit an entry point. */ 48979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell for (i = 0; i < NUMHOOKS; i++) { 490e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((handle->info.valid_hooks & (1 << i)) 491e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && off == handle->info.hook_entry[i]) 492e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return last_off; 493e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 494e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 495e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* We hit a user chain label */ 49679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = GET_TARGET(e); 49767088e73ce7707229c56987868f112051defca5aRusty Russell if (strcmp(t->u.user.name, ERROR_TARGET) == 0) 498e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return last_off; 499e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 500e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* SHOULD NEVER HAPPEN */ 501e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher fprintf(stderr, "ERROR: Off end (%u) of chain from %u!\n", 502e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher handle->entries.size, off); 503e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 504e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 505e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 50630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. */ 507e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 5088c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_CHAIN(TC_HANDLE_T *handle) 509e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 51030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if ((*handle)->cache_chain_heads == NULL 51130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell && !populate_cache(*handle)) 512e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 513e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 51430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell (*handle)->cache_chain_iteration 51530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell = &(*handle)->cache_chain_heads[0]; 51630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 51730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return (*handle)->cache_chain_iteration->name; 51830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 51930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 52030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Iterator functions to run through the chains. Returns NULL at end. */ 52130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellconst char * 52279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NEXT_CHAIN(TC_HANDLE_T *handle) 52330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 52430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell (*handle)->cache_chain_iteration++; 52530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 52630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if ((*handle)->cache_chain_iteration - (*handle)->cache_chain_heads 527841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson == (*handle)->cache_num_chains) 52830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 52930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 53030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return (*handle)->cache_chain_iteration->name; 53130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 53230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 53330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Get first rule in the given chain: NULL for empty chain. */ 53479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 5358c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_FIRST_RULE(const char *chain, TC_HANDLE_T *handle) 53630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 53730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 53830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 53930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell c = find_label(chain, *handle); 54030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!c) { 54130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell errno = ENOENT; 54230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 543e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 544e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 54530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Empty chain: single return/policy rule */ 54630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (c->start == c->end) 54730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 54830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 54930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell (*handle)->cache_rule_end = c->end; 55030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return c->start; 551e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 552e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 55330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell/* Returns NULL when rules run out. */ 55479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY * 5558c700900e2a0cf87d7917cb62578583a60ad1210Philip BlundellTC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle) 55630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 55730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if ((void *)prev + prev->next_offset 55830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell == (void *)(*handle)->cache_rule_end) 55930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return NULL; 56030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 56130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return (void *)prev + prev->next_offset; 56230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 56330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 56430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#if 0 565e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* How many rules in this chain? */ 566e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherunsigned int 56779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_NUM_RULES(const char *chain, TC_HANDLE_T *handle) 568e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 569e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int off = 0; 57079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *start, *end; 571e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 572e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 573e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!find_label(&off, chain, *handle)) { 574e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 575e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return (unsigned int)-1; 576e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 577e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 578e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher start = get_entry(*handle, off); 579e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher end = get_entry(*handle, get_chain_end(*handle, off)); 580e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 581e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return entry2index(*handle, end) - entry2index(*handle, start); 582e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 583e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 584e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get n'th rule in this chain. */ 58579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst STRUCT_ENTRY *TC_GET_RULE(const char *chain, 58679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int n, 58779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 588e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 589e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int pos = 0, chainindex; 590e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 591e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 592e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!find_label(&pos, chain, *handle)) { 593e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 594e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 595e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 596e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 597e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher chainindex = entry2index(*handle, get_entry(*handle, pos)); 598e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 599e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return index2entry(*handle, chainindex + n); 600e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 60130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell#endif 602e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 60330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russellstatic const char * 60479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russelltarget_name(TC_HANDLE_T handle, const STRUCT_ENTRY *ce) 605e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 606e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int spos; 607e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int labelidx; 60879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *jumpto; 609e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 61030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* To avoid const warnings */ 61179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 61230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 61379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET) != 0) 61479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return GET_TARGET(e)->u.user.name; 615e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 616e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Standard target: evaluate */ 61779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell spos = *(int *)GET_TARGET(e)->data; 618e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (spos < 0) { 61979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (spos == RETURN) 62079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_RETURN; 621e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else if (spos == -NF_ACCEPT-1) 62279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_ACCEPT; 623e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else if (spos == -NF_DROP-1) 62479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return LABEL_DROP; 6252f4e5d92c73906e0dc2ae42fee5c05740528e92bJames Morris else if (spos == -NF_QUEUE-1) 62667088e73ce7707229c56987868f112051defca5aRusty Russell return LABEL_QUEUE; 627e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 628e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher fprintf(stderr, "ERROR: off %lu/%u not a valid target (%i)\n", 629e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher entry2offset(handle, e), handle->entries.size, 630e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher spos); 631e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 632e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 633e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 634e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher jumpto = get_entry(handle, spos); 635e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 636e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Fall through rule */ 637e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (jumpto == (void *)e + e->next_offset) 638e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ""; 639e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 640e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Must point to head of a chain: ie. after error rule */ 641e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher labelidx = entry2index(handle, jumpto) - 1; 642e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return get_errorlabel(handle, index2offset(handle, labelidx)); 643e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 644e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 645e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Returns a pointer to the target name of this position. */ 64679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellconst char *TC_GET_TARGET(const STRUCT_ENTRY *e, 64779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 648e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 649e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return target_name(*handle, e); 650e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 651e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 652e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Is this a built-in chain? Actually returns hook + 1. */ 653e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 65479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_BUILTIN(const char *chain, const TC_HANDLE_T handle) 655e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 656e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 657e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 65879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell for (i = 0; i < NUMHOOKS; i++) { 659e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((handle->info.valid_hooks & (1 << i)) 660e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && handle->hooknames[i] 661e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && strcmp(handle->hooknames[i], chain) == 0) 662e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return i+1; 663e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 664e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 665e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 666e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 667e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get the policy of a given built-in chain */ 668e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 66979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_POLICY(const char *chain, 67079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_COUNTERS *counters, 67179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 672e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 673e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int start; 67479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e; 675e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int hook; 676e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 67779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell hook = TC_BUILTIN(chain, *handle); 678e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (hook != 0) 679e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher start = (*handle)->info.hook_entry[hook-1]; 680e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else 681e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 682e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 683e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e = get_entry(*handle, get_chain_end(*handle, start)); 684e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *counters = e->counters; 685e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 686e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return target_name(*handle, e); 687e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 688e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 689e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 69079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellcorrect_verdict(STRUCT_ENTRY *e, 691725d97a79cf0b332ed45cb7d254915178328427dRusty Russell char *base, 692e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int offset, int delta_offset) 693e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 69479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t = (void *)GET_TARGET(e); 695725d97a79cf0b332ed45cb7d254915178328427dRusty Russell unsigned int curr = (char *)e - base; 696e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 697e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Trap: insert of fall-through rule. Don't change fall-through 698e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher verdict to jump-over-next-rule. */ 69979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(t->target.u.user.name, STANDARD_TARGET) == 0 700e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && t->verdict > (int)offset 701e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && !(curr == offset && 702e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict == curr + e->next_offset)) { 703e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict += delta_offset; 704e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 705e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 706e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 707e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 708e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 709e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Adjusts standard verdict jump positions after an insertion/deletion. */ 710e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 71179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellset_verdict(unsigned int offset, int delta_offset, TC_HANDLE_T *handle) 712e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 713725d97a79cf0b332ed45cb7d254915178328427dRusty Russell ENTRY_ITERATE((*handle)->entries.entrytable, 71479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell (*handle)->entries.size, 715725d97a79cf0b332ed45cb7d254915178328427dRusty Russell correct_verdict, (char *)(*handle)->entries.entrytable, 71679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell offset, delta_offset); 717e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 718175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 719e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 720e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 721e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 722e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* If prepend is set, then we are prepending to a chain: if the 723e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * insertion position is an entry point, keep the entry point. */ 724e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 725e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherinsert_rules(unsigned int num_rules, unsigned int rules_size, 72679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *insert, 727e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int offset, unsigned int num_rules_offset, 728e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int prepend, 72979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 730e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 73179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T newh; 73279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_GETINFO newinfo; 733e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 734e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 735e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (offset >= (*handle)->entries.size) { 736e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 737e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 738e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 739e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 740e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newinfo = (*handle)->info; 741e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 742e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Fix up entry points. */ 74379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell for (i = 0; i < NUMHOOKS; i++) { 744e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Entry points to START of chain, so keep same if 745e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher inserting on at that point. */ 746e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((*handle)->info.hook_entry[i] > offset) 747e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newinfo.hook_entry[i] += rules_size; 748e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 749e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Underflow always points to END of chain (policy), 750e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher so if something is inserted at same point, it 751e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher should be advanced. */ 752e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((*handle)->info.underflow[i] >= offset) 753e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newinfo.underflow[i] += rules_size; 754e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 755e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 756e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newh = alloc_handle((*handle)->info.name, 7573c7a6c479f3eccd65a78dc103f33f4085e8e4703Rusty Russell (*handle)->entries.size + rules_size, 7581de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte (*handle)->new_number + num_rules); 759e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!newh) 760e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 761e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newh->info = newinfo; 762e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 763e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Copy pre... */ 764725d97a79cf0b332ed45cb7d254915178328427dRusty Russell memcpy(newh->entries.entrytable, (*handle)->entries.entrytable,offset); 765e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* ... Insert new ... */ 766725d97a79cf0b332ed45cb7d254915178328427dRusty Russell memcpy((char *)newh->entries.entrytable + offset, insert, rules_size); 767e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* ... copy post */ 768725d97a79cf0b332ed45cb7d254915178328427dRusty Russell memcpy((char *)newh->entries.entrytable + offset + rules_size, 769725d97a79cf0b332ed45cb7d254915178328427dRusty Russell (char *)(*handle)->entries.entrytable + offset, 770e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->entries.size - offset); 771e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 772e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Move counter map. */ 773e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Copy pre... */ 774e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memcpy(newh->counter_map, (*handle)->counter_map, 775e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher sizeof(struct counter_map) * num_rules_offset); 776e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* ... copy post */ 777e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memcpy(newh->counter_map + num_rules_offset + num_rules, 778e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->counter_map + num_rules_offset, 779e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher sizeof(struct counter_map) * ((*handle)->new_number 780e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher - num_rules_offset)); 781e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Set intermediates to no counter copy */ 782e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < num_rules; i++) 783e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newh->counter_map[num_rules_offset+i] 784e0072945b57dc499327567640648050563b19a5eHarald Welte = ((struct counter_map){ COUNTER_MAP_SET, 0 }); 785e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 786e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newh->new_number = (*handle)->new_number + num_rules; 787e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newh->entries.size = (*handle)->entries.size + rules_size; 788e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newh->hooknames = (*handle)->hooknames; 789e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 79030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if ((*handle)->cache_chain_heads) 79130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell free((*handle)->cache_chain_heads); 792e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(*handle); 793e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *handle = newh; 794e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 795e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return set_verdict(offset, rules_size, handle); 796e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 797e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 798e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 799e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherdelete_rules(unsigned int num_rules, unsigned int rules_size, 800e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int offset, unsigned int num_rules_offset, 80179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 802e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 803e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 804e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 805e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (offset + rules_size > (*handle)->entries.size) { 806e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 807e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 808e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 809e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 810e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Fix up entry points. */ 81179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell for (i = 0; i < NUMHOOKS; i++) { 812e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* In practice, we never delete up to a hook entry, 813e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher since the built-in chains are always first, 814e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher so these two are never equal */ 815e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((*handle)->info.hook_entry[i] >= offset + rules_size) 816e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->info.hook_entry[i] -= rules_size; 817e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else if ((*handle)->info.hook_entry[i] > offset) { 818e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher fprintf(stderr, "ERROR: Deleting entry %u %u %u\n", 819e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher i, (*handle)->info.hook_entry[i], offset); 820e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 821e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 822e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 823e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Underflow points to policy (terminal) rule in 824e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher built-in, so sequality is valid here (when deleting 825e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher the last rule). */ 826e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((*handle)->info.underflow[i] >= offset + rules_size) 827e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->info.underflow[i] -= rules_size; 828e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else if ((*handle)->info.underflow[i] > offset) { 829e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher fprintf(stderr, "ERROR: Deleting uflow %u %u %u\n", 830e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher i, (*handle)->info.underflow[i], offset); 831e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher abort(); 832e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 833e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 834e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 835e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Move the rules down. */ 836725d97a79cf0b332ed45cb7d254915178328427dRusty Russell memmove((char *)(*handle)->entries.entrytable + offset, 837725d97a79cf0b332ed45cb7d254915178328427dRusty Russell (char *)(*handle)->entries.entrytable + offset + rules_size, 838e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->entries.size - (offset + rules_size)); 839e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 840e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Move the counter map down. */ 841e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memmove(&(*handle)->counter_map[num_rules_offset], 842e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher &(*handle)->counter_map[num_rules_offset + num_rules], 843e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher sizeof(struct counter_map) 844e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * ((*handle)->new_number - (num_rules + num_rules_offset))); 845e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 846e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Fix numbers */ 847e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->new_number -= num_rules; 848e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->entries.size -= rules_size; 849e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 850e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return set_verdict(offset, -(int)rules_size, handle); 851e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 852e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 853e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 85479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstandard_map(STRUCT_ENTRY *e, int verdict) 855e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 85679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 857e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 85879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 859e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 86067088e73ce7707229c56987868f112051defca5aRusty Russell if (t->target.u.target_size 8618c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 862e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 863e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 864e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 865e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset for memcmp convenience on delete/replace */ 86679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 86779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell strcpy(t->target.u.user.name, STANDARD_TARGET); 868e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = verdict; 869e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 870e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 871e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 8727e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 873e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 87479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellmap_target(const TC_HANDLE_T handle, 87579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e, 876e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int offset, 87779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET *old) 878e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 87979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 880e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 881e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Save old target (except data, which we don't change, except for 882e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher standard case, where we don't care). */ 883e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *old = *t; 884e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 885e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's empty (=> fall through) */ 886228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (strcmp(t->u.user.name, "") == 0) 887e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return standard_map(e, offset + e->next_offset); 888e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's a standard target name... */ 88979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 890e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return standard_map(e, -NF_ACCEPT - 1); 89179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 892e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return standard_map(e, -NF_DROP - 1); 89367088e73ce7707229c56987868f112051defca5aRusty Russell else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 894e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return standard_map(e, -NF_QUEUE - 1); 89579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 89679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell return standard_map(e, RETURN); 89779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (TC_BUILTIN(t->u.user.name, handle)) { 898e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Can't jump to builtins. */ 899e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 900e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 901e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else { 902e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Maybe it's an existing chain name. */ 90330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 904e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 905228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell c = find_label(t->u.user.name, handle); 90630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (c) 90730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return standard_map(e, entry2offset(handle, c->start)); 908e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 909e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 910e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Must be a module? If not, kernel will reject... */ 911e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* memset to all 0 for your memcmp convenience. */ 912228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell memset(t->u.user.name + strlen(t->u.user.name), 913e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 0, 91479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell FUNCTION_MAXNAMELEN - strlen(t->u.user.name)); 915e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 916e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 917e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 918e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 91979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellunmap_target(STRUCT_ENTRY *e, STRUCT_ENTRY_TARGET *old) 920e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 92179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 922e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 923e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Save old target (except data, which we don't change, except for 924e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher standard case, where we don't care). */ 925e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *t = *old; 926e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 927e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 928e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 929e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 93079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 93179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 93279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 93379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 934e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 93530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int chainindex, offset; 93679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET old; 93730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 93814a1c9175257f73e936a68ba68d3541278c0e52aRusty Russell STRUCT_ENTRY *tmp; 939e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int ret; 940e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 94179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_INSERT_ENTRY; 94230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 943e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 944e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 945e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 946e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 94730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell chainindex = entry2index(*handle, c->start); 948e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 94914a1c9175257f73e936a68ba68d3541278c0e52aRusty Russell tmp = index2entry(*handle, chainindex + rulenum); 95014a1c9175257f73e936a68ba68d3541278c0e52aRusty Russell if (!tmp || tmp > c->end) { 951e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 952e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 953e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 954e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher offset = index2offset(*handle, chainindex + rulenum); 955e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 956e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Mapping target actually alters entry, but that's 957e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher transparent to the caller. */ 95879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (!map_target(*handle, (STRUCT_ENTRY *)e, offset, &old)) 959e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 960e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 961e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher ret = insert_rules(1, e->next_offset, e, offset, 962e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher chainindex + rulenum, rulenum == 0, handle); 96379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unmap_target((STRUCT_ENTRY *)e, &old); 964e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ret; 965e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 966e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 967e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 968e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 96979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 97079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 97179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 97279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 973e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 97430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int chainindex, offset; 97579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET old; 97630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 97714a1c9175257f73e936a68ba68d3541278c0e52aRusty Russell STRUCT_ENTRY *tmp; 978e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int ret; 979e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 98079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_REPLACE_ENTRY; 981e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 98230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 983e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 984e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 985e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 986e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 98730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell chainindex = entry2index(*handle, c->start); 988e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 98914a1c9175257f73e936a68ba68d3541278c0e52aRusty Russell tmp = index2entry(*handle, chainindex + rulenum); 99014a1c9175257f73e936a68ba68d3541278c0e52aRusty Russell if (!tmp || tmp >= c->end) { 991e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 992e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 993e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 994e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 995e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher offset = index2offset(*handle, chainindex + rulenum); 996e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Replace = delete and insert. */ 997e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!delete_rules(1, get_entry(*handle, offset)->next_offset, 998e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher offset, chainindex + rulenum, handle)) 999e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1000e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 100179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (!map_target(*handle, (STRUCT_ENTRY *)e, offset, &old)) 1002e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1003e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1004e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher ret = insert_rules(1, e->next_offset, e, offset, 1005e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher chainindex + rulenum, 1, handle); 100679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unmap_target((STRUCT_ENTRY *)e, &old); 1007e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ret; 1008e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1009e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1010e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Append entry `fw' to chain `chain'. Equivalent to insert with 1011e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher rulenum = length of chain. */ 1012e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 101379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 101479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *e, 101579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1016e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 101730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 101879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET old; 1019e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int ret; 1020e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 102179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_APPEND_ENTRY; 102230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1023e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1024e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1025e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1026e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 102779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (!map_target(*handle, (STRUCT_ENTRY *)e, 102830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell entry2offset(*handle, c->end), &old)) 1029e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1030e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 103130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell ret = insert_rules(1, e->next_offset, e, 103230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell entry2offset(*handle, c->end), 103330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell entry2index(*handle, c->end), 1034e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 0, handle); 103579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unmap_target((STRUCT_ENTRY *)e, &old); 1036e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ret; 1037e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1038e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1039e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic inline int 104079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellmatch_different(const STRUCT_ENTRY_MATCH *a, 1041edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *a_elems, 1042edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_elems, 1043edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned char **maskptr) 1044e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 104579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY_MATCH *b; 1046edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1047e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1048e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Offset of b is the same as a. */ 104930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell b = (void *)b_elems + ((unsigned char *)a - a_elems); 1050e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1051228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (a->u.match_size != b->u.match_size) 1052e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1053e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1054228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell if (strcmp(a->u.user.name, b->u.user.name) != 0) 1055e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1056e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 105773ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell *maskptr += ALIGN(sizeof(*a)); 1058edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 105973ef09b21573ddb17ff75e5fd06fd4b52ec8ea40Rusty Russell for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1060edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1061edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 1; 1062edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell *maskptr += i; 1063edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell return 0; 1064edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell} 1065edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell 1066edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russellstatic inline int 1067edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russelltarget_different(const unsigned char *a_targdata, 1068edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *b_targdata, 1069edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int tdatasize, 1070edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell const unsigned char *mask) 1071edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell{ 1072edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell unsigned int i; 1073edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell for (i = 0; i < tdatasize; i++) 1074edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (((a_targdata[i] ^ b_targdata[i]) & mask[i]) != 0) 107590e712a00913fe2a2f885142439c392392dc08a8Rusty Russell return 1; 1076e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1077e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1078e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1079e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 108079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic int 108179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellis_same(const STRUCT_ENTRY *a, 108279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *b, 108379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask); 1084e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1085e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Delete the first rule in `chain' which matches `fw'. */ 1086e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 108779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_ENTRY(const IPT_CHAINLABEL chain, 108879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_ENTRY *origfw, 108979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned char *matchmask, 109079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1091e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 109230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int offset; 109330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 109479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e, *fw; 1095e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 109679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_ENTRY; 109730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1098e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1099e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1100e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1101e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1102e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher fw = malloc(origfw->next_offset); 1103e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (fw == NULL) { 1104e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1105e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1106e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1107e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 110830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell for (offset = entry2offset(*handle, c->start); 110930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell offset < entry2offset(*handle, c->end); 111030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell offset += e->next_offset) { 111179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY_TARGET discard; 1112e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1113e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memcpy(fw, origfw, origfw->next_offset); 1114e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1115e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* FIXME: handle this in is_same --RR */ 1116e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!map_target(*handle, fw, offset, &discard)) { 1117e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(fw); 1118e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1119e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1120e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e = get_entry(*handle, offset); 1121e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1122e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#if 0 1123e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("Deleting:\n"); 1124e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher dump_entry(newe); 1125e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#endif 1126edf14cf4b5edb148d7473f067d95e7bd1316900bRusty Russell if (is_same(e, fw, matchmask)) { 1127e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int ret; 1128e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher ret = delete_rules(1, e->next_offset, 1129e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher offset, entry2index(*handle, e), 1130e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher handle); 1131e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(fw); 1132e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ret; 1133e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1134e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1135e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1136e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(fw); 1137e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1138e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 11397e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell} 1140e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1141e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Delete the rule in position `rulenum' in `chain'. */ 1142e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 114379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 114479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int rulenum, 114579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1146e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1147e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int index; 1148e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int ret; 114979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e; 115030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 1151e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 115279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_NUM_ENTRY; 115330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1154e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1155e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1156e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1157e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 115830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell index = entry2index(*handle, c->start) + rulenum; 1159e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 116030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (index >= entry2index(*handle, c->end)) { 1161e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = E2BIG; 1162e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1163e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1164e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1165e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e = index2entry(*handle, index); 1166e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (e == NULL) { 1167e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1168e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1169e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1170e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1171e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher ret = delete_rules(1, e->next_offset, entry2offset(*handle, e), 1172e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher index, handle); 1173e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ret; 1174e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1175e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1176e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Check the packet `fw' on chain `chain'. Returns the verdict, or 1177e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher NULL and sets errno. */ 1178e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 117979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CHECK_PACKET(const IPT_CHAINLABEL chain, 118079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *entry, 118179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1182e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1183e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOSYS; 1184e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 1185e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1186e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1187e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Flushes the entries in the given chain (ie. empties chain). */ 1188e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 118979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1190e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 119130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int startindex, endindex; 119230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 1193e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int ret; 1194e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 119579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_FLUSH_ENTRIES; 119630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1197e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1198e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1199e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 120030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell startindex = entry2index(*handle, c->start); 120130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell endindex = entry2index(*handle, c->end); 1202e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1203e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher ret = delete_rules(endindex - startindex, 120430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell (char *)c->end - (char *)c->start, 120530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell entry2offset(*handle, c->start), startindex, 1206e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher handle); 1207e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ret; 1208e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1209e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1210e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Zeroes the counters in a chain. */ 1211e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 121279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1213e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1214e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i, end; 121530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 12167e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 121730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1218e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1219e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1220e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1221e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 122230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell i = entry2index(*handle, c->start); 122330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell end = entry2index(*handle, c->end); 1224e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1225e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (; i <= end; i++) { 1226e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((*handle)->counter_map[i].maptype ==COUNTER_MAP_NORMAL_MAP) 1227e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->counter_map[i].maptype = COUNTER_MAP_ZEROED; 1228e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1229175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1230e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1231e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1232e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1233e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 12341cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteSTRUCT_COUNTERS * 12351cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_READ_COUNTER(const IPT_CHAINLABEL chain, 12361cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 12371cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 12381cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 12391cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 12401cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte struct chain_cache *c; 12411cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int chainindex, end; 12421cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12431cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_READ_COUNTER; 12441cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 12451cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12461cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (!(c = find_label(chain, *handle))) { 12471cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 12481cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return NULL; 12491cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 12501cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12511cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte chainindex = entry2index(*handle, c->start); 12521cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte end = entry2index(*handle, c->end); 12531cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12541cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (chainindex + rulenum > end) { 12551cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = E2BIG; 12561cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return NULL; 12571cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 12581cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12591cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte e = index2entry(*handle, chainindex + rulenum); 12601cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12611cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return &e->counters; 12621cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 12631cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12641cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 12651cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 12661cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 12671cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 12681cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 12691cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 12701cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte struct chain_cache *c; 12711cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int chainindex, end; 12721cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12731cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_ZERO_COUNTER; 12741cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 12751cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12761cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (!(c = find_label(chain, *handle))) { 12771cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 12781cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 12791cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 12801cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12811cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte chainindex = entry2index(*handle, c->start); 12821cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte end = entry2index(*handle, c->end); 12831cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12841cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (chainindex + rulenum > end) { 12851cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = E2BIG; 12861cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 12871cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 12881cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12891cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte e = index2entry(*handle, chainindex + rulenum); 12901cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12911cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if ((*handle)->counter_map[chainindex + rulenum].maptype 12921cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte == COUNTER_MAP_NORMAL_MAP) { 12931cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte (*handle)->counter_map[chainindex + rulenum].maptype 12941cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte = COUNTER_MAP_ZEROED; 12951cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 12961cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12971cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 12981cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 12991cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 13001cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 13011cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13021cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welteint 13031cef74d943055668b5e356eebea877fdaa1ce3e0Harald WelteTC_SET_COUNTER(const IPT_CHAINLABEL chain, 13041cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int rulenum, 13051cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 13061cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte TC_HANDLE_T *handle) 13071cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte{ 13081cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_ENTRY *e; 13091cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte struct chain_cache *c; 13101cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int chainindex, end; 13111cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13121cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte iptc_fn = TC_SET_COUNTER; 13131cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte CHECK(*handle); 13141cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13151cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (!(c = find_label(chain, *handle))) { 13161cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = ENOENT; 13171cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 13181cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 13191cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13201cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte chainindex = entry2index(*handle, c->start); 13211cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte end = entry2index(*handle, c->end); 13221cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13231cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (chainindex + rulenum > end) { 13241cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte errno = E2BIG; 13251cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 0; 13261cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 13271cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13281cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte e = index2entry(*handle, chainindex + rulenum); 13291cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13301cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte (*handle)->counter_map[chainindex + rulenum].maptype 13311cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte = COUNTER_MAP_SET; 13321cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13331cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 13341cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13351cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte set_changed(*handle); 13361cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 13371cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte return 1; 13381cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte} 13391cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1340e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Creates a new chain. */ 1341e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* To create a chain, create two rules: error node and unconditional 1342e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * return. */ 1343e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 134479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1345e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1346e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int ret; 1347e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct { 134879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY head; 1349e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_error_target name; 135079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY ret; 135179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET target; 1352e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } newc; 1353e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 135479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_CREATE_CHAIN; 1355e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1356e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* find_label doesn't cover built-in targets: DROP, ACCEPT, 1357e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher QUEUE, RETURN. */ 135830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (find_label(chain, *handle) 135979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_DROP) == 0 136079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_ACCEPT) == 0 136167088e73ce7707229c56987868f112051defca5aRusty Russell || strcmp(chain, LABEL_QUEUE) == 0 136279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(chain, LABEL_RETURN) == 0) { 1363e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1364e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1365e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1366e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 136779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 1368e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1369e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1370e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1371e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1372e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memset(&newc, 0, sizeof(newc)); 137379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell newc.head.target_offset = sizeof(STRUCT_ENTRY); 1374e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newc.head.next_offset 137567088e73ce7707229c56987868f112051defca5aRusty Russell = sizeof(STRUCT_ENTRY) 13768c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell + ALIGN(sizeof(struct ipt_error_target)); 137767088e73ce7707229c56987868f112051defca5aRusty Russell strcpy(newc.name.t.u.user.name, ERROR_TARGET); 13788c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell newc.name.t.u.target_size = ALIGN(sizeof(struct ipt_error_target)); 1379e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(newc.name.error, chain); 1380e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 138179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell newc.ret.target_offset = sizeof(STRUCT_ENTRY); 1382e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newc.ret.next_offset 138367088e73ce7707229c56987868f112051defca5aRusty Russell = sizeof(STRUCT_ENTRY) 13848c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell + ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 138579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell strcpy(newc.target.target.u.user.name, STANDARD_TARGET); 138667088e73ce7707229c56987868f112051defca5aRusty Russell newc.target.target.u.target_size 13878c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell = ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 138879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell newc.target.verdict = RETURN; 1389e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1390e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Add just before terminal entry */ 1391e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher ret = insert_rules(2, sizeof(newc), &newc.head, 1392e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher index2offset(*handle, (*handle)->new_number - 1), 1393e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->new_number - 1, 1394e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 0, handle); 1395e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ret; 1396e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1397e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1398e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 139979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellcount_ref(STRUCT_ENTRY *e, unsigned int offset, unsigned int *ref) 1400e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 140179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 1402e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 140379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET) == 0) { 140479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1405e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1406e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (t->verdict == offset) 1407e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*ref)++; 1408e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1409e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1410e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1411e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1412e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1413e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get the number of references to this chain. */ 1414e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 141579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 141679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1417e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 141830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 1419e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 142030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1421e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1422e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1423e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1424e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1425e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *ref = 0; 1426725d97a79cf0b332ed45cb7d254915178328427dRusty Russell ENTRY_ITERATE((*handle)->entries.entrytable, 142779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell (*handle)->entries.size, 142879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell count_ref, entry2offset(*handle, c->start), ref); 1429e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1430e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1431e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1432e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Deletes a chain. */ 1433e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 143479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1435e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 143630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int labelidx, labeloff; 1437e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int references; 143830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 1439e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int ret; 1440e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 144179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (!TC_GET_REFERENCES(&references, chain, handle)) 1442e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 14437e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 144479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_DELETE_CHAIN; 1445e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 144679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (TC_BUILTIN(chain, *handle)) { 1447e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1448e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1449e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1450e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1451e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (references > 0) { 1452e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EMLINK; 1453e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1454e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1455e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 145630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(chain, *handle))) { 1457e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1458e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1459e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1460e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 146130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if ((void *)c->start != c->end) { 1462e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOTEMPTY; 1463e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1464e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1465e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1466e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Need label index: preceeds chain start */ 146730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell labelidx = entry2index(*handle, c->start) - 1; 1468e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher labeloff = index2offset(*handle, labelidx); 1469e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1470e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher ret = delete_rules(2, 1471e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher get_entry(*handle, labeloff)->next_offset 147230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell + c->start->next_offset, 1473e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher labeloff, labelidx, handle); 1474e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return ret; 1475e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1476e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1477e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Renames a chain. */ 147879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellint TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 147979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL newname, 148079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1481e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 148230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell unsigned int labeloff, labelidx; 148330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct chain_cache *c; 1484e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_error_target *t; 1485e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 148679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_RENAME_CHAIN; 1487e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 14881de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte /* find_label doesn't cover built-in targets: DROP, ACCEPT, 14891de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte QUEUE, RETURN. */ 149030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (find_label(newname, *handle) 149179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_DROP) == 0 149279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_ACCEPT) == 0 14931de804642d4c8e9c71b7e225a1528fff15fa7faaHarald Welte || strcmp(newname, LABEL_QUEUE) == 0 149479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || strcmp(newname, LABEL_RETURN) == 0) { 1495e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1496e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1497e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1498e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 149930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (!(c = find_label(oldname, *handle)) 150079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell || TC_BUILTIN(oldname, *handle)) { 1501e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 1502e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1503e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1504e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 150579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 1506e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1507e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1508e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1509e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1510e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Need label index: preceeds chain start */ 151130fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell labelidx = entry2index(*handle, c->start) - 1; 1512e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher labeloff = index2offset(*handle, labelidx); 1513e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1514e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t = (struct ipt_error_target *) 151579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell GET_TARGET(get_entry(*handle, labeloff)); 1516e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1517e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memset(t->error, 0, sizeof(t->error)); 1518e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(t->error, newname); 1519175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1520e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1521e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1522e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1523e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1524e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Sets the policy on a built-in chain. */ 1525e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 152679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_SET_POLICY(const IPT_CHAINLABEL chain, 152779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const IPT_CHAINLABEL policy, 15281cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte STRUCT_COUNTERS *counters, 152979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell TC_HANDLE_T *handle) 1530e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1531e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int hook; 15321cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int policyoff, ctrindex; 153379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_ENTRY *e; 153479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_STANDARD_TARGET *t; 1535e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 153679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell iptc_fn = TC_SET_POLICY; 1537e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Figure out which chain. */ 153879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell hook = TC_BUILTIN(chain, *handle); 1539e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (hook == 0) { 1540c8264991454b5e77279830736f80ea3153b6f814Marc Boucher errno = ENOENT; 1541e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1542e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else 1543e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher hook--; 1544e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1545e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher policyoff = get_chain_end(*handle, (*handle)->info.hook_entry[hook]); 1546e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (policyoff != (*handle)->info.underflow[hook]) { 1547e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher printf("ERROR: Policy for `%s' offset %u != underflow %u\n", 1548e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher chain, policyoff, (*handle)->info.underflow[hook]); 1549e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1550e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1551e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1552e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e = get_entry(*handle, policyoff); 155379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1554e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 155579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (strcmp(policy, LABEL_ACCEPT) == 0) 1556e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = -NF_ACCEPT - 1; 155779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell else if (strcmp(policy, LABEL_DROP) == 0) 1558e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t->verdict = -NF_DROP - 1; 1559e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else { 1560e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1561e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1562e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 15631cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 15641cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte ctrindex = entry2index(*handle, e); 15651cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 15661cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte if (counters) { 15671cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte /* set byte and packet counters */ 15681cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 15691cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 15701cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte (*handle)->counter_map[ctrindex].maptype 15711cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte = COUNTER_MAP_SET; 15721cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 15731cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } else { 15741cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte (*handle)->counter_map[ctrindex] 15751cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte = ((struct counter_map){ COUNTER_MAP_NOMAP, 0 }); 15761cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte } 15771cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 1578175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell set_changed(*handle); 1579e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1580e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1581e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1582e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1583e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Without this, on gcc 2.7.2.3, we get: 158479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell libiptc.c: In function `TC_COMMIT': 1585e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher libiptc.c:833: fixed or forbidden register was spilled. 1586e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher This may be due to a compiler bug or to impossible asm 1587e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher statements or clauses. 1588e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher*/ 1589e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void 159079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellsubtract_counters(STRUCT_COUNTERS *answer, 159179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *a, 159279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell const STRUCT_COUNTERS *b) 1593e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1594e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->pcnt = a->pcnt - b->pcnt; 1595e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher answer->bcnt = a->bcnt - b->bcnt; 1596e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1597e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1598e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 159979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_COMMIT(TC_HANDLE_T *handle) 1600e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1601e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Replace, then map back the counters. */ 160279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_REPLACE *repl; 160379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell STRUCT_COUNTERS_INFO *newcounters; 1604e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 1605841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson size_t counterlen; 1606e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1607e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1608841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 1609841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson counterlen = sizeof(STRUCT_COUNTERS_INFO) 1610841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson + sizeof(STRUCT_COUNTERS) * (*handle)->new_number; 1611841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 1612e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#if 0 161354c307e0ff401f40a6fe382af4ae5bff0f5b40baRusty Russell TC_DUMP_ENTRIES(*handle); 1614e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#endif 1615e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1616e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Don't commit if nothing changed. */ 1617e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!(*handle)->changed) 1618e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher goto finished; 1619e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1620e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl = malloc(sizeof(*repl) + (*handle)->entries.size); 1621e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl) { 1622e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1623e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1624e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1625e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1626e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the old counters we will get from kernel */ 162779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell repl->counters = malloc(sizeof(STRUCT_COUNTERS) 1628e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * (*handle)->info.num_entries); 1629e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!repl->counters) { 1630e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1631e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1632e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1633e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 16347e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell 1635e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* These are the counters we're going to put back, later. */ 1636e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters = malloc(counterlen); 1637e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!newcounters) { 1638e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 1639e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1640e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOMEM; 1641e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1642e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1643e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1644e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(repl->name, (*handle)->info.name); 1645e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->num_entries = (*handle)->new_number; 1646e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->size = (*handle)->entries.size; 1647e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memcpy(repl->hook_entry, (*handle)->info.hook_entry, 1648e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher sizeof(repl->hook_entry)); 1649e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memcpy(repl->underflow, (*handle)->info.underflow, 1650e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher sizeof(repl->underflow)); 1651e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->num_counters = (*handle)->info.num_entries; 1652e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher repl->valid_hooks = (*handle)->info.valid_hooks; 1653725d97a79cf0b332ed45cb7d254915178328427dRusty Russell memcpy(repl->entries, (*handle)->entries.entrytable, 1654e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->entries.size); 1655e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 165679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 1657e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher sizeof(*repl) + (*handle)->entries.size) < 0) { 1658e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 1659e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1660e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 1661e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1662e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1663e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1664e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Put counters back. */ 1665e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(newcounters->name, (*handle)->info.name); 1666e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters->num_counters = (*handle)->new_number; 1667e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < (*handle)->new_number; i++) { 1668e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int mappos = (*handle)->counter_map[i].mappos; 1669e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher switch ((*handle)->counter_map[i].maptype) { 1670e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher case COUNTER_MAP_NOMAP: 1671e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters->counters[i] 167279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell = ((STRUCT_COUNTERS){ 0, 0 }); 1673e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher break; 1674e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1675e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher case COUNTER_MAP_NORMAL_MAP: 1676e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Original read: X. 1677e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Atomic read on replacement: X + Y. 1678e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Currently in kernel: Z. 1679e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Want in kernel: X + Y + Z. 1680e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * => Add in X + Y 1681e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * => Add in replacement read. 1682e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher */ 1683e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters->counters[i] = repl->counters[mappos]; 1684e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher break; 1685e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1686e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher case COUNTER_MAP_ZEROED: 1687e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Original read: X. 1688e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Atomic read on replacement: X + Y. 1689e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Currently in kernel: Z. 1690e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Want in kernel: Y + Z. 1691e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * => Add in Y. 1692e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * => Add in (replacement read - original read). 1693e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher */ 1694e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher subtract_counters(&newcounters->counters[i], 1695e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher &repl->counters[mappos], 1696e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher &index2entry(*handle, i)->counters); 1697e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher break; 16981cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 16991cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte case COUNTER_MAP_SET: 17001cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte /* Want to set counter (iptables-restore) */ 17011cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17021cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte memcpy(&newcounters->counters[i], 17031cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte &index2entry(*handle, i)->counters, 17041cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte sizeof(STRUCT_COUNTERS)); 17051cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 17061cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte break; 1707e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1708e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 170962527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell 171062527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell#ifdef KERNEL_64_USERSPACE_32 171162527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell { 171262527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell /* Kernel will think that pointer should be 64-bits, and get 171362527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell padding. So we accomodate here (assumption: alignment of 171462527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell `counters' is on 64-bit boundary). */ 171562527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell u_int64_t *kernptr = (u_int64_t *)&newcounters->counters; 171662527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell if ((unsigned long)&newcounters->counters % 8 != 0) { 171762527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell fprintf(stderr, 171862527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell "counters alignment incorrect! Mail rusty!\n"); 171962527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell abort(); 172062527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell } 172162527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell *kernptr = newcounters->counters; 172254c307e0ff401f40a6fe382af4ae5bff0f5b40baRusty Russell } 172362527ce5f0ffaa5b18aa118f64c21af238ddc156Rusty Russell#endif /* KERNEL_64_USERSPACE_32 */ 1724e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 172579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 172679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell newcounters, counterlen) < 0) { 1727e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 1728e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1729e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 1730e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1731e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1732e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1733e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 1734e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl); 1735e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(newcounters); 1736e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1737e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher finished: 1738841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson TC_FREE(handle); 1739e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 1740e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1741e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1742e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get raw socket. */ 1743e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 174479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_GET_RAW_SOCKET() 1745e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1746e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return sockfd; 1747e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1748e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1749e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Translates errno numbers into more human-readable form than strerror. */ 1750e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherconst char * 175179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty RussellTC_STRERROR(int err) 1752e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1753e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 1754e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct table_struct { 1755e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher void *fn; 1756e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int err; 1757e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher const char *message; 1758e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } table [] = 17594ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 176079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INIT, EINVAL, "Module is wrong version" }, 17614ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_INIT, ENOENT, 17624ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Table does not exist (do you need to insmod?)" }, 176379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 176479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 176579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_CHAIN, EMLINK, 1766e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher "Can't delete chain with references left" }, 176779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 176879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 176979dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 177079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 17711cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 17721cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 177379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 177479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 1775e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* EINVAL for CHECK probably means bad interface. */ 177679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_CHECK_PACKET, EINVAL, 1777c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad arguments (does that interface exist?)" }, 17784ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { TC_CHECK_PACKET, ENOSYS, 17794ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte "Checking will most likely never get implemented" }, 1780e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* ENOENT for DELETE probably means no matching rule */ 178179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_DELETE_ENTRY, ENOENT, 1782c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad rule (does a matching rule exist in that chain?)" }, 178379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, ENOENT, 1784c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad built-in chain name" }, 178579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell { TC_SET_POLICY, EINVAL, 1786c8264991454b5e77279830736f80ea3153b6f814Marc Boucher "Bad policy name" }, 17874ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte 17884ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, 0, "Incompatible with this kernel" }, 17894ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 17904ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 17914ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOMEM, "Memory allocation problem" }, 17924ccfa630d9a588d4b852abef8bc467642427c8cfHarald Welte { NULL, ENOENT, "No chain/target/match by that name" }, 1793e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher }; 1794e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1795e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 1796e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if ((!table[i].fn || table[i].fn == iptc_fn) 1797e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher && table[i].err == err) 1798e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return table[i].message; 1799e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1800e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1801e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return strerror(err); 1802e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1803