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