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