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