Home | History | Annotate | Download | only in libiptc
      1 /* Library which manipulates firewall rules.  Version $Revision$ */
      2 
      3 /* Architecture of firewall rules is as follows:
      4  *
      5  * Chains go INPUT, FORWARD, OUTPUT then user chains.
      6  * Each user chain starts with an ERROR node.
      7  * Every chain ends with an unconditional jump: a RETURN for user chains,
      8  * and a POLICY for built-ins.
      9  */
     10 
     11 /* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
     12  * COPYING for details).
     13  * (C) 2000-2004 by the Netfilter Core Team <coreteam (at) netfilter.org>
     14  *
     15  * 2003-Jun-20: Harald Welte <laforge (at) netfilter.org>:
     16  *	- Reimplementation of chain cache to use offsets instead of entries
     17  * 2003-Jun-23: Harald Welte <laforge (at) netfilter.org>:
     18  * 	- performance optimization, sponsored by Astaro AG (http://www.astaro.com/)
     19  * 	  don't rebuild the chain cache after every operation, instead fix it
     20  * 	  up after a ruleset change.
     21  * 2004-Aug-18: Harald Welte <laforge (at) netfilter.org>:
     22  * 	- further performance work: total reimplementation of libiptc.
     23  * 	- libiptc now has a real internal (linked-list) represntation of the
     24  * 	  ruleset and a parser/compiler from/to this internal representation
     25  * 	- again sponsored by Astaro AG (http://www.astaro.com/)
     26  *
     27  * 2008-Jan+Jul: Jesper Dangaard Brouer <hawk (at) comx.dk>
     28  * 	- performance work: speedup chain list "name" searching.
     29  * 	- performance work: speedup initial ruleset parsing.
     30  * 	- sponsored by ComX Networks A/S (http://www.comx.dk/)
     31  */
     32 #include <unistd.h>
     33 #include <fcntl.h>
     34 #include <sys/types.h>
     35 #include <sys/socket.h>
     36 #include <stdbool.h>
     37 #include <xtables.h>
     38 #include <libiptc/xtcshared.h>
     39 
     40 #include "linux_list.h"
     41 
     42 //#define IPTC_DEBUG2 1
     43 
     44 #ifdef IPTC_DEBUG2
     45 #include <fcntl.h>
     46 #define DEBUGP(x, args...)	fprintf(stderr, "%s: " x, __FUNCTION__, ## args)
     47 #define DEBUGP_C(x, args...)	fprintf(stderr, x, ## args)
     48 #else
     49 #define DEBUGP(x, args...)
     50 #define DEBUGP_C(x, args...)
     51 #endif
     52 
     53 #ifdef DEBUG
     54 #define debug(x, args...)	fprintf(stderr, x, ## args)
     55 #else
     56 #define debug(x, args...)
     57 #endif
     58 
     59 static void *iptc_fn = NULL;
     60 
     61 static const char *hooknames[] = {
     62 	[HOOK_PRE_ROUTING]	= "PREROUTING",
     63 	[HOOK_LOCAL_IN]		= "INPUT",
     64 	[HOOK_FORWARD]		= "FORWARD",
     65 	[HOOK_LOCAL_OUT]	= "OUTPUT",
     66 	[HOOK_POST_ROUTING]	= "POSTROUTING",
     67 };
     68 
     69 /* Convenience structures */
     70 #undef ipt_error_target /* uapi includes this already. */
     71 struct ipt_error_target
     72 {
     73 	STRUCT_ENTRY_TARGET t;
     74 	char error[TABLE_MAXNAMELEN];
     75 };
     76 
     77 struct chain_head;
     78 struct rule_head;
     79 
     80 struct counter_map
     81 {
     82 	enum {
     83 		COUNTER_MAP_NOMAP,
     84 		COUNTER_MAP_NORMAL_MAP,
     85 		COUNTER_MAP_ZEROED,
     86 		COUNTER_MAP_SET
     87 	} maptype;
     88 	unsigned int mappos;
     89 };
     90 
     91 enum iptcc_rule_type {
     92 	IPTCC_R_STANDARD,		/* standard target (ACCEPT, ...) */
     93 	IPTCC_R_MODULE,			/* extension module (SNAT, ...) */
     94 	IPTCC_R_FALLTHROUGH,		/* fallthrough rule */
     95 	IPTCC_R_JUMP,			/* jump to other chain */
     96 };
     97 
     98 struct rule_head
     99 {
    100 	struct list_head list;
    101 	struct chain_head *chain;
    102 	struct counter_map counter_map;
    103 
    104 	unsigned int index;		/* index (needed for counter_map) */
    105 	unsigned int offset;		/* offset in rule blob */
    106 
    107 	enum iptcc_rule_type type;
    108 	struct chain_head *jump;	/* jump target, if IPTCC_R_JUMP */
    109 
    110 	unsigned int size;		/* size of entry data */
    111 	STRUCT_ENTRY entry[0];
    112 };
    113 
    114 struct chain_head
    115 {
    116 	struct list_head list;
    117 	char name[TABLE_MAXNAMELEN];
    118 	unsigned int hooknum;		/* hook number+1 if builtin */
    119 	unsigned int references;	/* how many jumps reference us */
    120 	int verdict;			/* verdict if builtin */
    121 
    122 	STRUCT_COUNTERS counters;	/* per-chain counters */
    123 	struct counter_map counter_map;
    124 
    125 	unsigned int num_rules;		/* number of rules in list */
    126 	struct list_head rules;		/* list of rules */
    127 
    128 	unsigned int index;		/* index (needed for jump resolval) */
    129 	unsigned int head_offset;	/* offset in rule blob */
    130 	unsigned int foot_index;	/* index (needed for counter_map) */
    131 	unsigned int foot_offset;	/* offset in rule blob */
    132 };
    133 
    134 struct xtc_handle {
    135 	int sockfd;
    136 	int changed;			 /* Have changes been made? */
    137 
    138 	struct list_head chains;
    139 
    140 	struct chain_head *chain_iterator_cur;
    141 	struct rule_head *rule_iterator_cur;
    142 
    143 	unsigned int num_chains;         /* number of user defined chains */
    144 
    145 	struct chain_head **chain_index;   /* array for fast chain list access*/
    146 	unsigned int        chain_index_sz;/* size of chain index array */
    147 
    148 	int sorted_offsets; /* if chains are received sorted from kernel,
    149 			     * then the offsets are also sorted. Says if its
    150 			     * possible to bsearch offsets using chain_index.
    151 			     */
    152 
    153 	STRUCT_GETINFO info;
    154 	STRUCT_GET_ENTRIES *entries;
    155 };
    156 
    157 enum bsearch_type {
    158 	BSEARCH_NAME,	/* Binary search after chain name */
    159 	BSEARCH_OFFSET,	/* Binary search based on offset */
    160 };
    161 
    162 /* allocate a new chain head for the cache */
    163 static struct chain_head *iptcc_alloc_chain_head(const char *name, int hooknum)
    164 {
    165 	struct chain_head *c = malloc(sizeof(*c));
    166 	if (!c)
    167 		return NULL;
    168 	memset(c, 0, sizeof(*c));
    169 
    170 	strncpy(c->name, name, TABLE_MAXNAMELEN);
    171 	c->hooknum = hooknum;
    172 	INIT_LIST_HEAD(&c->rules);
    173 
    174 	return c;
    175 }
    176 
    177 /* allocate and initialize a new rule for the cache */
    178 static struct rule_head *iptcc_alloc_rule(struct chain_head *c, unsigned int size)
    179 {
    180 	struct rule_head *r = malloc(sizeof(*r)+size);
    181 	if (!r)
    182 		return NULL;
    183 	memset(r, 0, sizeof(*r));
    184 
    185 	r->chain = c;
    186 	r->size = size;
    187 
    188 	return r;
    189 }
    190 
    191 /* notify us that the ruleset has been modified by the user */
    192 static inline void
    193 set_changed(struct xtc_handle *h)
    194 {
    195 	h->changed = 1;
    196 }
    197 
    198 #ifdef IPTC_DEBUG
    199 static void do_check(struct xtc_handle *h, unsigned int line);
    200 #define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0)
    201 #else
    202 #define CHECK(h)
    203 #endif
    204 
    205 
    206 /**********************************************************************
    207  * iptc blob utility functions (iptcb_*)
    208  **********************************************************************/
    209 
    210 static inline int
    211 iptcb_get_number(const STRUCT_ENTRY *i,
    212 	   const STRUCT_ENTRY *seek,
    213 	   unsigned int *pos)
    214 {
    215 	if (i == seek)
    216 		return 1;
    217 	(*pos)++;
    218 	return 0;
    219 }
    220 
    221 static inline int
    222 iptcb_get_entry_n(STRUCT_ENTRY *i,
    223 	    unsigned int number,
    224 	    unsigned int *pos,
    225 	    STRUCT_ENTRY **pe)
    226 {
    227 	if (*pos == number) {
    228 		*pe = i;
    229 		return 1;
    230 	}
    231 	(*pos)++;
    232 	return 0;
    233 }
    234 
    235 static inline STRUCT_ENTRY *
    236 iptcb_get_entry(struct xtc_handle *h, unsigned int offset)
    237 {
    238 	return (STRUCT_ENTRY *)((char *)h->entries->entrytable + offset);
    239 }
    240 
    241 static unsigned int
    242 iptcb_entry2index(struct xtc_handle *const h, const STRUCT_ENTRY *seek)
    243 {
    244 	unsigned int pos = 0;
    245 
    246 	if (ENTRY_ITERATE(h->entries->entrytable, h->entries->size,
    247 			  iptcb_get_number, seek, &pos) == 0) {
    248 		fprintf(stderr, "ERROR: offset %u not an entry!\n",
    249 			(unsigned int)((char *)seek - (char *)h->entries->entrytable));
    250 		abort();
    251 	}
    252 	return pos;
    253 }
    254 
    255 static inline STRUCT_ENTRY *
    256 iptcb_offset2entry(struct xtc_handle *h, unsigned int offset)
    257 {
    258 	return (STRUCT_ENTRY *) ((void *)h->entries->entrytable+offset);
    259 }
    260 
    261 
    262 static inline unsigned long
    263 iptcb_entry2offset(struct xtc_handle *const h, const STRUCT_ENTRY *e)
    264 {
    265 	return (void *)e - (void *)h->entries->entrytable;
    266 }
    267 
    268 static inline unsigned int
    269 iptcb_offset2index(struct xtc_handle *const h, unsigned int offset)
    270 {
    271 	return iptcb_entry2index(h, iptcb_offset2entry(h, offset));
    272 }
    273 
    274 /* Returns 0 if not hook entry, else hooknumber + 1 */
    275 static inline unsigned int
    276 iptcb_ent_is_hook_entry(STRUCT_ENTRY *e, struct xtc_handle *h)
    277 {
    278 	unsigned int i;
    279 
    280 	for (i = 0; i < NUMHOOKS; i++) {
    281 		if ((h->info.valid_hooks & (1 << i))
    282 		    && iptcb_get_entry(h, h->info.hook_entry[i]) == e)
    283 			return i+1;
    284 	}
    285 	return 0;
    286 }
    287 
    288 
    289 /**********************************************************************
    290  * Chain index (cache utility) functions
    291  **********************************************************************
    292  * The chain index is an array with pointers into the chain list, with
    293  * CHAIN_INDEX_BUCKET_LEN spacing.  This facilitates the ability to
    294  * speedup chain list searching, by find a more optimal starting
    295  * points when searching the linked list.
    296  *
    297  * The starting point can be found fast by using a binary search of
    298  * the chain index. Thus, reducing the previous search complexity of
    299  * O(n) to O(log(n/k) + k) where k is CHAIN_INDEX_BUCKET_LEN.
    300  *
    301  * A nice property of the chain index, is that the "bucket" list
    302  * length is max CHAIN_INDEX_BUCKET_LEN (when just build, inserts will
    303  * change this). Oppose to hashing, where the "bucket" list length can
    304  * vary a lot.
    305  */
    306 #ifndef CHAIN_INDEX_BUCKET_LEN
    307 #define CHAIN_INDEX_BUCKET_LEN 40
    308 #endif
    309 
    310 /* Another nice property of the chain index is that inserting/creating
    311  * chains in chain list don't change the correctness of the chain
    312  * index, it only causes longer lists in the buckets.
    313  *
    314  * To mitigate the performance penalty of longer bucket lists and the
    315  * penalty of rebuilding, the chain index is rebuild only when
    316  * CHAIN_INDEX_INSERT_MAX chains has been added.
    317  */
    318 #ifndef CHAIN_INDEX_INSERT_MAX
    319 #define CHAIN_INDEX_INSERT_MAX 355
    320 #endif
    321 
    322 static inline unsigned int iptcc_is_builtin(struct chain_head *c);
    323 
    324 /* Use binary search in the chain index array, to find a chain_head
    325  * pointer closest to the place of the searched name element.
    326  *
    327  * Notes that, binary search (obviously) requires that the chain list
    328  * is sorted by name.
    329  *
    330  * The not so obvious: The chain index array, is actually both sorted
    331  * by name and offset, at the same time!.  This is only true because,
    332  * chain are stored sorted in the kernel (as we pushed it in sorted).
    333  *
    334  */
    335 static struct list_head *
    336 __iptcc_bsearch_chain_index(const char *name, unsigned int offset,
    337 			    unsigned int *idx, struct xtc_handle *handle,
    338 			    enum bsearch_type type)
    339 {
    340 	unsigned int pos, end;
    341 	int res;
    342 
    343 	struct list_head *list_pos;
    344 	list_pos=&handle->chains;
    345 
    346 	/* Check for empty array, e.g. no user defined chains */
    347 	if (handle->chain_index_sz == 0) {
    348 		debug("WARNING: handle->chain_index_sz == 0\n");
    349 		return list_pos;
    350 	}
    351 
    352 	/* Init */
    353 	end = handle->chain_index_sz;
    354 	pos = end / 2;
    355 
    356 	debug("bsearch Find chain:%s (pos:%d end:%d) (offset:%d)\n",
    357 	      name, pos, end, offset);
    358 
    359 	/* Loop */
    360  loop:
    361 	if (!handle->chain_index[pos]) {
    362 		fprintf(stderr, "ERROR: NULL pointer chain_index[%d]\n", pos);
    363 		return &handle->chains; /* Be safe, return orig start pos */
    364 	}
    365 
    366 	debug("bsearch Index[%d] name:%s ",
    367 	      pos, handle->chain_index[pos]->name);
    368 
    369 	/* Support for different compare functions */
    370 	switch (type) {
    371 	case BSEARCH_NAME:
    372 		res = strcmp(name, handle->chain_index[pos]->name);
    373 		break;
    374 	case BSEARCH_OFFSET:
    375 		debug("head_offset:[%d] foot_offset:[%d] ",
    376 		      handle->chain_index[pos]->head_offset,
    377 		      handle->chain_index[pos]->foot_offset);
    378 		res = offset - handle->chain_index[pos]->head_offset;
    379 		break;
    380 	default:
    381 		fprintf(stderr, "ERROR: %d not a valid bsearch type\n",
    382 			type);
    383 		abort();
    384 		break;
    385 	}
    386 	debug("res:%d ", res);
    387 
    388 
    389 	list_pos = &handle->chain_index[pos]->list;
    390 	*idx = pos;
    391 
    392 	if (res == 0) { /* Found element, by direct hit */
    393 		debug("[found] Direct hit pos:%d end:%d\n", pos, end);
    394 		return list_pos;
    395 	} else if (res < 0) { /* Too far, jump back */
    396 		end = pos;
    397 		pos = pos / 2;
    398 
    399 		/* Exit case: First element of array */
    400 		if (end == 0) {
    401 			debug("[found] Reached first array elem (end%d)\n",end);
    402 			return list_pos;
    403 		}
    404 		debug("jump back to pos:%d (end:%d)\n", pos, end);
    405 		goto loop;
    406 	} else { /* res > 0; Not far enough, jump forward */
    407 
    408 		/* Exit case: Last element of array */
    409 		if (pos == handle->chain_index_sz-1) {
    410 			debug("[found] Last array elem (end:%d)\n", end);
    411 			return list_pos;
    412 		}
    413 
    414 		/* Exit case: Next index less, thus elem in this list section */
    415 		switch (type) {
    416 		case BSEARCH_NAME:
    417 			res = strcmp(name, handle->chain_index[pos+1]->name);
    418 			break;
    419 		case BSEARCH_OFFSET:
    420 			res = offset - handle->chain_index[pos+1]->head_offset;
    421 			break;
    422 		}
    423 
    424 		if (res < 0) {
    425 			debug("[found] closest list (end:%d)\n", end);
    426 			return list_pos;
    427 		}
    428 
    429 		pos = (pos+end)/2;
    430 		debug("jump forward to pos:%d (end:%d)\n", pos, end);
    431 		goto loop;
    432 	}
    433 }
    434 
    435 /* Wrapper for string chain name based bsearch */
    436 static struct list_head *
    437 iptcc_bsearch_chain_index(const char *name, unsigned int *idx,
    438 			  struct xtc_handle *handle)
    439 {
    440 	return __iptcc_bsearch_chain_index(name, 0, idx, handle, BSEARCH_NAME);
    441 }
    442 
    443 
    444 /* Wrapper for offset chain based bsearch */
    445 static struct list_head *
    446 iptcc_bsearch_chain_offset(unsigned int offset, unsigned int *idx,
    447 			  struct xtc_handle *handle)
    448 {
    449 	struct list_head *pos;
    450 
    451 	/* If chains were not received sorted from kernel, then the
    452 	 * offset bsearch is not possible.
    453 	 */
    454 	if (!handle->sorted_offsets)
    455 		pos = handle->chains.next;
    456 	else
    457 		pos = __iptcc_bsearch_chain_index(NULL, offset, idx, handle,
    458 						  BSEARCH_OFFSET);
    459 	return pos;
    460 }
    461 
    462 
    463 #ifdef DEBUG
    464 /* Trivial linear search of chain index. Function used for verifying
    465    the output of bsearch function */
    466 static struct list_head *
    467 iptcc_linearly_search_chain_index(const char *name, struct xtc_handle *handle)
    468 {
    469 	unsigned int i=0;
    470 	int res=0;
    471 
    472 	struct list_head *list_pos;
    473 	list_pos = &handle->chains;
    474 
    475 	if (handle->chain_index_sz)
    476 		list_pos = &handle->chain_index[0]->list;
    477 
    478 	/* Linearly walk of chain index array */
    479 
    480 	for (i=0; i < handle->chain_index_sz; i++) {
    481 		if (handle->chain_index[i]) {
    482 			res = strcmp(handle->chain_index[i]->name, name);
    483 			if (res > 0)
    484 				break; // One step too far
    485 			list_pos = &handle->chain_index[i]->list;
    486 			if (res == 0)
    487 				break; // Direct hit
    488 		}
    489 	}
    490 
    491 	return list_pos;
    492 }
    493 #endif
    494 
    495 static int iptcc_chain_index_alloc(struct xtc_handle *h)
    496 {
    497 	unsigned int list_length = CHAIN_INDEX_BUCKET_LEN;
    498 	unsigned int array_elems;
    499 	unsigned int array_mem;
    500 
    501 	/* Allocate memory for the chain index array */
    502 	array_elems = (h->num_chains / list_length) +
    503                       (h->num_chains % list_length ? 1 : 0);
    504 	array_mem   = sizeof(h->chain_index) * array_elems;
    505 
    506 	debug("Alloc Chain index, elems:%d mem:%d bytes\n",
    507 	      array_elems, array_mem);
    508 
    509 	h->chain_index = malloc(array_mem);
    510 	if (h->chain_index == NULL && array_mem > 0) {
    511 		h->chain_index_sz = 0;
    512 		return -ENOMEM;
    513 	}
    514 	memset(h->chain_index, 0, array_mem);
    515 	h->chain_index_sz = array_elems;
    516 
    517 	return 1;
    518 }
    519 
    520 static void iptcc_chain_index_free(struct xtc_handle *h)
    521 {
    522 	h->chain_index_sz = 0;
    523 	free(h->chain_index);
    524 }
    525 
    526 
    527 #ifdef DEBUG
    528 static void iptcc_chain_index_dump(struct xtc_handle *h)
    529 {
    530 	unsigned int i = 0;
    531 
    532 	/* Dump: contents of chain index array */
    533 	for (i=0; i < h->chain_index_sz; i++) {
    534 		if (h->chain_index[i]) {
    535 			fprintf(stderr, "Chain index[%d].name: %s\n",
    536 				i, h->chain_index[i]->name);
    537 		}
    538 	}
    539 }
    540 #endif
    541 
    542 /* Build the chain index */
    543 static int iptcc_chain_index_build(struct xtc_handle *h)
    544 {
    545 	unsigned int list_length = CHAIN_INDEX_BUCKET_LEN;
    546 	unsigned int chains = 0;
    547 	unsigned int cindex = 0;
    548 	struct chain_head *c;
    549 
    550 	/* Build up the chain index array here */
    551 	debug("Building chain index\n");
    552 
    553 	debug("Number of user defined chains:%d bucket_sz:%d array_sz:%d\n",
    554 		h->num_chains, list_length, h->chain_index_sz);
    555 
    556 	if (h->chain_index_sz == 0)
    557 		return 0;
    558 
    559 	list_for_each_entry(c, &h->chains, list) {
    560 
    561 		/* Issue: The index array needs to start after the
    562 		 * builtin chains, as they are not sorted */
    563 		if (!iptcc_is_builtin(c)) {
    564 			cindex=chains / list_length;
    565 
    566 			/* Safe guard, break out on array limit, this
    567 			 * is useful if chains are added and array is
    568 			 * rebuild, without realloc of memory. */
    569 			if (cindex >= h->chain_index_sz)
    570 				break;
    571 
    572 			if ((chains % list_length)== 0) {
    573 				debug("\nIndex[%d] Chains:", cindex);
    574 				h->chain_index[cindex] = c;
    575 			}
    576 			chains++;
    577 		}
    578 		debug("%s, ", c->name);
    579 	}
    580 	debug("\n");
    581 
    582 	return 1;
    583 }
    584 
    585 static int iptcc_chain_index_rebuild(struct xtc_handle *h)
    586 {
    587 	debug("REBUILD chain index array\n");
    588 	iptcc_chain_index_free(h);
    589 	if ((iptcc_chain_index_alloc(h)) < 0)
    590 		return -ENOMEM;
    591 	iptcc_chain_index_build(h);
    592 	return 1;
    593 }
    594 
    595 /* Delete chain (pointer) from index array.  Removing an element from
    596  * the chain list only affects the chain index array, if the chain
    597  * index points-to/uses that list pointer.
    598  *
    599  * There are different strategies, the simple and safe is to rebuild
    600  * the chain index every time.  The more advanced is to update the
    601  * array index to point to the next element, but that requires some
    602  * house keeping and boundry checks.  The advanced is implemented, as
    603  * the simple approach behaves badly when all chains are deleted
    604  * because list_for_each processing will always hit the first chain
    605  * index, thus causing a rebuild for every chain.
    606  */
    607 static int iptcc_chain_index_delete_chain(struct chain_head *c, struct xtc_handle *h)
    608 {
    609 	struct list_head *index_ptr, *next;
    610 	struct chain_head *c2;
    611 	unsigned int idx, idx2;
    612 
    613 	index_ptr = iptcc_bsearch_chain_index(c->name, &idx, h);
    614 
    615 	debug("Del chain[%s] c->list:%p index_ptr:%p\n",
    616 	      c->name, &c->list, index_ptr);
    617 
    618 	/* Save the next pointer */
    619 	next = c->list.next;
    620 	list_del(&c->list);
    621 
    622 	if (index_ptr == &c->list) { /* Chain used as index ptr */
    623 
    624 		/* See if its possible to avoid a rebuild, by shifting
    625 		 * to next pointer.  Its possible if the next pointer
    626 		 * is located in the same index bucket.
    627 		 */
    628 		c2         = list_entry(next, struct chain_head, list);
    629 		iptcc_bsearch_chain_index(c2->name, &idx2, h);
    630 		if (idx != idx2) {
    631 			/* Rebuild needed */
    632 			return iptcc_chain_index_rebuild(h);
    633 		} else {
    634 			/* Avoiding rebuild */
    635 			debug("Update cindex[%d] with next ptr name:[%s]\n",
    636 			      idx, c2->name);
    637 			h->chain_index[idx]=c2;
    638 			return 0;
    639 		}
    640 	}
    641 	return 0;
    642 }
    643 
    644 
    645 /**********************************************************************
    646  * iptc cache utility functions (iptcc_*)
    647  **********************************************************************/
    648 
    649 /* Is the given chain builtin (1) or user-defined (0) */
    650 static inline unsigned int iptcc_is_builtin(struct chain_head *c)
    651 {
    652 	return (c->hooknum ? 1 : 0);
    653 }
    654 
    655 /* Get a specific rule within a chain */
    656 static struct rule_head *iptcc_get_rule_num(struct chain_head *c,
    657 					    unsigned int rulenum)
    658 {
    659 	struct rule_head *r;
    660 	unsigned int num = 0;
    661 
    662 	list_for_each_entry(r, &c->rules, list) {
    663 		num++;
    664 		if (num == rulenum)
    665 			return r;
    666 	}
    667 	return NULL;
    668 }
    669 
    670 /* Get a specific rule within a chain backwards */
    671 static struct rule_head *iptcc_get_rule_num_reverse(struct chain_head *c,
    672 					    unsigned int rulenum)
    673 {
    674 	struct rule_head *r;
    675 	unsigned int num = 0;
    676 
    677 	list_for_each_entry_reverse(r, &c->rules, list) {
    678 		num++;
    679 		if (num == rulenum)
    680 			return r;
    681 	}
    682 	return NULL;
    683 }
    684 
    685 /* Returns chain head if found, otherwise NULL. */
    686 static struct chain_head *
    687 iptcc_find_chain_by_offset(struct xtc_handle *handle, unsigned int offset)
    688 {
    689 	struct list_head *pos;
    690 	struct list_head *list_start_pos;
    691 	unsigned int i;
    692 
    693 	if (list_empty(&handle->chains))
    694 		return NULL;
    695 
    696 	/* Find a smart place to start the search */
    697   	list_start_pos = iptcc_bsearch_chain_offset(offset, &i, handle);
    698 
    699 	/* Note that iptcc_bsearch_chain_offset() skips builtin
    700 	 * chains, but this function is only used for finding jump
    701 	 * targets, and a buildin chain is not a valid jump target */
    702 
    703 	debug("Offset:[%u] starting search at index:[%u]\n", offset, i);
    704 //	list_for_each(pos, &handle->chains) {
    705 	list_for_each(pos, list_start_pos->prev) {
    706 		struct chain_head *c = list_entry(pos, struct chain_head, list);
    707 		debug(".");
    708 		if (offset >= c->head_offset && offset <= c->foot_offset) {
    709 			debug("Offset search found chain:[%s]\n", c->name);
    710 			return c;
    711 		}
    712 	}
    713 
    714 	return NULL;
    715 }
    716 
    717 /* Returns chain head if found, otherwise NULL. */
    718 static struct chain_head *
    719 iptcc_find_label(const char *name, struct xtc_handle *handle)
    720 {
    721 	struct list_head *pos;
    722 	struct list_head *list_start_pos;
    723 	unsigned int i=0;
    724 	int res;
    725 
    726 	if (list_empty(&handle->chains))
    727 		return NULL;
    728 
    729 	/* First look at builtin chains */
    730 	list_for_each(pos, &handle->chains) {
    731 		struct chain_head *c = list_entry(pos, struct chain_head, list);
    732 		if (!iptcc_is_builtin(c))
    733 			break;
    734 		if (!strcmp(c->name, name))
    735 			return c;
    736 	}
    737 
    738 	/* Find a smart place to start the search via chain index */
    739   	//list_start_pos = iptcc_linearly_search_chain_index(name, handle);
    740   	list_start_pos = iptcc_bsearch_chain_index(name, &i, handle);
    741 
    742 	/* Handel if bsearch bails out early */
    743 	if (list_start_pos == &handle->chains) {
    744 		list_start_pos = pos;
    745 	}
    746 #ifdef DEBUG
    747 	else {
    748 		/* Verify result of bsearch against linearly index search */
    749 		struct list_head *test_pos;
    750 		struct chain_head *test_c, *tmp_c;
    751 		test_pos = iptcc_linearly_search_chain_index(name, handle);
    752 		if (list_start_pos != test_pos) {
    753 			debug("BUG in chain_index search\n");
    754 			test_c=list_entry(test_pos,      struct chain_head,list);
    755 			tmp_c =list_entry(list_start_pos,struct chain_head,list);
    756 			debug("Verify search found:\n");
    757 			debug(" Chain:%s\n", test_c->name);
    758 			debug("BSearch found:\n");
    759 			debug(" Chain:%s\n", tmp_c->name);
    760 			exit(42);
    761 		}
    762 	}
    763 #endif
    764 
    765 	/* Initial/special case, no user defined chains */
    766 	if (handle->num_chains == 0)
    767 		return NULL;
    768 
    769 	/* Start searching through the chain list */
    770 	list_for_each(pos, list_start_pos->prev) {
    771 		struct chain_head *c = list_entry(pos, struct chain_head, list);
    772 		res = strcmp(c->name, name);
    773 		debug("List search name:%s == %s res:%d\n", name, c->name, res);
    774 		if (res==0)
    775 			return c;
    776 
    777 		/* We can stop earlier as we know list is sorted */
    778 		if (res>0 && !iptcc_is_builtin(c)) { /* Walked too far*/
    779 			debug(" Not in list, walked too far, sorted list\n");
    780 			return NULL;
    781 		}
    782 
    783 		/* Stop on wrap around, if list head is reached */
    784 		if (pos == &handle->chains) {
    785 			debug("Stop, list head reached\n");
    786 			return NULL;
    787 		}
    788 	}
    789 
    790 	debug("List search NOT found name:%s\n", name);
    791 	return NULL;
    792 }
    793 
    794 /* called when rule is to be removed from cache */
    795 static void iptcc_delete_rule(struct rule_head *r)
    796 {
    797 	DEBUGP("deleting rule %p (offset %u)\n", r, r->offset);
    798 	/* clean up reference count of called chain */
    799 	if (r->type == IPTCC_R_JUMP
    800 	    && r->jump)
    801 		r->jump->references--;
    802 
    803 	list_del(&r->list);
    804 	free(r);
    805 }
    806 
    807 
    808 /**********************************************************************
    809  * RULESET PARSER (blob -> cache)
    810  **********************************************************************/
    811 
    812 /* Delete policy rule of previous chain, since cache doesn't contain
    813  * chain policy rules.
    814  * WARNING: This function has ugly design and relies on a lot of context, only
    815  * to be called from specific places within the parser */
    816 static int __iptcc_p_del_policy(struct xtc_handle *h, unsigned int num)
    817 {
    818 	const unsigned char *data;
    819 
    820 	if (h->chain_iterator_cur) {
    821 		/* policy rule is last rule */
    822 		struct rule_head *pr = (struct rule_head *)
    823 			h->chain_iterator_cur->rules.prev;
    824 
    825 		/* save verdict */
    826 		data = GET_TARGET(pr->entry)->data;
    827 		h->chain_iterator_cur->verdict = *(const int *)data;
    828 
    829 		/* save counter and counter_map information */
    830 		h->chain_iterator_cur->counter_map.maptype =
    831 						COUNTER_MAP_ZEROED;
    832 		h->chain_iterator_cur->counter_map.mappos = num-1;
    833 		memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters,
    834 			sizeof(h->chain_iterator_cur->counters));
    835 
    836 		/* foot_offset points to verdict rule */
    837 		h->chain_iterator_cur->foot_index = num;
    838 		h->chain_iterator_cur->foot_offset = pr->offset;
    839 
    840 		/* delete rule from cache */
    841 		iptcc_delete_rule(pr);
    842 		h->chain_iterator_cur->num_rules--;
    843 
    844 		return 1;
    845 	}
    846 	return 0;
    847 }
    848 
    849 /* alphabetically insert a chain into the list */
    850 static void iptc_insert_chain(struct xtc_handle *h, struct chain_head *c)
    851 {
    852 	struct chain_head *tmp;
    853 	struct list_head  *list_start_pos;
    854 	unsigned int i=1;
    855 
    856 	/* Find a smart place to start the insert search */
    857   	list_start_pos = iptcc_bsearch_chain_index(c->name, &i, h);
    858 
    859 	/* Handle the case, where chain.name is smaller than index[0] */
    860 	if (i==0 && strcmp(c->name, h->chain_index[0]->name) <= 0) {
    861 		h->chain_index[0] = c; /* Update chain index head */
    862 		list_start_pos = h->chains.next;
    863 		debug("Update chain_index[0] with %s\n", c->name);
    864 	}
    865 
    866 	/* Handel if bsearch bails out early */
    867 	if (list_start_pos == &h->chains) {
    868 		list_start_pos = h->chains.next;
    869 	}
    870 
    871 	/* sort only user defined chains */
    872 	if (!c->hooknum) {
    873 		list_for_each_entry(tmp, list_start_pos->prev, list) {
    874 			if (!tmp->hooknum && strcmp(c->name, tmp->name) <= 0) {
    875 				list_add(&c->list, tmp->list.prev);
    876 				return;
    877 			}
    878 
    879 			/* Stop if list head is reached */
    880 			if (&tmp->list == &h->chains) {
    881 				debug("Insert, list head reached add to tail\n");
    882 				break;
    883 			}
    884 		}
    885 	}
    886 
    887 	/* survived till end of list: add at tail */
    888 	list_add_tail(&c->list, &h->chains);
    889 }
    890 
    891 /* Another ugly helper function split out of cache_add_entry to make it less
    892  * spaghetti code */
    893 static void __iptcc_p_add_chain(struct xtc_handle *h, struct chain_head *c,
    894 				unsigned int offset, unsigned int *num)
    895 {
    896 	struct list_head  *tail = h->chains.prev;
    897 	struct chain_head *ctail;
    898 
    899 	__iptcc_p_del_policy(h, *num);
    900 
    901 	c->head_offset = offset;
    902 	c->index = *num;
    903 
    904 	/* Chains from kernel are already sorted, as they are inserted
    905 	 * sorted. But there exists an issue when shifting to 1.4.0
    906 	 * from an older version, as old versions allow last created
    907 	 * chain to be unsorted.
    908 	 */
    909 	if (iptcc_is_builtin(c)) /* Only user defined chains are sorted*/
    910 		list_add_tail(&c->list, &h->chains);
    911 	else {
    912 		ctail = list_entry(tail, struct chain_head, list);
    913 
    914 		if (strcmp(c->name, ctail->name) > 0 ||
    915 		    iptcc_is_builtin(ctail))
    916 			list_add_tail(&c->list, &h->chains);/* Already sorted*/
    917 		else {
    918 			iptc_insert_chain(h, c);/* Was not sorted */
    919 
    920 			/* Notice, if chains were not received sorted
    921 			 * from kernel, then an offset bsearch is no
    922 			 * longer valid.
    923 			 */
    924 			h->sorted_offsets = 0;
    925 
    926 			debug("NOTICE: chain:[%s] was NOT sorted(ctail:%s)\n",
    927 			      c->name, ctail->name);
    928 		}
    929 	}
    930 
    931 	h->chain_iterator_cur = c;
    932 }
    933 
    934 /* main parser function: add an entry from the blob to the cache */
    935 static int cache_add_entry(STRUCT_ENTRY *e,
    936 			   struct xtc_handle *h,
    937 			   STRUCT_ENTRY **prev,
    938 			   unsigned int *num)
    939 {
    940 	unsigned int builtin;
    941 	unsigned int offset = (char *)e - (char *)h->entries->entrytable;
    942 
    943 	DEBUGP("entering...");
    944 
    945 	/* Last entry ("policy rule"). End it.*/
    946 	if (iptcb_entry2offset(h,e) + e->next_offset == h->entries->size) {
    947 		/* This is the ERROR node at the end of the chain */
    948 		DEBUGP_C("%u:%u: end of table:\n", *num, offset);
    949 
    950 		__iptcc_p_del_policy(h, *num);
    951 
    952 		h->chain_iterator_cur = NULL;
    953 		goto out_inc;
    954 	}
    955 
    956 	/* We know this is the start of a new chain if it's an ERROR
    957 	 * target, or a hook entry point */
    958 
    959 	if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) {
    960 		struct chain_head *c =
    961 			iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0);
    962 		DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset,
    963 			(char *)c->name, c);
    964 		if (!c) {
    965 			errno = -ENOMEM;
    966 			return -1;
    967 		}
    968 		h->num_chains++; /* New user defined chain */
    969 
    970 		__iptcc_p_add_chain(h, c, offset, num);
    971 
    972 	} else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) {
    973 		struct chain_head *c =
    974 			iptcc_alloc_chain_head((char *)hooknames[builtin-1],
    975 						builtin);
    976 		DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n",
    977 			*num, offset, c, &c->rules);
    978 		if (!c) {
    979 			errno = -ENOMEM;
    980 			return -1;
    981 		}
    982 
    983 		c->hooknum = builtin;
    984 
    985 		__iptcc_p_add_chain(h, c, offset, num);
    986 
    987 		/* FIXME: this is ugly. */
    988 		goto new_rule;
    989 	} else {
    990 		/* has to be normal rule */
    991 		struct rule_head *r;
    992 new_rule:
    993 
    994 		if (!(r = iptcc_alloc_rule(h->chain_iterator_cur,
    995 					   e->next_offset))) {
    996 			errno = ENOMEM;
    997 			return -1;
    998 		}
    999 		DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r);
   1000 
   1001 		r->index = *num;
   1002 		r->offset = offset;
   1003 		memcpy(r->entry, e, e->next_offset);
   1004 		r->counter_map.maptype = COUNTER_MAP_NORMAL_MAP;
   1005 		r->counter_map.mappos = r->index;
   1006 
   1007 		/* handling of jumps, etc. */
   1008 		if (!strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET)) {
   1009 			STRUCT_STANDARD_TARGET *t;
   1010 
   1011 			t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
   1012 			if (t->target.u.target_size
   1013 			    != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) {
   1014 				errno = EINVAL;
   1015 				free(r);
   1016 				return -1;
   1017 			}
   1018 
   1019 			if (t->verdict < 0) {
   1020 				DEBUGP_C("standard, verdict=%d\n", t->verdict);
   1021 				r->type = IPTCC_R_STANDARD;
   1022 			} else if (t->verdict == r->offset+e->next_offset) {
   1023 				DEBUGP_C("fallthrough\n");
   1024 				r->type = IPTCC_R_FALLTHROUGH;
   1025 			} else {
   1026 				DEBUGP_C("jump, target=%u\n", t->verdict);
   1027 				r->type = IPTCC_R_JUMP;
   1028 				/* Jump target fixup has to be deferred
   1029 				 * until second pass, since we migh not
   1030 				 * yet have parsed the target */
   1031 			}
   1032 		} else {
   1033 			DEBUGP_C("module, target=%s\n", GET_TARGET(e)->u.user.name);
   1034 			r->type = IPTCC_R_MODULE;
   1035 		}
   1036 
   1037 		list_add_tail(&r->list, &h->chain_iterator_cur->rules);
   1038 		h->chain_iterator_cur->num_rules++;
   1039 	}
   1040 out_inc:
   1041 	(*num)++;
   1042 	return 0;
   1043 }
   1044 
   1045 
   1046 /* parse an iptables blob into it's pieces */
   1047 static int parse_table(struct xtc_handle *h)
   1048 {
   1049 	STRUCT_ENTRY *prev;
   1050 	unsigned int num = 0;
   1051 	struct chain_head *c;
   1052 
   1053 	/* Assume that chains offsets are sorted, this verified during
   1054 	   parsing of ruleset (in __iptcc_p_add_chain())*/
   1055 	h->sorted_offsets = 1;
   1056 
   1057 	/* First pass: over ruleset blob */
   1058 	ENTRY_ITERATE(h->entries->entrytable, h->entries->size,
   1059 			cache_add_entry, h, &prev, &num);
   1060 
   1061 	/* Build the chain index, used for chain list search speedup */
   1062 	if ((iptcc_chain_index_alloc(h)) < 0)
   1063 		return -ENOMEM;
   1064 	iptcc_chain_index_build(h);
   1065 
   1066 	/* Second pass: fixup parsed data from first pass */
   1067 	list_for_each_entry(c, &h->chains, list) {
   1068 		struct rule_head *r;
   1069 		list_for_each_entry(r, &c->rules, list) {
   1070 			struct chain_head *lc;
   1071 			STRUCT_STANDARD_TARGET *t;
   1072 
   1073 			if (r->type != IPTCC_R_JUMP)
   1074 				continue;
   1075 
   1076 			t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
   1077 			lc = iptcc_find_chain_by_offset(h, t->verdict);
   1078 			if (!lc)
   1079 				return -1;
   1080 			r->jump = lc;
   1081 			lc->references++;
   1082 		}
   1083 	}
   1084 
   1085 	return 1;
   1086 }
   1087 
   1088 
   1089 /**********************************************************************
   1090  * RULESET COMPILATION (cache -> blob)
   1091  **********************************************************************/
   1092 
   1093 /* Convenience structures */
   1094 struct iptcb_chain_start{
   1095 	STRUCT_ENTRY e;
   1096 	struct xt_error_target name;
   1097 };
   1098 #define IPTCB_CHAIN_START_SIZE	(sizeof(STRUCT_ENTRY) +			\
   1099 				 ALIGN(sizeof(struct xt_error_target)))
   1100 
   1101 struct iptcb_chain_foot {
   1102 	STRUCT_ENTRY e;
   1103 	STRUCT_STANDARD_TARGET target;
   1104 };
   1105 #define IPTCB_CHAIN_FOOT_SIZE	(sizeof(STRUCT_ENTRY) +			\
   1106 				 ALIGN(sizeof(STRUCT_STANDARD_TARGET)))
   1107 
   1108 struct iptcb_chain_error {
   1109 	STRUCT_ENTRY entry;
   1110 	struct xt_error_target target;
   1111 };
   1112 #define IPTCB_CHAIN_ERROR_SIZE	(sizeof(STRUCT_ENTRY) +			\
   1113 				 ALIGN(sizeof(struct xt_error_target)))
   1114 
   1115 
   1116 
   1117 /* compile rule from cache into blob */
   1118 static inline int iptcc_compile_rule (struct xtc_handle *h, STRUCT_REPLACE *repl, struct rule_head *r)
   1119 {
   1120 	/* handle jumps */
   1121 	if (r->type == IPTCC_R_JUMP) {
   1122 		STRUCT_STANDARD_TARGET *t;
   1123 		t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
   1124 		/* memset for memcmp convenience on delete/replace */
   1125 		memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
   1126 		strcpy(t->target.u.user.name, STANDARD_TARGET);
   1127 		/* Jumps can only happen to builtin chains, so we
   1128 		 * can safely assume that they always have a header */
   1129 		t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE;
   1130 	} else if (r->type == IPTCC_R_FALLTHROUGH) {
   1131 		STRUCT_STANDARD_TARGET *t;
   1132 		t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
   1133 		t->verdict = r->offset + r->size;
   1134 	}
   1135 
   1136 	/* copy entry from cache to blob */
   1137 	memcpy((char *)repl->entries+r->offset, r->entry, r->size);
   1138 
   1139 	return 1;
   1140 }
   1141 
   1142 /* compile chain from cache into blob */
   1143 static int iptcc_compile_chain(struct xtc_handle *h, STRUCT_REPLACE *repl, struct chain_head *c)
   1144 {
   1145 	int ret;
   1146 	struct rule_head *r;
   1147 	struct iptcb_chain_start *head;
   1148 	struct iptcb_chain_foot *foot;
   1149 
   1150 	/* only user-defined chains have heaer */
   1151 	if (!iptcc_is_builtin(c)) {
   1152 		/* put chain header in place */
   1153 		head = (void *)repl->entries + c->head_offset;
   1154 		head->e.target_offset = sizeof(STRUCT_ENTRY);
   1155 		head->e.next_offset = IPTCB_CHAIN_START_SIZE;
   1156 		strcpy(head->name.target.u.user.name, ERROR_TARGET);
   1157 		head->name.target.u.target_size =
   1158 				ALIGN(sizeof(struct xt_error_target));
   1159 		strcpy(head->name.errorname, c->name);
   1160 	} else {
   1161 		repl->hook_entry[c->hooknum-1] = c->head_offset;
   1162 		repl->underflow[c->hooknum-1] = c->foot_offset;
   1163 	}
   1164 
   1165 	/* iterate over rules */
   1166 	list_for_each_entry(r, &c->rules, list) {
   1167 		ret = iptcc_compile_rule(h, repl, r);
   1168 		if (ret < 0)
   1169 			return ret;
   1170 	}
   1171 
   1172 	/* put chain footer in place */
   1173 	foot = (void *)repl->entries + c->foot_offset;
   1174 	foot->e.target_offset = sizeof(STRUCT_ENTRY);
   1175 	foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE;
   1176 	strcpy(foot->target.target.u.user.name, STANDARD_TARGET);
   1177 	foot->target.target.u.target_size =
   1178 				ALIGN(sizeof(STRUCT_STANDARD_TARGET));
   1179 	/* builtin targets have verdict, others return */
   1180 	if (iptcc_is_builtin(c))
   1181 		foot->target.verdict = c->verdict;
   1182 	else
   1183 		foot->target.verdict = RETURN;
   1184 	/* set policy-counters */
   1185 	memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS));
   1186 
   1187 	return 0;
   1188 }
   1189 
   1190 /* calculate offset and number for every rule in the cache */
   1191 static int iptcc_compile_chain_offsets(struct xtc_handle *h, struct chain_head *c,
   1192 				       unsigned int *offset, unsigned int *num)
   1193 {
   1194 	struct rule_head *r;
   1195 
   1196 	c->head_offset = *offset;
   1197 	DEBUGP("%s: chain_head %u, offset=%u\n", c->name, *num, *offset);
   1198 
   1199 	if (!iptcc_is_builtin(c))  {
   1200 		/* Chain has header */
   1201 		*offset += sizeof(STRUCT_ENTRY)
   1202 			     + ALIGN(sizeof(struct xt_error_target));
   1203 		(*num)++;
   1204 	}
   1205 
   1206 	list_for_each_entry(r, &c->rules, list) {
   1207 		DEBUGP("rule %u, offset=%u, index=%u\n", *num, *offset, *num);
   1208 		r->offset = *offset;
   1209 		r->index = *num;
   1210 		*offset += r->size;
   1211 		(*num)++;
   1212 	}
   1213 
   1214 	DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num,
   1215 		*offset, *num);
   1216 	c->foot_offset = *offset;
   1217 	c->foot_index = *num;
   1218 	*offset += sizeof(STRUCT_ENTRY)
   1219 		   + ALIGN(sizeof(STRUCT_STANDARD_TARGET));
   1220 	(*num)++;
   1221 
   1222 	return 1;
   1223 }
   1224 
   1225 /* put the pieces back together again */
   1226 static int iptcc_compile_table_prep(struct xtc_handle *h, unsigned int *size)
   1227 {
   1228 	struct chain_head *c;
   1229 	unsigned int offset = 0, num = 0;
   1230 	int ret = 0;
   1231 
   1232 	/* First pass: calculate offset for every rule */
   1233 	list_for_each_entry(c, &h->chains, list) {
   1234 		ret = iptcc_compile_chain_offsets(h, c, &offset, &num);
   1235 		if (ret < 0)
   1236 			return ret;
   1237 	}
   1238 
   1239 	/* Append one error rule at end of chain */
   1240 	num++;
   1241 	offset += sizeof(STRUCT_ENTRY)
   1242 		  + ALIGN(sizeof(struct xt_error_target));
   1243 
   1244 	/* ruleset size is now in offset */
   1245 	*size = offset;
   1246 	return num;
   1247 }
   1248 
   1249 static int iptcc_compile_table(struct xtc_handle *h, STRUCT_REPLACE *repl)
   1250 {
   1251 	struct chain_head *c;
   1252 	struct iptcb_chain_error *error;
   1253 
   1254 	/* Second pass: copy from cache to offsets, fill in jumps */
   1255 	list_for_each_entry(c, &h->chains, list) {
   1256 		int ret = iptcc_compile_chain(h, repl, c);
   1257 		if (ret < 0)
   1258 			return ret;
   1259 	}
   1260 
   1261 	/* Append error rule at end of chain */
   1262 	error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE;
   1263 	error->entry.target_offset = sizeof(STRUCT_ENTRY);
   1264 	error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE;
   1265 	error->target.target.u.user.target_size =
   1266 		ALIGN(sizeof(struct xt_error_target));
   1267 	strcpy((char *)&error->target.target.u.user.name, ERROR_TARGET);
   1268 	strcpy((char *)&error->target.errorname, "ERROR");
   1269 
   1270 	return 1;
   1271 }
   1272 
   1273 /**********************************************************************
   1274  * EXTERNAL API (operates on cache only)
   1275  **********************************************************************/
   1276 
   1277 /* Allocate handle of given size */
   1278 static struct xtc_handle *
   1279 alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
   1280 {
   1281 	struct xtc_handle *h;
   1282 
   1283 	h = malloc(sizeof(*h));
   1284 	if (!h) {
   1285 		errno = ENOMEM;
   1286 		return NULL;
   1287 	}
   1288 	memset(h, 0, sizeof(*h));
   1289 	INIT_LIST_HEAD(&h->chains);
   1290 	strcpy(h->info.name, tablename);
   1291 
   1292 	h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size);
   1293 	if (!h->entries)
   1294 		goto out_free_handle;
   1295 
   1296 	strcpy(h->entries->name, tablename);
   1297 	h->entries->size = size;
   1298 
   1299 	return h;
   1300 
   1301 out_free_handle:
   1302 	free(h);
   1303 
   1304 	return NULL;
   1305 }
   1306 
   1307 
   1308 struct xtc_handle *
   1309 TC_INIT(const char *tablename)
   1310 {
   1311 	struct xtc_handle *h;
   1312 	STRUCT_GETINFO info;
   1313 	unsigned int tmp;
   1314 	socklen_t s;
   1315 	int sockfd;
   1316 
   1317 retry:
   1318 	iptc_fn = TC_INIT;
   1319 
   1320 	if (strlen(tablename) >= TABLE_MAXNAMELEN) {
   1321 		errno = EINVAL;
   1322 		return NULL;
   1323 	}
   1324 
   1325 	sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);
   1326 	if (sockfd < 0)
   1327 		return NULL;
   1328 
   1329 	if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) {
   1330 		fprintf(stderr, "Could not set close on exec: %s\n",
   1331 			strerror(errno));
   1332 		abort();
   1333 	}
   1334 
   1335 	s = sizeof(info);
   1336 
   1337 	strcpy(info.name, tablename);
   1338 	if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) {
   1339 		close(sockfd);
   1340 		return NULL;
   1341 	}
   1342 
   1343 	DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n",
   1344 		info.valid_hooks, info.num_entries, info.size);
   1345 
   1346 	if ((h = alloc_handle(info.name, info.size, info.num_entries))
   1347 	    == NULL) {
   1348 		close(sockfd);
   1349 		return NULL;
   1350 	}
   1351 
   1352 	/* Initialize current state */
   1353 	h->sockfd = sockfd;
   1354 	h->info = info;
   1355 
   1356 	h->entries->size = h->info.size;
   1357 
   1358 	tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size;
   1359 
   1360 	if (getsockopt(h->sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries,
   1361 		       &tmp) < 0)
   1362 		goto error;
   1363 
   1364 #ifdef IPTC_DEBUG2
   1365 	{
   1366 		int fd = open("/tmp/libiptc-so_get_entries.blob",
   1367 				O_CREAT|O_WRONLY);
   1368 		if (fd >= 0) {
   1369 			write(fd, h->entries, tmp);
   1370 			close(fd);
   1371 		}
   1372 	}
   1373 #endif
   1374 
   1375 	if (parse_table(h) < 0)
   1376 		goto error;
   1377 
   1378 	CHECK(h);
   1379 	return h;
   1380 error:
   1381 	TC_FREE(h);
   1382 	/* A different process changed the ruleset size, retry */
   1383 	if (errno == EAGAIN)
   1384 		goto retry;
   1385 	return NULL;
   1386 }
   1387 
   1388 void
   1389 TC_FREE(struct xtc_handle *h)
   1390 {
   1391 	struct chain_head *c, *tmp;
   1392 
   1393 	iptc_fn = TC_FREE;
   1394 	close(h->sockfd);
   1395 
   1396 	list_for_each_entry_safe(c, tmp, &h->chains, list) {
   1397 		struct rule_head *r, *rtmp;
   1398 
   1399 		list_for_each_entry_safe(r, rtmp, &c->rules, list) {
   1400 			free(r);
   1401 		}
   1402 
   1403 		free(c);
   1404 	}
   1405 
   1406 	iptcc_chain_index_free(h);
   1407 
   1408 	free(h->entries);
   1409 	free(h);
   1410 }
   1411 
   1412 static inline int
   1413 print_match(const STRUCT_ENTRY_MATCH *m)
   1414 {
   1415 	printf("Match name: `%s'\n", m->u.user.name);
   1416 	return 0;
   1417 }
   1418 
   1419 static int dump_entry(STRUCT_ENTRY *e, struct xtc_handle *const handle);
   1420 
   1421 void
   1422 TC_DUMP_ENTRIES(struct xtc_handle *const handle)
   1423 {
   1424 	iptc_fn = TC_DUMP_ENTRIES;
   1425 	CHECK(handle);
   1426 
   1427 	printf("libiptc v%s. %u bytes.\n",
   1428 	       XTABLES_VERSION, handle->entries->size);
   1429 	printf("Table `%s'\n", handle->info.name);
   1430 	printf("Hooks: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n",
   1431 	       handle->info.hook_entry[HOOK_PRE_ROUTING],
   1432 	       handle->info.hook_entry[HOOK_LOCAL_IN],
   1433 	       handle->info.hook_entry[HOOK_FORWARD],
   1434 	       handle->info.hook_entry[HOOK_LOCAL_OUT],
   1435 	       handle->info.hook_entry[HOOK_POST_ROUTING]);
   1436 	printf("Underflows: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n",
   1437 	       handle->info.underflow[HOOK_PRE_ROUTING],
   1438 	       handle->info.underflow[HOOK_LOCAL_IN],
   1439 	       handle->info.underflow[HOOK_FORWARD],
   1440 	       handle->info.underflow[HOOK_LOCAL_OUT],
   1441 	       handle->info.underflow[HOOK_POST_ROUTING]);
   1442 
   1443 	ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size,
   1444 		      dump_entry, handle);
   1445 }
   1446 
   1447 /* Does this chain exist? */
   1448 int TC_IS_CHAIN(const char *chain, struct xtc_handle *const handle)
   1449 {
   1450 	iptc_fn = TC_IS_CHAIN;
   1451 	return iptcc_find_label(chain, handle) != NULL;
   1452 }
   1453 
   1454 static void iptcc_chain_iterator_advance(struct xtc_handle *handle)
   1455 {
   1456 	struct chain_head *c = handle->chain_iterator_cur;
   1457 
   1458 	if (c->list.next == &handle->chains)
   1459 		handle->chain_iterator_cur = NULL;
   1460 	else
   1461 		handle->chain_iterator_cur =
   1462 			list_entry(c->list.next, struct chain_head, list);
   1463 }
   1464 
   1465 /* Iterator functions to run through the chains. */
   1466 const char *
   1467 TC_FIRST_CHAIN(struct xtc_handle *handle)
   1468 {
   1469 	struct chain_head *c = list_entry(handle->chains.next,
   1470 					  struct chain_head, list);
   1471 
   1472 	iptc_fn = TC_FIRST_CHAIN;
   1473 
   1474 
   1475 	if (list_empty(&handle->chains)) {
   1476 		DEBUGP(": no chains\n");
   1477 		return NULL;
   1478 	}
   1479 
   1480 	handle->chain_iterator_cur = c;
   1481 	iptcc_chain_iterator_advance(handle);
   1482 
   1483 	DEBUGP(": returning `%s'\n", c->name);
   1484 	return c->name;
   1485 }
   1486 
   1487 /* Iterator functions to run through the chains.  Returns NULL at end. */
   1488 const char *
   1489 TC_NEXT_CHAIN(struct xtc_handle *handle)
   1490 {
   1491 	struct chain_head *c = handle->chain_iterator_cur;
   1492 
   1493 	iptc_fn = TC_NEXT_CHAIN;
   1494 
   1495 	if (!c) {
   1496 		DEBUGP(": no more chains\n");
   1497 		return NULL;
   1498 	}
   1499 
   1500 	iptcc_chain_iterator_advance(handle);
   1501 
   1502 	DEBUGP(": returning `%s'\n", c->name);
   1503 	return c->name;
   1504 }
   1505 
   1506 /* Get first rule in the given chain: NULL for empty chain. */
   1507 const STRUCT_ENTRY *
   1508 TC_FIRST_RULE(const char *chain, struct xtc_handle *handle)
   1509 {
   1510 	struct chain_head *c;
   1511 	struct rule_head *r;
   1512 
   1513 	iptc_fn = TC_FIRST_RULE;
   1514 
   1515 	DEBUGP("first rule(%s): ", chain);
   1516 
   1517 	c = iptcc_find_label(chain, handle);
   1518 	if (!c) {
   1519 		errno = ENOENT;
   1520 		return NULL;
   1521 	}
   1522 
   1523 	/* Empty chain: single return/policy rule */
   1524 	if (list_empty(&c->rules)) {
   1525 		DEBUGP_C("no rules, returning NULL\n");
   1526 		return NULL;
   1527 	}
   1528 
   1529 	r = list_entry(c->rules.next, struct rule_head, list);
   1530 	handle->rule_iterator_cur = r;
   1531 	DEBUGP_C("%p\n", r);
   1532 
   1533 	return r->entry;
   1534 }
   1535 
   1536 /* Returns NULL when rules run out. */
   1537 const STRUCT_ENTRY *
   1538 TC_NEXT_RULE(const STRUCT_ENTRY *prev, struct xtc_handle *handle)
   1539 {
   1540 	struct rule_head *r;
   1541 
   1542 	iptc_fn = TC_NEXT_RULE;
   1543 	DEBUGP("rule_iterator_cur=%p...", handle->rule_iterator_cur);
   1544 
   1545 	if (handle->rule_iterator_cur == NULL) {
   1546 		DEBUGP_C("returning NULL\n");
   1547 		return NULL;
   1548 	}
   1549 
   1550 	r = list_entry(handle->rule_iterator_cur->list.next,
   1551 			struct rule_head, list);
   1552 
   1553 	iptc_fn = TC_NEXT_RULE;
   1554 
   1555 	DEBUGP_C("next=%p, head=%p...", &r->list,
   1556 		&handle->rule_iterator_cur->chain->rules);
   1557 
   1558 	if (&r->list == &handle->rule_iterator_cur->chain->rules) {
   1559 		handle->rule_iterator_cur = NULL;
   1560 		DEBUGP_C("finished, returning NULL\n");
   1561 		return NULL;
   1562 	}
   1563 
   1564 	handle->rule_iterator_cur = r;
   1565 
   1566 	/* NOTE: prev is without any influence ! */
   1567 	DEBUGP_C("returning rule %p\n", r);
   1568 	return r->entry;
   1569 }
   1570 
   1571 /* Returns a pointer to the target name of this position. */
   1572 static const char *standard_target_map(int verdict)
   1573 {
   1574 	switch (verdict) {
   1575 		case RETURN:
   1576 			return LABEL_RETURN;
   1577 			break;
   1578 		case -NF_ACCEPT-1:
   1579 			return LABEL_ACCEPT;
   1580 			break;
   1581 		case -NF_DROP-1:
   1582 			return LABEL_DROP;
   1583 			break;
   1584 		case -NF_QUEUE-1:
   1585 			return LABEL_QUEUE;
   1586 			break;
   1587 		default:
   1588 			fprintf(stderr, "ERROR: %d not a valid target)\n",
   1589 				verdict);
   1590 			abort();
   1591 			break;
   1592 	}
   1593 	/* not reached */
   1594 	return NULL;
   1595 }
   1596 
   1597 /* Returns a pointer to the target name of this position. */
   1598 const char *TC_GET_TARGET(const STRUCT_ENTRY *ce,
   1599 			  struct xtc_handle *handle)
   1600 {
   1601 	STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce;
   1602 	struct rule_head *r = container_of(e, struct rule_head, entry[0]);
   1603 	const unsigned char *data;
   1604 
   1605 	iptc_fn = TC_GET_TARGET;
   1606 
   1607 	switch(r->type) {
   1608 		int spos;
   1609 		case IPTCC_R_FALLTHROUGH:
   1610 			return "";
   1611 			break;
   1612 		case IPTCC_R_JUMP:
   1613 			DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name);
   1614 			return r->jump->name;
   1615 			break;
   1616 		case IPTCC_R_STANDARD:
   1617 			data = GET_TARGET(e)->data;
   1618 			spos = *(const int *)data;
   1619 			DEBUGP("r=%p, spos=%d'\n", r, spos);
   1620 			return standard_target_map(spos);
   1621 			break;
   1622 		case IPTCC_R_MODULE:
   1623 			return GET_TARGET(e)->u.user.name;
   1624 			break;
   1625 	}
   1626 	return NULL;
   1627 }
   1628 /* Is this a built-in chain?  Actually returns hook + 1. */
   1629 int
   1630 TC_BUILTIN(const char *chain, struct xtc_handle *const handle)
   1631 {
   1632 	struct chain_head *c;
   1633 
   1634 	iptc_fn = TC_BUILTIN;
   1635 
   1636 	c = iptcc_find_label(chain, handle);
   1637 	if (!c) {
   1638 		errno = ENOENT;
   1639 		return 0;
   1640 	}
   1641 
   1642 	return iptcc_is_builtin(c);
   1643 }
   1644 
   1645 /* Get the policy of a given built-in chain */
   1646 const char *
   1647 TC_GET_POLICY(const char *chain,
   1648 	      STRUCT_COUNTERS *counters,
   1649 	      struct xtc_handle *handle)
   1650 {
   1651 	struct chain_head *c;
   1652 
   1653 	iptc_fn = TC_GET_POLICY;
   1654 
   1655 	DEBUGP("called for chain %s\n", chain);
   1656 
   1657 	c = iptcc_find_label(chain, handle);
   1658 	if (!c) {
   1659 		errno = ENOENT;
   1660 		return NULL;
   1661 	}
   1662 
   1663 	if (!iptcc_is_builtin(c))
   1664 		return NULL;
   1665 
   1666 	*counters = c->counters;
   1667 
   1668 	return standard_target_map(c->verdict);
   1669 }
   1670 
   1671 static int
   1672 iptcc_standard_map(struct rule_head *r, int verdict)
   1673 {
   1674 	STRUCT_ENTRY *e = r->entry;
   1675 	STRUCT_STANDARD_TARGET *t;
   1676 
   1677 	t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
   1678 
   1679 	if (t->target.u.target_size
   1680 	    != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) {
   1681 		errno = EINVAL;
   1682 		return 0;
   1683 	}
   1684 	/* memset for memcmp convenience on delete/replace */
   1685 	memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
   1686 	strcpy(t->target.u.user.name, STANDARD_TARGET);
   1687 	t->verdict = verdict;
   1688 
   1689 	r->type = IPTCC_R_STANDARD;
   1690 
   1691 	return 1;
   1692 }
   1693 
   1694 static int
   1695 iptcc_map_target(struct xtc_handle *const handle,
   1696 	   struct rule_head *r)
   1697 {
   1698 	STRUCT_ENTRY *e = r->entry;
   1699 	STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
   1700 
   1701 	/* Maybe it's empty (=> fall through) */
   1702 	if (strcmp(t->u.user.name, "") == 0) {
   1703 		r->type = IPTCC_R_FALLTHROUGH;
   1704 		return 1;
   1705 	}
   1706 	/* Maybe it's a standard target name... */
   1707 	else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0)
   1708 		return iptcc_standard_map(r, -NF_ACCEPT - 1);
   1709 	else if (strcmp(t->u.user.name, LABEL_DROP) == 0)
   1710 		return iptcc_standard_map(r, -NF_DROP - 1);
   1711 	else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0)
   1712 		return iptcc_standard_map(r, -NF_QUEUE - 1);
   1713 	else if (strcmp(t->u.user.name, LABEL_RETURN) == 0)
   1714 		return iptcc_standard_map(r, RETURN);
   1715 	else if (TC_BUILTIN(t->u.user.name, handle)) {
   1716 		/* Can't jump to builtins. */
   1717 		errno = EINVAL;
   1718 		return 0;
   1719 	} else {
   1720 		/* Maybe it's an existing chain name. */
   1721 		struct chain_head *c;
   1722 		DEBUGP("trying to find chain `%s': ", t->u.user.name);
   1723 
   1724 		c = iptcc_find_label(t->u.user.name, handle);
   1725 		if (c) {
   1726 			DEBUGP_C("found!\n");
   1727 			r->type = IPTCC_R_JUMP;
   1728 			r->jump = c;
   1729 			c->references++;
   1730 			return 1;
   1731 		}
   1732 		DEBUGP_C("not found :(\n");
   1733 	}
   1734 
   1735 	/* Must be a module?  If not, kernel will reject... */
   1736 	/* memset to all 0 for your memcmp convenience: don't clear version */
   1737 	memset(t->u.user.name + strlen(t->u.user.name),
   1738 	       0,
   1739 	       FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name));
   1740 	r->type = IPTCC_R_MODULE;
   1741 	set_changed(handle);
   1742 	return 1;
   1743 }
   1744 
   1745 /* Insert the entry `fw' in chain `chain' into position `rulenum'. */
   1746 int
   1747 TC_INSERT_ENTRY(const IPT_CHAINLABEL chain,
   1748 		const STRUCT_ENTRY *e,
   1749 		unsigned int rulenum,
   1750 		struct xtc_handle *handle)
   1751 {
   1752 	struct chain_head *c;
   1753 	struct rule_head *r;
   1754 	struct list_head *prev;
   1755 
   1756 	iptc_fn = TC_INSERT_ENTRY;
   1757 
   1758 	if (!(c = iptcc_find_label(chain, handle))) {
   1759 		errno = ENOENT;
   1760 		return 0;
   1761 	}
   1762 
   1763 	/* first rulenum index = 0
   1764 	   first c->num_rules index = 1 */
   1765 	if (rulenum > c->num_rules) {
   1766 		errno = E2BIG;
   1767 		return 0;
   1768 	}
   1769 
   1770 	/* If we are inserting at the end just take advantage of the
   1771 	   double linked list, insert will happen before the entry
   1772 	   prev points to. */
   1773 	if (rulenum == c->num_rules) {
   1774 		prev = &c->rules;
   1775 	} else if (rulenum + 1 <= c->num_rules/2) {
   1776 		r = iptcc_get_rule_num(c, rulenum + 1);
   1777 		prev = &r->list;
   1778 	} else {
   1779 		r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum);
   1780 		prev = &r->list;
   1781 	}
   1782 
   1783 	if (!(r = iptcc_alloc_rule(c, e->next_offset))) {
   1784 		errno = ENOMEM;
   1785 		return 0;
   1786 	}
   1787 
   1788 	memcpy(r->entry, e, e->next_offset);
   1789 	r->counter_map.maptype = COUNTER_MAP_SET;
   1790 
   1791 	if (!iptcc_map_target(handle, r)) {
   1792 		free(r);
   1793 		return 0;
   1794 	}
   1795 
   1796 	list_add_tail(&r->list, prev);
   1797 	c->num_rules++;
   1798 
   1799 	set_changed(handle);
   1800 
   1801 	return 1;
   1802 }
   1803 
   1804 /* Atomically replace rule `rulenum' in `chain' with `fw'. */
   1805 int
   1806 TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain,
   1807 		 const STRUCT_ENTRY *e,
   1808 		 unsigned int rulenum,
   1809 		 struct xtc_handle *handle)
   1810 {
   1811 	struct chain_head *c;
   1812 	struct rule_head *r, *old;
   1813 
   1814 	iptc_fn = TC_REPLACE_ENTRY;
   1815 
   1816 	if (!(c = iptcc_find_label(chain, handle))) {
   1817 		errno = ENOENT;
   1818 		return 0;
   1819 	}
   1820 
   1821 	if (rulenum >= c->num_rules) {
   1822 		errno = E2BIG;
   1823 		return 0;
   1824 	}
   1825 
   1826 	/* Take advantage of the double linked list if possible. */
   1827 	if (rulenum + 1 <= c->num_rules/2) {
   1828 		old = iptcc_get_rule_num(c, rulenum + 1);
   1829 	} else {
   1830 		old = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum);
   1831 	}
   1832 
   1833 	if (!(r = iptcc_alloc_rule(c, e->next_offset))) {
   1834 		errno = ENOMEM;
   1835 		return 0;
   1836 	}
   1837 
   1838 	memcpy(r->entry, e, e->next_offset);
   1839 	r->counter_map.maptype = COUNTER_MAP_SET;
   1840 
   1841 	if (!iptcc_map_target(handle, r)) {
   1842 		free(r);
   1843 		return 0;
   1844 	}
   1845 
   1846 	list_add(&r->list, &old->list);
   1847 	iptcc_delete_rule(old);
   1848 
   1849 	set_changed(handle);
   1850 
   1851 	return 1;
   1852 }
   1853 
   1854 /* Append entry `fw' to chain `chain'.  Equivalent to insert with
   1855    rulenum = length of chain. */
   1856 int
   1857 TC_APPEND_ENTRY(const IPT_CHAINLABEL chain,
   1858 		const STRUCT_ENTRY *e,
   1859 		struct xtc_handle *handle)
   1860 {
   1861 	struct chain_head *c;
   1862 	struct rule_head *r;
   1863 
   1864 	iptc_fn = TC_APPEND_ENTRY;
   1865 	if (!(c = iptcc_find_label(chain, handle))) {
   1866 		DEBUGP("unable to find chain `%s'\n", chain);
   1867 		errno = ENOENT;
   1868 		return 0;
   1869 	}
   1870 
   1871 	if (!(r = iptcc_alloc_rule(c, e->next_offset))) {
   1872 		DEBUGP("unable to allocate rule for chain `%s'\n", chain);
   1873 		errno = ENOMEM;
   1874 		return 0;
   1875 	}
   1876 
   1877 	memcpy(r->entry, e, e->next_offset);
   1878 	r->counter_map.maptype = COUNTER_MAP_SET;
   1879 
   1880 	if (!iptcc_map_target(handle, r)) {
   1881 		DEBUGP("unable to map target of rule for chain `%s'\n", chain);
   1882 		free(r);
   1883 		return 0;
   1884 	}
   1885 
   1886 	list_add_tail(&r->list, &c->rules);
   1887 	c->num_rules++;
   1888 
   1889 	set_changed(handle);
   1890 
   1891 	return 1;
   1892 }
   1893 
   1894 static inline int
   1895 match_different(const STRUCT_ENTRY_MATCH *a,
   1896 		const unsigned char *a_elems,
   1897 		const unsigned char *b_elems,
   1898 		unsigned char **maskptr)
   1899 {
   1900 	const STRUCT_ENTRY_MATCH *b;
   1901 	unsigned int i;
   1902 
   1903 	/* Offset of b is the same as a. */
   1904 	b = (void *)b_elems + ((unsigned char *)a - a_elems);
   1905 
   1906 	if (a->u.match_size != b->u.match_size)
   1907 		return 1;
   1908 
   1909 	if (strcmp(a->u.user.name, b->u.user.name) != 0)
   1910 		return 1;
   1911 
   1912 	*maskptr += ALIGN(sizeof(*a));
   1913 
   1914 	for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++)
   1915 		if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0)
   1916 			return 1;
   1917 	*maskptr += i;
   1918 	return 0;
   1919 }
   1920 
   1921 static inline int
   1922 target_same(struct rule_head *a, struct rule_head *b,const unsigned char *mask)
   1923 {
   1924 	unsigned int i;
   1925 	STRUCT_ENTRY_TARGET *ta, *tb;
   1926 
   1927 	if (a->type != b->type)
   1928 		return 0;
   1929 
   1930 	ta = GET_TARGET(a->entry);
   1931 	tb = GET_TARGET(b->entry);
   1932 
   1933 	switch (a->type) {
   1934 	case IPTCC_R_FALLTHROUGH:
   1935 		return 1;
   1936 	case IPTCC_R_JUMP:
   1937 		return a->jump == b->jump;
   1938 	case IPTCC_R_STANDARD:
   1939 		return ((STRUCT_STANDARD_TARGET *)ta)->verdict
   1940 			== ((STRUCT_STANDARD_TARGET *)tb)->verdict;
   1941 	case IPTCC_R_MODULE:
   1942 		if (ta->u.target_size != tb->u.target_size)
   1943 			return 0;
   1944 		if (strcmp(ta->u.user.name, tb->u.user.name) != 0)
   1945 			return 0;
   1946 
   1947 		for (i = 0; i < ta->u.target_size - sizeof(*ta); i++)
   1948 			if (((ta->data[i] ^ tb->data[i]) & mask[i]) != 0)
   1949 				return 0;
   1950 		return 1;
   1951 	default:
   1952 		fprintf(stderr, "ERROR: bad type %i\n", a->type);
   1953 		abort();
   1954 	}
   1955 }
   1956 
   1957 static unsigned char *
   1958 is_same(const STRUCT_ENTRY *a,
   1959 	const STRUCT_ENTRY *b,
   1960 	unsigned char *matchmask);
   1961 
   1962 
   1963 /* find the first rule in `chain' which matches `fw' and remove it unless dry_run is set */
   1964 static int delete_entry(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw,
   1965 			unsigned char *matchmask, struct xtc_handle *handle,
   1966 			bool dry_run)
   1967 {
   1968 	struct chain_head *c;
   1969 	struct rule_head *r, *i;
   1970 
   1971 	iptc_fn = TC_DELETE_ENTRY;
   1972 	if (!(c = iptcc_find_label(chain, handle))) {
   1973 		errno = ENOENT;
   1974 		return 0;
   1975 	}
   1976 
   1977 	/* Create a rule_head from origfw. */
   1978 	r = iptcc_alloc_rule(c, origfw->next_offset);
   1979 	if (!r) {
   1980 		errno = ENOMEM;
   1981 		return 0;
   1982 	}
   1983 
   1984 	memcpy(r->entry, origfw, origfw->next_offset);
   1985 	r->counter_map.maptype = COUNTER_MAP_NOMAP;
   1986 	if (!iptcc_map_target(handle, r)) {
   1987 		DEBUGP("unable to map target of rule for chain `%s'\n", chain);
   1988 		free(r);
   1989 		return 0;
   1990 	} else {
   1991 		/* iptcc_map_target increment target chain references
   1992 		 * since this is a fake rule only used for matching
   1993 		 * the chain references count is decremented again.
   1994 		 */
   1995 		if (r->type == IPTCC_R_JUMP
   1996 		    && r->jump)
   1997 			r->jump->references--;
   1998 	}
   1999 
   2000 	list_for_each_entry(i, &c->rules, list) {
   2001 		unsigned char *mask;
   2002 
   2003 		mask = is_same(r->entry, i->entry, matchmask);
   2004 		if (!mask)
   2005 			continue;
   2006 
   2007 		if (!target_same(r, i, mask))
   2008 			continue;
   2009 
   2010 		/* if we are just doing a dry run, we simply skip the rest */
   2011 		if (dry_run){
   2012 			free(r);
   2013 			return 1;
   2014 		}
   2015 
   2016 		/* If we are about to delete the rule that is the
   2017 		 * current iterator, move rule iterator back.  next
   2018 		 * pointer will then point to real next node */
   2019 		if (i == handle->rule_iterator_cur) {
   2020 			handle->rule_iterator_cur =
   2021 				list_entry(handle->rule_iterator_cur->list.prev,
   2022 					   struct rule_head, list);
   2023 		}
   2024 
   2025 		c->num_rules--;
   2026 		iptcc_delete_rule(i);
   2027 
   2028 		set_changed(handle);
   2029 		free(r);
   2030 		return 1;
   2031 	}
   2032 
   2033 	free(r);
   2034 	errno = ENOENT;
   2035 	return 0;
   2036 }
   2037 
   2038 /* check whether a specified rule is present */
   2039 int TC_CHECK_ENTRY(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw,
   2040 		   unsigned char *matchmask, struct xtc_handle *handle)
   2041 {
   2042 	/* do a dry-run delete to find out whether a matching rule exists */
   2043 	return delete_entry(chain, origfw, matchmask, handle, true);
   2044 }
   2045 
   2046 /* Delete the first rule in `chain' which matches `fw'. */
   2047 int TC_DELETE_ENTRY(const IPT_CHAINLABEL chain,	const STRUCT_ENTRY *origfw,
   2048 		    unsigned char *matchmask, struct xtc_handle *handle)
   2049 {
   2050 	return delete_entry(chain, origfw, matchmask, handle, false);
   2051 }
   2052 
   2053 /* Delete the rule in position `rulenum' in `chain'. */
   2054 int
   2055 TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain,
   2056 		    unsigned int rulenum,
   2057 		    struct xtc_handle *handle)
   2058 {
   2059 	struct chain_head *c;
   2060 	struct rule_head *r;
   2061 
   2062 	iptc_fn = TC_DELETE_NUM_ENTRY;
   2063 
   2064 	if (!(c = iptcc_find_label(chain, handle))) {
   2065 		errno = ENOENT;
   2066 		return 0;
   2067 	}
   2068 
   2069 	if (rulenum >= c->num_rules) {
   2070 		errno = E2BIG;
   2071 		return 0;
   2072 	}
   2073 
   2074 	/* Take advantage of the double linked list if possible. */
   2075 	if (rulenum + 1 <= c->num_rules/2) {
   2076 		r = iptcc_get_rule_num(c, rulenum + 1);
   2077 	} else {
   2078 		r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum);
   2079 	}
   2080 
   2081 	/* If we are about to delete the rule that is the current
   2082 	 * iterator, move rule iterator back.  next pointer will then
   2083 	 * point to real next node */
   2084 	if (r == handle->rule_iterator_cur) {
   2085 		handle->rule_iterator_cur =
   2086 			list_entry(handle->rule_iterator_cur->list.prev,
   2087 				   struct rule_head, list);
   2088 	}
   2089 
   2090 	c->num_rules--;
   2091 	iptcc_delete_rule(r);
   2092 
   2093 	set_changed(handle);
   2094 
   2095 	return 1;
   2096 }
   2097 
   2098 /* Flushes the entries in the given chain (ie. empties chain). */
   2099 int
   2100 TC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle)
   2101 {
   2102 	struct chain_head *c;
   2103 	struct rule_head *r, *tmp;
   2104 
   2105 	iptc_fn = TC_FLUSH_ENTRIES;
   2106 	if (!(c = iptcc_find_label(chain, handle))) {
   2107 		errno = ENOENT;
   2108 		return 0;
   2109 	}
   2110 
   2111 	list_for_each_entry_safe(r, tmp, &c->rules, list) {
   2112 		iptcc_delete_rule(r);
   2113 	}
   2114 
   2115 	c->num_rules = 0;
   2116 
   2117 	set_changed(handle);
   2118 
   2119 	return 1;
   2120 }
   2121 
   2122 /* Zeroes the counters in a chain. */
   2123 int
   2124 TC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle)
   2125 {
   2126 	struct chain_head *c;
   2127 	struct rule_head *r;
   2128 
   2129 	iptc_fn = TC_ZERO_ENTRIES;
   2130 	if (!(c = iptcc_find_label(chain, handle))) {
   2131 		errno = ENOENT;
   2132 		return 0;
   2133 	}
   2134 
   2135 	if (c->counter_map.maptype == COUNTER_MAP_NORMAL_MAP)
   2136 		c->counter_map.maptype = COUNTER_MAP_ZEROED;
   2137 
   2138 	list_for_each_entry(r, &c->rules, list) {
   2139 		if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP)
   2140 			r->counter_map.maptype = COUNTER_MAP_ZEROED;
   2141 	}
   2142 
   2143 	set_changed(handle);
   2144 
   2145 	return 1;
   2146 }
   2147 
   2148 STRUCT_COUNTERS *
   2149 TC_READ_COUNTER(const IPT_CHAINLABEL chain,
   2150 		unsigned int rulenum,
   2151 		struct xtc_handle *handle)
   2152 {
   2153 	struct chain_head *c;
   2154 	struct rule_head *r;
   2155 
   2156 	iptc_fn = TC_READ_COUNTER;
   2157 	CHECK(*handle);
   2158 
   2159 	if (!(c = iptcc_find_label(chain, handle))) {
   2160 		errno = ENOENT;
   2161 		return NULL;
   2162 	}
   2163 
   2164 	if (!(r = iptcc_get_rule_num(c, rulenum))) {
   2165 		errno = E2BIG;
   2166 		return NULL;
   2167 	}
   2168 
   2169 	return &r->entry[0].counters;
   2170 }
   2171 
   2172 int
   2173 TC_ZERO_COUNTER(const IPT_CHAINLABEL chain,
   2174 		unsigned int rulenum,
   2175 		struct xtc_handle *handle)
   2176 {
   2177 	struct chain_head *c;
   2178 	struct rule_head *r;
   2179 
   2180 	iptc_fn = TC_ZERO_COUNTER;
   2181 	CHECK(handle);
   2182 
   2183 	if (!(c = iptcc_find_label(chain, handle))) {
   2184 		errno = ENOENT;
   2185 		return 0;
   2186 	}
   2187 
   2188 	if (!(r = iptcc_get_rule_num(c, rulenum))) {
   2189 		errno = E2BIG;
   2190 		return 0;
   2191 	}
   2192 
   2193 	if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP)
   2194 		r->counter_map.maptype = COUNTER_MAP_ZEROED;
   2195 
   2196 	set_changed(handle);
   2197 
   2198 	return 1;
   2199 }
   2200 
   2201 int
   2202 TC_SET_COUNTER(const IPT_CHAINLABEL chain,
   2203 	       unsigned int rulenum,
   2204 	       STRUCT_COUNTERS *counters,
   2205 	       struct xtc_handle *handle)
   2206 {
   2207 	struct chain_head *c;
   2208 	struct rule_head *r;
   2209 	STRUCT_ENTRY *e;
   2210 
   2211 	iptc_fn = TC_SET_COUNTER;
   2212 	CHECK(handle);
   2213 
   2214 	if (!(c = iptcc_find_label(chain, handle))) {
   2215 		errno = ENOENT;
   2216 		return 0;
   2217 	}
   2218 
   2219 	if (!(r = iptcc_get_rule_num(c, rulenum))) {
   2220 		errno = E2BIG;
   2221 		return 0;
   2222 	}
   2223 
   2224 	e = r->entry;
   2225 	r->counter_map.maptype = COUNTER_MAP_SET;
   2226 
   2227 	memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS));
   2228 
   2229 	set_changed(handle);
   2230 
   2231 	return 1;
   2232 }
   2233 
   2234 /* Creates a new chain. */
   2235 /* To create a chain, create two rules: error node and unconditional
   2236  * return. */
   2237 int
   2238 TC_CREATE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle)
   2239 {
   2240 	static struct chain_head *c;
   2241 	int capacity;
   2242 	int exceeded;
   2243 
   2244 	iptc_fn = TC_CREATE_CHAIN;
   2245 
   2246 	/* find_label doesn't cover built-in targets: DROP, ACCEPT,
   2247            QUEUE, RETURN. */
   2248 	if (iptcc_find_label(chain, handle)
   2249 	    || strcmp(chain, LABEL_DROP) == 0
   2250 	    || strcmp(chain, LABEL_ACCEPT) == 0
   2251 	    || strcmp(chain, LABEL_QUEUE) == 0
   2252 	    || strcmp(chain, LABEL_RETURN) == 0) {
   2253 		DEBUGP("Chain `%s' already exists\n", chain);
   2254 		errno = EEXIST;
   2255 		return 0;
   2256 	}
   2257 
   2258 	if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) {
   2259 		DEBUGP("Chain name `%s' too long\n", chain);
   2260 		errno = EINVAL;
   2261 		return 0;
   2262 	}
   2263 
   2264 	c = iptcc_alloc_chain_head(chain, 0);
   2265 	if (!c) {
   2266 		DEBUGP("Cannot allocate memory for chain `%s'\n", chain);
   2267 		errno = ENOMEM;
   2268 		return 0;
   2269 
   2270 	}
   2271 	handle->num_chains++; /* New user defined chain */
   2272 
   2273 	DEBUGP("Creating chain `%s'\n", chain);
   2274 	iptc_insert_chain(handle, c); /* Insert sorted */
   2275 
   2276 	/* Inserting chains don't change the correctness of the chain
   2277 	 * index (except if its smaller than index[0], but that
   2278 	 * handled by iptc_insert_chain).  It only causes longer lists
   2279 	 * in the buckets. Thus, only rebuild chain index when the
   2280 	 * capacity is exceed with CHAIN_INDEX_INSERT_MAX chains.
   2281 	 */
   2282 	capacity = handle->chain_index_sz * CHAIN_INDEX_BUCKET_LEN;
   2283 	exceeded = handle->num_chains - capacity;
   2284 	if (exceeded > CHAIN_INDEX_INSERT_MAX) {
   2285 		debug("Capacity(%d) exceeded(%d) rebuild (chains:%d)\n",
   2286 		      capacity, exceeded, handle->num_chains);
   2287 		iptcc_chain_index_rebuild(handle);
   2288 	}
   2289 
   2290 	set_changed(handle);
   2291 
   2292 	return 1;
   2293 }
   2294 
   2295 /* Get the number of references to this chain. */
   2296 int
   2297 TC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain,
   2298 		  struct xtc_handle *handle)
   2299 {
   2300 	struct chain_head *c;
   2301 
   2302 	iptc_fn = TC_GET_REFERENCES;
   2303 	if (!(c = iptcc_find_label(chain, handle))) {
   2304 		errno = ENOENT;
   2305 		return 0;
   2306 	}
   2307 
   2308 	*ref = c->references;
   2309 
   2310 	return 1;
   2311 }
   2312 
   2313 /* Deletes a chain. */
   2314 int
   2315 TC_DELETE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle)
   2316 {
   2317 	unsigned int references;
   2318 	struct chain_head *c;
   2319 
   2320 	iptc_fn = TC_DELETE_CHAIN;
   2321 
   2322 	if (!(c = iptcc_find_label(chain, handle))) {
   2323 		DEBUGP("cannot find chain `%s'\n", chain);
   2324 		errno = ENOENT;
   2325 		return 0;
   2326 	}
   2327 
   2328 	if (TC_BUILTIN(chain, handle)) {
   2329 		DEBUGP("cannot remove builtin chain `%s'\n", chain);
   2330 		errno = EINVAL;
   2331 		return 0;
   2332 	}
   2333 
   2334 	if (!TC_GET_REFERENCES(&references, chain, handle)) {
   2335 		DEBUGP("cannot get references on chain `%s'\n", chain);
   2336 		return 0;
   2337 	}
   2338 
   2339 	if (references > 0) {
   2340 		DEBUGP("chain `%s' still has references\n", chain);
   2341 		errno = EMLINK;
   2342 		return 0;
   2343 	}
   2344 
   2345 	if (c->num_rules) {
   2346 		DEBUGP("chain `%s' is not empty\n", chain);
   2347 		errno = ENOTEMPTY;
   2348 		return 0;
   2349 	}
   2350 
   2351 	/* If we are about to delete the chain that is the current
   2352 	 * iterator, move chain iterator forward. */
   2353 	if (c == handle->chain_iterator_cur)
   2354 		iptcc_chain_iterator_advance(handle);
   2355 
   2356 	handle->num_chains--; /* One user defined chain deleted */
   2357 
   2358 	//list_del(&c->list); /* Done in iptcc_chain_index_delete_chain() */
   2359 	iptcc_chain_index_delete_chain(c, handle);
   2360 	free(c);
   2361 
   2362 	DEBUGP("chain `%s' deleted\n", chain);
   2363 
   2364 	set_changed(handle);
   2365 
   2366 	return 1;
   2367 }
   2368 
   2369 /* Renames a chain. */
   2370 int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname,
   2371 		    const IPT_CHAINLABEL newname,
   2372 		    struct xtc_handle *handle)
   2373 {
   2374 	struct chain_head *c;
   2375 	iptc_fn = TC_RENAME_CHAIN;
   2376 
   2377 	/* find_label doesn't cover built-in targets: DROP, ACCEPT,
   2378            QUEUE, RETURN. */
   2379 	if (iptcc_find_label(newname, handle)
   2380 	    || strcmp(newname, LABEL_DROP) == 0
   2381 	    || strcmp(newname, LABEL_ACCEPT) == 0
   2382 	    || strcmp(newname, LABEL_QUEUE) == 0
   2383 	    || strcmp(newname, LABEL_RETURN) == 0) {
   2384 		errno = EEXIST;
   2385 		return 0;
   2386 	}
   2387 
   2388 	if (!(c = iptcc_find_label(oldname, handle))
   2389 	    || TC_BUILTIN(oldname, handle)) {
   2390 		errno = ENOENT;
   2391 		return 0;
   2392 	}
   2393 
   2394 	if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) {
   2395 		errno = EINVAL;
   2396 		return 0;
   2397 	}
   2398 
   2399 	/* This only unlinks "c" from the list, thus no free(c) */
   2400 	iptcc_chain_index_delete_chain(c, handle);
   2401 
   2402 	/* Change the name of the chain */
   2403 	strncpy(c->name, newname, sizeof(IPT_CHAINLABEL));
   2404 
   2405 	/* Insert sorted into to list again */
   2406 	iptc_insert_chain(handle, c);
   2407 
   2408 	set_changed(handle);
   2409 
   2410 	return 1;
   2411 }
   2412 
   2413 /* Sets the policy on a built-in chain. */
   2414 int
   2415 TC_SET_POLICY(const IPT_CHAINLABEL chain,
   2416 	      const IPT_CHAINLABEL policy,
   2417 	      STRUCT_COUNTERS *counters,
   2418 	      struct xtc_handle *handle)
   2419 {
   2420 	struct chain_head *c;
   2421 
   2422 	iptc_fn = TC_SET_POLICY;
   2423 
   2424 	if (!(c = iptcc_find_label(chain, handle))) {
   2425 		DEBUGP("cannot find chain `%s'\n", chain);
   2426 		errno = ENOENT;
   2427 		return 0;
   2428 	}
   2429 
   2430 	if (!iptcc_is_builtin(c)) {
   2431 		DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain);
   2432 		errno = ENOENT;
   2433 		return 0;
   2434 	}
   2435 
   2436 	if (strcmp(policy, LABEL_ACCEPT) == 0)
   2437 		c->verdict = -NF_ACCEPT - 1;
   2438 	else if (strcmp(policy, LABEL_DROP) == 0)
   2439 		c->verdict = -NF_DROP - 1;
   2440 	else {
   2441 		errno = EINVAL;
   2442 		return 0;
   2443 	}
   2444 
   2445 	if (counters) {
   2446 		/* set byte and packet counters */
   2447 		memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS));
   2448 		c->counter_map.maptype = COUNTER_MAP_SET;
   2449 	} else {
   2450 		c->counter_map.maptype = COUNTER_MAP_NOMAP;
   2451 	}
   2452 
   2453 	set_changed(handle);
   2454 
   2455 	return 1;
   2456 }
   2457 
   2458 /* Without this, on gcc 2.7.2.3, we get:
   2459    libiptc.c: In function `TC_COMMIT':
   2460    libiptc.c:833: fixed or forbidden register was spilled.
   2461    This may be due to a compiler bug or to impossible asm
   2462    statements or clauses.
   2463 */
   2464 static void
   2465 subtract_counters(STRUCT_COUNTERS *answer,
   2466 		  const STRUCT_COUNTERS *a,
   2467 		  const STRUCT_COUNTERS *b)
   2468 {
   2469 	answer->pcnt = a->pcnt - b->pcnt;
   2470 	answer->bcnt = a->bcnt - b->bcnt;
   2471 }
   2472 
   2473 
   2474 static void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, unsigned int idx)
   2475 {
   2476 	newcounters->counters[idx] = ((STRUCT_COUNTERS) { 0, 0});
   2477 	DEBUGP_C("NOMAP => zero\n");
   2478 }
   2479 
   2480 static void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters,
   2481 				STRUCT_REPLACE *repl, unsigned int idx,
   2482 				unsigned int mappos)
   2483 {
   2484 	/* Original read: X.
   2485 	 * Atomic read on replacement: X + Y.
   2486 	 * Currently in kernel: Z.
   2487 	 * Want in kernel: X + Y + Z.
   2488 	 * => Add in X + Y
   2489 	 * => Add in replacement read.
   2490 	 */
   2491 	newcounters->counters[idx] = repl->counters[mappos];
   2492 	DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos);
   2493 }
   2494 
   2495 static void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters,
   2496 				STRUCT_REPLACE *repl, unsigned int idx,
   2497 				unsigned int mappos, STRUCT_COUNTERS *counters)
   2498 {
   2499 	/* Original read: X.
   2500 	 * Atomic read on replacement: X + Y.
   2501 	 * Currently in kernel: Z.
   2502 	 * Want in kernel: Y + Z.
   2503 	 * => Add in Y.
   2504 	 * => Add in (replacement read - original read).
   2505 	 */
   2506 	subtract_counters(&newcounters->counters[idx],
   2507 			  &repl->counters[mappos],
   2508 			  counters);
   2509 	DEBUGP_C("ZEROED => mappos %u\n", mappos);
   2510 }
   2511 
   2512 static void counters_map_set(STRUCT_COUNTERS_INFO *newcounters,
   2513                              unsigned int idx, STRUCT_COUNTERS *counters)
   2514 {
   2515 	/* Want to set counter (iptables-restore) */
   2516 
   2517 	memcpy(&newcounters->counters[idx], counters,
   2518 		sizeof(STRUCT_COUNTERS));
   2519 
   2520 	DEBUGP_C("SET\n");
   2521 }
   2522 
   2523 
   2524 int
   2525 TC_COMMIT(struct xtc_handle *handle)
   2526 {
   2527 	/* Replace, then map back the counters. */
   2528 	STRUCT_REPLACE *repl;
   2529 	STRUCT_COUNTERS_INFO *newcounters;
   2530 	struct chain_head *c;
   2531 	int ret;
   2532 	size_t counterlen;
   2533 	int new_number;
   2534 	unsigned int new_size;
   2535 
   2536 	iptc_fn = TC_COMMIT;
   2537 	CHECK(*handle);
   2538 
   2539 	/* Don't commit if nothing changed. */
   2540 	if (!handle->changed)
   2541 		goto finished;
   2542 
   2543 	new_number = iptcc_compile_table_prep(handle, &new_size);
   2544 	if (new_number < 0) {
   2545 		errno = ENOMEM;
   2546 		goto out_zero;
   2547 	}
   2548 
   2549 	repl = malloc(sizeof(*repl) + new_size);
   2550 	if (!repl) {
   2551 		errno = ENOMEM;
   2552 		goto out_zero;
   2553 	}
   2554 	memset(repl, 0, sizeof(*repl) + new_size);
   2555 
   2556 #if 0
   2557 	TC_DUMP_ENTRIES(*handle);
   2558 #endif
   2559 
   2560 	counterlen = sizeof(STRUCT_COUNTERS_INFO)
   2561 			+ sizeof(STRUCT_COUNTERS) * new_number;
   2562 
   2563 	/* These are the old counters we will get from kernel */
   2564 	repl->counters = malloc(sizeof(STRUCT_COUNTERS)
   2565 				* handle->info.num_entries);
   2566 	if (!repl->counters) {
   2567 		errno = ENOMEM;
   2568 		goto out_free_repl;
   2569 	}
   2570 	/* These are the counters we're going to put back, later. */
   2571 	newcounters = malloc(counterlen);
   2572 	if (!newcounters) {
   2573 		errno = ENOMEM;
   2574 		goto out_free_repl_counters;
   2575 	}
   2576 	memset(newcounters, 0, counterlen);
   2577 
   2578 	strcpy(repl->name, handle->info.name);
   2579 	repl->num_entries = new_number;
   2580 	repl->size = new_size;
   2581 
   2582 	repl->num_counters = handle->info.num_entries;
   2583 	repl->valid_hooks  = handle->info.valid_hooks;
   2584 
   2585 	DEBUGP("num_entries=%u, size=%u, num_counters=%u\n",
   2586 		repl->num_entries, repl->size, repl->num_counters);
   2587 
   2588 	ret = iptcc_compile_table(handle, repl);
   2589 	if (ret < 0) {
   2590 		errno = ret;
   2591 		goto out_free_newcounters;
   2592 	}
   2593 
   2594 
   2595 #ifdef IPTC_DEBUG2
   2596 	{
   2597 		int fd = open("/tmp/libiptc-so_set_replace.blob",
   2598 				O_CREAT|O_WRONLY);
   2599 		if (fd >= 0) {
   2600 			write(fd, repl, sizeof(*repl) + repl->size);
   2601 			close(fd);
   2602 		}
   2603 	}
   2604 #endif
   2605 
   2606 	ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_REPLACE, repl,
   2607 			 sizeof(*repl) + repl->size);
   2608 	if (ret < 0)
   2609 		goto out_free_newcounters;
   2610 
   2611 	/* Put counters back. */
   2612 	strcpy(newcounters->name, handle->info.name);
   2613 	newcounters->num_counters = new_number;
   2614 
   2615 	list_for_each_entry(c, &handle->chains, list) {
   2616 		struct rule_head *r;
   2617 
   2618 		/* Builtin chains have their own counters */
   2619 		if (iptcc_is_builtin(c)) {
   2620 			DEBUGP("counter for chain-index %u: ", c->foot_index);
   2621 			switch(c->counter_map.maptype) {
   2622 			case COUNTER_MAP_NOMAP:
   2623 				counters_nomap(newcounters, c->foot_index);
   2624 				break;
   2625 			case COUNTER_MAP_NORMAL_MAP:
   2626 				counters_normal_map(newcounters, repl,
   2627 						    c->foot_index,
   2628 						    c->counter_map.mappos);
   2629 				break;
   2630 			case COUNTER_MAP_ZEROED:
   2631 				counters_map_zeroed(newcounters, repl,
   2632 						    c->foot_index,
   2633 						    c->counter_map.mappos,
   2634 						    &c->counters);
   2635 				break;
   2636 			case COUNTER_MAP_SET:
   2637 				counters_map_set(newcounters, c->foot_index,
   2638 						 &c->counters);
   2639 				break;
   2640 			}
   2641 		}
   2642 
   2643 		list_for_each_entry(r, &c->rules, list) {
   2644 			DEBUGP("counter for index %u: ", r->index);
   2645 			switch (r->counter_map.maptype) {
   2646 			case COUNTER_MAP_NOMAP:
   2647 				counters_nomap(newcounters, r->index);
   2648 				break;
   2649 
   2650 			case COUNTER_MAP_NORMAL_MAP:
   2651 				counters_normal_map(newcounters, repl,
   2652 						    r->index,
   2653 						    r->counter_map.mappos);
   2654 				break;
   2655 
   2656 			case COUNTER_MAP_ZEROED:
   2657 				counters_map_zeroed(newcounters, repl,
   2658 						    r->index,
   2659 						    r->counter_map.mappos,
   2660 						    &r->entry->counters);
   2661 				break;
   2662 
   2663 			case COUNTER_MAP_SET:
   2664 				counters_map_set(newcounters, r->index,
   2665 						 &r->entry->counters);
   2666 				break;
   2667 			}
   2668 		}
   2669 	}
   2670 
   2671 #ifdef IPTC_DEBUG2
   2672 	{
   2673 		int fd = open("/tmp/libiptc-so_set_add_counters.blob",
   2674 				O_CREAT|O_WRONLY);
   2675 		if (fd >= 0) {
   2676 			write(fd, newcounters, counterlen);
   2677 			close(fd);
   2678 		}
   2679 	}
   2680 #endif
   2681 
   2682 	ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS,
   2683 			 newcounters, counterlen);
   2684 	if (ret < 0)
   2685 		goto out_free_newcounters;
   2686 
   2687 	free(repl->counters);
   2688 	free(repl);
   2689 	free(newcounters);
   2690 
   2691 finished:
   2692 	return 1;
   2693 
   2694 out_free_newcounters:
   2695 	free(newcounters);
   2696 out_free_repl_counters:
   2697 	free(repl->counters);
   2698 out_free_repl:
   2699 	free(repl);
   2700 out_zero:
   2701 	return 0;
   2702 }
   2703 
   2704 /* Translates errno numbers into more human-readable form than strerror. */
   2705 const char *
   2706 TC_STRERROR(int err)
   2707 {
   2708 	unsigned int i;
   2709 	struct table_struct {
   2710 		void *fn;
   2711 		int err;
   2712 		const char *message;
   2713 	} table [] =
   2714 	  { { TC_INIT, EPERM, "Permission denied (you must be root)" },
   2715 	    { TC_INIT, EINVAL, "Module is wrong version" },
   2716 	    { TC_INIT, ENOENT,
   2717 		    "Table does not exist (do you need to insmod?)" },
   2718 	    { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" },
   2719 	    { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" },
   2720 	    { TC_DELETE_CHAIN, EMLINK,
   2721 	      "Can't delete chain with references left" },
   2722 	    { TC_CREATE_CHAIN, EEXIST, "Chain already exists" },
   2723 	    { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" },
   2724 	    { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" },
   2725 	    { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" },
   2726 	    { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
   2727 	    { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" },
   2728 	    { TC_INSERT_ENTRY, ELOOP, "Loop found in table" },
   2729 	    { TC_INSERT_ENTRY, EINVAL, "Target problem" },
   2730 	    /* ENOENT for DELETE probably means no matching rule */
   2731 	    { TC_DELETE_ENTRY, ENOENT,
   2732 	      "Bad rule (does a matching rule exist in that chain?)" },
   2733 	    { TC_SET_POLICY, ENOENT,
   2734 	      "Bad built-in chain name" },
   2735 	    { TC_SET_POLICY, EINVAL,
   2736 	      "Bad policy name" },
   2737 
   2738 	    { NULL, 0, "Incompatible with this kernel" },
   2739 	    { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
   2740 	    { NULL, ENOSYS, "Will be implemented real soon.  I promise ;)" },
   2741 	    { NULL, ENOMEM, "Memory allocation problem" },
   2742 	    { NULL, ENOENT, "No chain/target/match by that name" },
   2743 	  };
   2744 
   2745 	for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
   2746 		if ((!table[i].fn || table[i].fn == iptc_fn)
   2747 		    && table[i].err == err)
   2748 			return table[i].message;
   2749 	}
   2750 
   2751 	return strerror(err);
   2752 }
   2753 
   2754 const struct xtc_ops TC_OPS = {
   2755 	.commit        = TC_COMMIT,
   2756 	.free          = TC_FREE,
   2757 	.builtin       = TC_BUILTIN,
   2758 	.is_chain      = TC_IS_CHAIN,
   2759 	.flush_entries = TC_FLUSH_ENTRIES,
   2760 	.create_chain  = TC_CREATE_CHAIN,
   2761 	.set_policy    = TC_SET_POLICY,
   2762 	.strerror      = TC_STRERROR,
   2763 };
   2764