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