- fix building iptables plugin
[packages/collectd.git] / netfilter.patch
1 commit 99364c70a7039ed496dbe429fb86ee41e464fc76
2 Author: Florian Forster <octo@collectd.org>
3 Date:   Sun Apr 3 09:17:26 2011 -0700
4
5     iptables plugin: Remove the shipped version of libiptc.
6     
7     Since libiptc is now publicly available as a shared library, we don't really
8     have any need to ship it with collectd anymore.
9
10 diff --git a/configure.in b/configure.in
11 index 8db24ca..8043d9a 100644
12 --- a/configure.in
13 +++ b/configure.in
14 @@ -1764,21 +1764,16 @@ AM_CONDITIONAL(BUILD_WITH_LIBGCRYPT, test "x$with_libgcrypt" = "xyes")
15  # }}}
16  
17  # --with-libiptc {{{
18 -with_own_libiptc="no"
19  AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to libiptc.])],
20  [
21 -       if test "x$withval" = "xshipped"
22 -       then
23 -               with_own_libiptc="yes"
24 -               with_libiptc="yes"
25 -       else if test "x$withval" != "xno" && test "x$withval" != "xyes"
26 +       if test "x$withval" != "xno" && test "x$withval" != "xyes"
27         then
28                 LIBIPTC_CPPFLAGS="$LIBIPTC_CPPFLAGS -I$withval/include"
29                 LIBIPTC_LDFLAGS="$LIBIPTC_LDFLAGS -L$withval/lib"
30                 with_libiptc="yes"
31         else
32                 with_libiptc="$withval"
33 -       fi; fi
34 +       fi
35  ],
36  [
37         if test "x$ac_system" = "xLinux"
38 @@ -1793,32 +1788,22 @@ SAVE_LDFLAGS="$LDFLAGS"
39  CPPFLAGS="$CPPFLAGS $LIBIPTC_CPPFLAGS"
40  LDFLAGS="$LDFLAGS $LIBIPTC_LDFLAGS"
41  # check whether the header file for libiptc is available.
42 -if test "x$with_libiptc" = "xyes" && test "x$with_own_libiptc" = "xno"
43 +if test "x$with_libiptc" = "xyes"
44  then
45         AC_CHECK_HEADERS(libiptc/libiptc.h,
46 -       [
47 -               AC_DEFINE(HAVE_LIBIPTC_LIBIPTC_H, 1, [Define to 1 if you have the <libiptc/libiptc.h> header file.])
48 -       ],
49 -       [
50 -               with_libiptc="yes"
51 -               with_own_libiptc="yes"
52 -       ])
53 +                        [with_libiptc="yes"],
54 +                        [with_libiptc="no (libiptc/libiptc.h not found)"])
55  fi
56 -if test "x$with_libiptc" = "xyes" && test "x$with_own_libiptc" = "xno"
57 +if test "x$with_libiptc" = "xyes"
58  then
59         AC_CHECK_HEADERS(libiptc/libip6tc.h,
60 -       [
61 -               AC_DEFINE(HAVE_LIBIPTC_LIBIP6TC_H, 1, [Define to 1 if you have the <libiptc/libip6tc.h> header file.])
62 -       ],
63 -       [
64 -               with_libiptc="yes"
65 -               with_own_libiptc="yes"
66 -       ])
67 +                        [with_libiptc="yes"],
68 +                        [with_libiptc="no (libiptc/libip6tc.h not found)"])
69  fi
70  # If the header file is available, check for the required type declaractions.
71  # They may be missing in old versions of libiptc. In that case, they will be
72  # declared in the iptables plugin.
73 -if test "x$with_libiptc" = "xyes" && test "x$with_own_libiptc" = "xno"
74 +if test "x$with_libiptc" = "xyes"
75  then
76         AC_CHECK_TYPES([iptc_handle_t, ip6tc_handle_t], [], [],
77         [
78 @@ -1832,32 +1817,13 @@ then
79         ])
80  fi
81  # Check for the iptc_init symbol in the library.
82 -if test "x$with_libiptc" = "xyes" && test "x$with_own_libiptc" = "xno"
83 +if test "x$with_libiptc" = "xyes"
84  then
85         AC_CHECK_LIB(iptc, iptc_init,
86 -       [
87 -               AC_DEFINE(HAVE_LIBIPTC, 1, [Define to 1 if you have the iptc library (-liptc).])
88 -       ],
89 -       [
90 -               with_libiptc="yes"
91 -               with_own_libiptc="yes"
92 -       ])
93 -fi
94 -# The system wide version failed for some reason. Check if we have the required
95 -# headers to build the shipped version.
96 -if test "x$with_libiptc" = "xyes" && test "x$with_own_libiptc" = "xyes"
97 -then
98 -       AC_CHECK_HEADERS(linux/netfilter_ipv4/ip_tables.h linux/netfilter_ipv6/ip6_tables.h linux/netfilter/x_tables.h, [],
99 -       [
100 -               with_libiptc="no (Linux iptables headers not found)"
101 -               with_own_libiptc="no"
102 -       ],
103 -       [
104 -#include "$srcdir/src/owniptc/ipt_kernel_headers.h"
105 -       ])
106 +                    [with_libiptc="yes"],
107 +                    [with_libiptc="no (symbol 'iptc_init' not found)"])
108  fi
109  AM_CONDITIONAL(BUILD_WITH_LIBIPTC, test "x$with_libiptc" = "xyes")
110 -AM_CONDITIONAL(BUILD_WITH_OWN_LIBIPTC, test "x$with_own_libiptc" = "xyes")
111  if test "x$with_libiptc" = "xyes"
112  then
113         BUILD_WITH_LIBIPTC_CPPFLAGS="$LIBIPTC_CPPFLAGS"
114 @@ -1865,10 +1831,6 @@ then
115         AC_SUBST(BUILD_WITH_LIBIPTC_CPPFLAGS)
116         AC_SUBST(BUILD_WITH_LIBIPTC_LDFLAGS)
117  fi
118 -if test "x$with_own_libiptc" = "xyes"
119 -then
120 -       AC_DEFINE(OWN_LIBIPTC, 1, [Define to 1 if we use the shipped iptc library.])
121 -fi
122  CPPFLAGS="$SAVE_CPPFLAGS"
123  LDFLAGS="$SAVE_LDFLAGS"
124  # }}}
125 @@ -4859,11 +4821,6 @@ then
126         with_librrd="yes (warning: librrd is not thread-safe)"
127  fi
128  
129 -if test "x$with_libiptc" = "xyes" && test "x$with_own_libiptc" = "xyes"
130 -then
131 -       with_libiptc="yes (shipped version)"
132 -fi
133 -
134  if test "x$with_libperl" = "xyes"
135  then
136         with_libperl="yes (version `$perl_interpreter -MConfig -e 'print $Config{version};'`)"
137 diff --git a/src/Makefile.am b/src/Makefile.am
138 index 5728144..795de57 100644
139 --- a/src/Makefile.am
140 +++ b/src/Makefile.am
141 @@ -1,7 +1,4 @@
142  SUBDIRS = libcollectdclient
143 -if BUILD_WITH_OWN_LIBIPTC
144 -SUBDIRS += owniptc
145 -endif
146  if BUILD_WITH_OWN_LIBOCONFIG
147  SUBDIRS += liboconfig
148  endif
149 @@ -440,12 +437,7 @@ pkglib_LTLIBRARIES += iptables.la
150  iptables_la_SOURCES = iptables.c
151  iptables_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBIPTC_CPPFLAGS)
152  iptables_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBIPTC_LDFLAGS)
153 -if BUILD_WITH_OWN_LIBIPTC
154 -iptables_la_LIBADD  = owniptc/libiptc.la
155 -iptables_la_DEPENDENCIES = owniptc/libiptc.la
156 -else
157  iptables_la_LIBADD = -liptc
158 -endif
159  collectd_LDADD += "-dlopen" iptables.la
160  collectd_DEPENDENCIES += iptables.la
161  endif
162 diff --git a/src/iptables.c b/src/iptables.c
163 index c39aff8..49454f0 100644
164 --- a/src/iptables.c
165 +++ b/src/iptables.c
166 @@ -31,16 +31,8 @@
167  
168  #include <sys/socket.h>
169  
170 -#if OWN_LIBIPTC
171 -# include "owniptc/libiptc.h"
172 -# include "owniptc/libip6tc.h"
173 -
174 -# define HAVE_IPTC_HANDLE_T 1
175 -# define HAVE_IP6TC_HANDLE_T 1
176 -
177 -#else /* if !OWN_LIBIPTC */
178 -# include <libiptc/libiptc.h>
179 -# include <libiptc/libip6tc.h>
180 +#include <libiptc/libiptc.h>
181 +#include <libiptc/libip6tc.h>
182  
183  /*
184   * iptc_handle_t was available before libiptc was officially available as a
185 @@ -54,13 +46,12 @@
186   * this is somewhat hacky, I didn't find better way to solve that :-/
187   * -tokkee
188   */
189 -# ifndef HAVE_IPTC_HANDLE_T
190 +#ifndef HAVE_IPTC_HANDLE_T
191  typedef struct iptc_handle iptc_handle_t;
192 -# endif
193 -# ifndef HAVE_IP6TC_HANDLE_T
194 +#endif
195 +#ifndef HAVE_IP6TC_HANDLE_T
196  typedef struct ip6tc_handle ip6tc_handle_t;
197 -# endif
198 -#endif /* !OWN_LIBIPTC */
199 +#endif
200  
201  /*
202   * (Module-)Global variables
203 diff --git a/src/owniptc/Makefile.am b/src/owniptc/Makefile.am
204 deleted file mode 100644
205 index d51e993..0000000
206 --- a/src/owniptc/Makefile.am
207 +++ /dev/null
208 @@ -1,14 +0,0 @@
209 -AUTOMAKE_OPTIONS = foreign no-dependencies
210 -
211 -EXTRA_DIST = libiptc.c README.collectd
212 -
213 -if COMPILER_IS_GCC
214 -AM_CFLAGS = -Wall -Werror
215 -endif
216 -
217 -noinst_LTLIBRARIES = libiptc.la
218 -
219 -libiptc_la_SOURCES = libip4tc.c libip6tc.c \
220 -               ipt_kernel_headers.h libip6tc.h libiptc.h linux_list.h \
221 -               xtables.h libxtc.h
222 -
223 diff --git a/src/owniptc/README.collectd b/src/owniptc/README.collectd
224 deleted file mode 100644
225 index adb53b0..0000000
226 --- a/src/owniptc/README.collectd
227 +++ /dev/null
228 @@ -1,25 +0,0 @@
229 - libiptc (IPTables Chains) in collectd
230 -=======================================
231 -http://netfilter.org/
232 -http://collectd.org/
233 -
234 -About
235 ------
236 -
237 -  This is libiptc taken from the iptables source distribution. As it is not
238 -  meant to be a public interface by upstream it is not shipped in some binary
239 -  distributions. Thus, collectd ships its own copy as a fall-back.
240 -
241 -  The presently available version was imported from iptables 1.4.1.1.
242 -
243 -Changes to the iptables upstream sources:
244 ------------------------------------------
245 -
246 -  * Added copyright headers mentioning the "Netfilter Core Team" as copyright
247 -    holder.
248 -
249 -  * Changed "libiptc/*" includes to "*".
250 -
251 -  * Use the shipped copy of "xtables.h" instead of the one possibly available
252 -    on the system.
253 -
254 diff --git a/src/owniptc/ipt_kernel_headers.h b/src/owniptc/ipt_kernel_headers.h
255 deleted file mode 100644
256 index bf81f6e..0000000
257 --- a/src/owniptc/ipt_kernel_headers.h
258 +++ /dev/null
259 @@ -1,45 +0,0 @@
260 -/**
261 - * This file was imported from the iptables sources.
262 - * Copyright (C) 1999-2008 Netfilter Core Team
263 - *
264 - * This program is free software; you can redistribute it and/or modify it
265 - * under the terms of the GNU General Public License as published by the
266 - * Free Software Foundation; only version 2 of the License is applicable.
267 - *
268 - * This program is distributed in the hope that it will be useful, but
269 - * WITHOUT ANY WARRANTY; without even the implied warranty of
270 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
271 - * General Public License for more details.
272 - *
273 - * You should have received a copy of the GNU General Public License along
274 - * with this program; if not, write to the Free Software Foundation, Inc.,
275 - * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
276 - */
277 -
278 -/* This is the userspace/kernel interface for Generic IP Chains,
279 -   required for libc6. */
280 -#ifndef _FWCHAINS_KERNEL_HEADERS_H
281 -#define _FWCHAINS_KERNEL_HEADERS_H
282 -
283 -#include <limits.h>
284 -
285 -#if defined(__GLIBC__) && __GLIBC__ == 2
286 -#include <netinet/ip.h>
287 -#include <netinet/in.h>
288 -#include <netinet/ip_icmp.h>
289 -#include <netinet/tcp.h>
290 -#include <netinet/udp.h>
291 -#include <net/if.h>
292 -#include <sys/types.h>
293 -#else /* libc5 */
294 -#include <sys/socket.h>
295 -#include <linux/ip.h>
296 -#include <linux/in.h>
297 -#include <linux/if.h>
298 -#include <linux/icmp.h>
299 -#include <linux/tcp.h>
300 -#include <linux/udp.h>
301 -#include <linux/types.h>
302 -#include <linux/in6.h>
303 -#endif
304 -#endif
305 diff --git a/src/owniptc/libip4tc.c b/src/owniptc/libip4tc.c
306 deleted file mode 100644
307 index bf7327c..0000000
308 --- a/src/owniptc/libip4tc.c
309 +++ /dev/null
310 @@ -1,517 +0,0 @@
311 -/**
312 - * This file was imported from the iptables sources.
313 - * Copyright (C) 1999-2008 Netfilter Core Team
314 - *
315 - * This program is free software; you can redistribute it and/or modify it
316 - * under the terms of the GNU General Public License as published by the
317 - * Free Software Foundation; only version 2 of the License is applicable.
318 - *
319 - * This program is distributed in the hope that it will be useful, but
320 - * WITHOUT ANY WARRANTY; without even the implied warranty of
321 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
322 - * General Public License for more details.
323 - *
324 - * You should have received a copy of the GNU General Public License along
325 - * with this program; if not, write to the Free Software Foundation, Inc.,
326 - * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
327 - */
328 -
329 -/* Library which manipulates firewall rules.  Version 0.1. */
330 -
331 -/* Architecture of firewall rules is as follows:
332 - *
333 - * Chains go INPUT, FORWARD, OUTPUT then user chains.
334 - * Each user chain starts with an ERROR node.
335 - * Every chain ends with an unconditional jump: a RETURN for user chains,
336 - * and a POLICY for built-ins.
337 - */
338 -
339 -/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
340 -   COPYING for details). */
341 -
342 -#include <assert.h>
343 -#include <string.h>
344 -#include <errno.h>
345 -#include <stdlib.h>
346 -#include <stdio.h>
347 -#include <unistd.h>
348 -
349 -#ifdef DEBUG_CONNTRACK
350 -#define inline
351 -#endif
352 -
353 -#if !defined(__GLIBC__) || (__GLIBC__ < 2)
354 -typedef unsigned int socklen_t;
355 -#endif
356 -
357 -#include "libiptc.h"
358 -
359 -#define IP_VERSION     4
360 -#define IP_OFFSET      0x1FFF
361 -
362 -#define HOOK_PRE_ROUTING       NF_IP_PRE_ROUTING
363 -#define HOOK_LOCAL_IN          NF_IP_LOCAL_IN
364 -#define HOOK_FORWARD           NF_IP_FORWARD
365 -#define HOOK_LOCAL_OUT         NF_IP_LOCAL_OUT
366 -#define HOOK_POST_ROUTING      NF_IP_POST_ROUTING
367 -#ifdef NF_IP_DROPPING
368 -#define HOOK_DROPPING          NF_IP_DROPPING
369 -#endif
370 -
371 -#define STRUCT_ENTRY_TARGET    struct ipt_entry_target
372 -#define STRUCT_ENTRY           struct ipt_entry
373 -#define STRUCT_ENTRY_MATCH     struct ipt_entry_match
374 -#define STRUCT_GETINFO         struct ipt_getinfo
375 -#define STRUCT_GET_ENTRIES     struct ipt_get_entries
376 -#define STRUCT_COUNTERS                struct ipt_counters
377 -#define STRUCT_COUNTERS_INFO   struct ipt_counters_info
378 -#define STRUCT_STANDARD_TARGET struct ipt_standard_target
379 -#define STRUCT_REPLACE         struct ipt_replace
380 -
381 -#define STRUCT_TC_HANDLE       struct iptc_handle
382 -#define TC_HANDLE_T            iptc_handle_t
383 -
384 -#define ENTRY_ITERATE          IPT_ENTRY_ITERATE
385 -#define TABLE_MAXNAMELEN       IPT_TABLE_MAXNAMELEN
386 -#define FUNCTION_MAXNAMELEN    IPT_FUNCTION_MAXNAMELEN
387 -
388 -#define GET_TARGET             ipt_get_target
389 -
390 -#define ERROR_TARGET           IPT_ERROR_TARGET
391 -#define NUMHOOKS               NF_IP_NUMHOOKS
392 -
393 -#define IPT_CHAINLABEL         ipt_chainlabel
394 -
395 -#define TC_DUMP_ENTRIES                dump_entries
396 -#define TC_IS_CHAIN            iptc_is_chain
397 -#define TC_FIRST_CHAIN         iptc_first_chain
398 -#define TC_NEXT_CHAIN          iptc_next_chain
399 -#define TC_FIRST_RULE          iptc_first_rule
400 -#define TC_NEXT_RULE           iptc_next_rule
401 -#define TC_GET_TARGET          iptc_get_target
402 -#define TC_BUILTIN             iptc_builtin
403 -#define TC_GET_POLICY          iptc_get_policy
404 -#define TC_INSERT_ENTRY                iptc_insert_entry
405 -#define TC_REPLACE_ENTRY       iptc_replace_entry
406 -#define TC_APPEND_ENTRY                iptc_append_entry
407 -#define TC_DELETE_ENTRY                iptc_delete_entry
408 -#define TC_DELETE_NUM_ENTRY    iptc_delete_num_entry
409 -#define TC_CHECK_PACKET                iptc_check_packet
410 -#define TC_FLUSH_ENTRIES       iptc_flush_entries
411 -#define TC_ZERO_ENTRIES                iptc_zero_entries
412 -#define TC_READ_COUNTER                iptc_read_counter
413 -#define TC_ZERO_COUNTER                iptc_zero_counter
414 -#define TC_SET_COUNTER         iptc_set_counter
415 -#define TC_CREATE_CHAIN                iptc_create_chain
416 -#define TC_GET_REFERENCES      iptc_get_references
417 -#define TC_DELETE_CHAIN                iptc_delete_chain
418 -#define TC_RENAME_CHAIN                iptc_rename_chain
419 -#define TC_SET_POLICY          iptc_set_policy
420 -#define TC_GET_RAW_SOCKET      iptc_get_raw_socket
421 -#define TC_INIT                        iptc_init
422 -#define TC_FREE                        iptc_free
423 -#define TC_COMMIT              iptc_commit
424 -#define TC_STRERROR            iptc_strerror
425 -#define TC_NUM_RULES           iptc_num_rules
426 -#define TC_GET_RULE            iptc_get_rule
427 -
428 -#define TC_AF                  AF_INET
429 -#define TC_IPPROTO             IPPROTO_IP
430 -
431 -#define SO_SET_REPLACE         IPT_SO_SET_REPLACE
432 -#define SO_SET_ADD_COUNTERS    IPT_SO_SET_ADD_COUNTERS
433 -#define SO_GET_INFO            IPT_SO_GET_INFO
434 -#define SO_GET_ENTRIES         IPT_SO_GET_ENTRIES
435 -#define SO_GET_VERSION         IPT_SO_GET_VERSION
436 -
437 -#define STANDARD_TARGET                IPT_STANDARD_TARGET
438 -#define LABEL_RETURN           IPTC_LABEL_RETURN
439 -#define LABEL_ACCEPT           IPTC_LABEL_ACCEPT
440 -#define LABEL_DROP             IPTC_LABEL_DROP
441 -#define LABEL_QUEUE            IPTC_LABEL_QUEUE
442 -
443 -#define ALIGN                  IPT_ALIGN
444 -#define RETURN                 IPT_RETURN
445 -
446 -#include "libiptc.c"
447 -
448 -#define IP_PARTS_NATIVE(n)                     \
449 -(unsigned int)((n)>>24)&0xFF,                  \
450 -(unsigned int)((n)>>16)&0xFF,                  \
451 -(unsigned int)((n)>>8)&0xFF,                   \
452 -(unsigned int)((n)&0xFF)
453 -
454 -#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n))
455 -
456 -int
457 -dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle)
458 -{
459 -       size_t i;
460 -       STRUCT_ENTRY_TARGET *t;
461 -
462 -       printf("Entry %u (%lu):\n", iptcb_entry2index(handle, e),
463 -              iptcb_entry2offset(handle, e));
464 -       printf("SRC IP: %u.%u.%u.%u/%u.%u.%u.%u\n",
465 -              IP_PARTS(e->ip.src.s_addr),IP_PARTS(e->ip.smsk.s_addr));
466 -       printf("DST IP: %u.%u.%u.%u/%u.%u.%u.%u\n",
467 -              IP_PARTS(e->ip.dst.s_addr),IP_PARTS(e->ip.dmsk.s_addr));
468 -       printf("Interface: `%s'/", e->ip.iniface);
469 -       for (i = 0; i < IFNAMSIZ; i++)
470 -               printf("%c", e->ip.iniface_mask[i] ? 'X' : '.');
471 -       printf("to `%s'/", e->ip.outiface);
472 -       for (i = 0; i < IFNAMSIZ; i++)
473 -               printf("%c", e->ip.outiface_mask[i] ? 'X' : '.');
474 -       printf("\nProtocol: %u\n", e->ip.proto);
475 -       printf("Flags: %02X\n", e->ip.flags);
476 -       printf("Invflags: %02X\n", e->ip.invflags);
477 -       printf("Counters: %llu packets, %llu bytes\n",
478 -              (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
479 -       printf("Cache: %08X\n", e->nfcache);
480 -
481 -       IPT_MATCH_ITERATE(e, print_match);
482 -
483 -       t = GET_TARGET(e);
484 -       printf("Target name: `%s' [%u]\n", t->u.user.name, t->u.target_size);
485 -       if (strcmp(t->u.user.name, STANDARD_TARGET) == 0) {
486 -               const unsigned char *data = t->data;
487 -               int pos = *(const int *)data;
488 -               if (pos < 0)
489 -                       printf("verdict=%s\n",
490 -                              pos == -NF_ACCEPT-1 ? "NF_ACCEPT"
491 -                              : pos == -NF_DROP-1 ? "NF_DROP"
492 -                              : pos == -NF_QUEUE-1 ? "NF_QUEUE"
493 -                              : pos == RETURN ? "RETURN"
494 -                              : "UNKNOWN");
495 -               else
496 -                       printf("verdict=%u\n", pos);
497 -       } else if (strcmp(t->u.user.name, IPT_ERROR_TARGET) == 0)
498 -               printf("error=`%s'\n", t->data);
499 -
500 -       printf("\n");
501 -       return 0;
502 -}
503 -
504 -static unsigned char *
505 -is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b, unsigned char *matchmask)
506 -{
507 -       unsigned int i;
508 -       unsigned char *mptr;
509 -
510 -       /* Always compare head structures: ignore mask here. */
511 -       if (a->ip.src.s_addr != b->ip.src.s_addr
512 -           || a->ip.dst.s_addr != b->ip.dst.s_addr
513 -           || a->ip.smsk.s_addr != b->ip.smsk.s_addr
514 -           || a->ip.dmsk.s_addr != b->ip.dmsk.s_addr
515 -           || a->ip.proto != b->ip.proto
516 -           || a->ip.flags != b->ip.flags
517 -           || a->ip.invflags != b->ip.invflags)
518 -               return NULL;
519 -
520 -       for (i = 0; i < IFNAMSIZ; i++) {
521 -               if (a->ip.iniface_mask[i] != b->ip.iniface_mask[i])
522 -                       return NULL;
523 -               if ((a->ip.iniface[i] & a->ip.iniface_mask[i])
524 -                   != (b->ip.iniface[i] & b->ip.iniface_mask[i]))
525 -                       return NULL;
526 -               if (a->ip.outiface_mask[i] != b->ip.outiface_mask[i])
527 -                       return NULL;
528 -               if ((a->ip.outiface[i] & a->ip.outiface_mask[i])
529 -                   != (b->ip.outiface[i] & b->ip.outiface_mask[i]))
530 -                       return NULL;
531 -       }
532 -
533 -       if (a->target_offset != b->target_offset
534 -           || a->next_offset != b->next_offset)
535 -               return NULL;
536 -
537 -       mptr = matchmask + sizeof(STRUCT_ENTRY);
538 -       if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
539 -               return NULL;
540 -       mptr += IPT_ALIGN(sizeof(struct ipt_entry_target));
541 -
542 -       return mptr;
543 -}
544 -
545 -#if 0
546 -/***************************** DEBUGGING ********************************/
547 -static inline int
548 -unconditional(const struct ipt_ip *ip)
549 -{
550 -       unsigned int i;
551 -
552 -       for (i = 0; i < sizeof(*ip)/sizeof(u_int32_t); i++)
553 -               if (((u_int32_t *)ip)[i])
554 -                       return 0;
555 -
556 -       return 1;
557 -}
558 -
559 -static inline int
560 -check_match(const STRUCT_ENTRY_MATCH *m, unsigned int *off)
561 -{
562 -       assert(m->u.match_size >= sizeof(STRUCT_ENTRY_MATCH));
563 -       assert(ALIGN(m->u.match_size) == m->u.match_size);
564 -
565 -       (*off) += m->u.match_size;
566 -       return 0;
567 -}
568 -
569 -static inline int
570 -check_entry(const STRUCT_ENTRY *e, unsigned int *i, unsigned int *off,
571 -           unsigned int user_offset, int *was_return,
572 -           TC_HANDLE_T h)
573 -{
574 -       unsigned int toff;
575 -       STRUCT_STANDARD_TARGET *t;
576 -
577 -       assert(e->target_offset >= sizeof(STRUCT_ENTRY));
578 -       assert(e->next_offset >= e->target_offset
579 -              + sizeof(STRUCT_ENTRY_TARGET));
580 -       toff = sizeof(STRUCT_ENTRY);
581 -       IPT_MATCH_ITERATE(e, check_match, &toff);
582 -
583 -       assert(toff == e->target_offset);
584 -
585 -       t = (STRUCT_STANDARD_TARGET *)
586 -               GET_TARGET((STRUCT_ENTRY *)e);
587 -       /* next_offset will have to be multiple of entry alignment. */
588 -       assert(e->next_offset == ALIGN(e->next_offset));
589 -       assert(e->target_offset == ALIGN(e->target_offset));
590 -       assert(t->target.u.target_size == ALIGN(t->target.u.target_size));
591 -       assert(!TC_IS_CHAIN(t->target.u.user.name, h));
592 -
593 -       if (strcmp(t->target.u.user.name, STANDARD_TARGET) == 0) {
594 -               assert(t->target.u.target_size
595 -                      == ALIGN(sizeof(STRUCT_STANDARD_TARGET)));
596 -
597 -               assert(t->verdict == -NF_DROP-1
598 -                      || t->verdict == -NF_ACCEPT-1
599 -                      || t->verdict == RETURN
600 -                      || t->verdict < (int)h->entries->size);
601 -
602 -               if (t->verdict >= 0) {
603 -                       STRUCT_ENTRY *te = get_entry(h, t->verdict);
604 -                       int idx;
605 -
606 -                       idx = iptcb_entry2index(h, te);
607 -                       assert(strcmp(GET_TARGET(te)->u.user.name,
608 -                                     IPT_ERROR_TARGET)
609 -                              != 0);
610 -                       assert(te != e);
611 -
612 -                       /* Prior node must be error node, or this node. */
613 -                       assert(t->verdict == iptcb_entry2offset(h, e)+e->next_offset
614 -                              || strcmp(GET_TARGET(index2entry(h, idx-1))
615 -                                        ->u.user.name, IPT_ERROR_TARGET)
616 -                              == 0);
617 -               }
618 -
619 -               if (t->verdict == RETURN
620 -                   && unconditional(&e->ip)
621 -                   && e->target_offset == sizeof(*e))
622 -                       *was_return = 1;
623 -               else
624 -                       *was_return = 0;
625 -       } else if (strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0) {
626 -               assert(t->target.u.target_size
627 -                      == ALIGN(sizeof(struct ipt_error_target)));
628 -
629 -               /* If this is in user area, previous must have been return */
630 -               if (*off > user_offset)
631 -                       assert(*was_return);
632 -
633 -               *was_return = 0;
634 -       }
635 -       else *was_return = 0;
636 -
637 -       if (*off == user_offset)
638 -               assert(strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0);
639 -
640 -       (*off) += e->next_offset;
641 -       (*i)++;
642 -       return 0;
643 -}
644 -
645 -#ifdef IPTC_DEBUG
646 -/* Do every conceivable sanity check on the handle */
647 -static void
648 -do_check(TC_HANDLE_T h, unsigned int line)
649 -{
650 -       unsigned int i, n;
651 -       unsigned int user_offset; /* Offset of first user chain */
652 -       int was_return;
653 -
654 -       assert(h->changed == 0 || h->changed == 1);
655 -       if (strcmp(h->info.name, "filter") == 0) {
656 -               assert(h->info.valid_hooks
657 -                      == (1 << NF_IP_LOCAL_IN
658 -                          | 1 << NF_IP_FORWARD
659 -                          | 1 << NF_IP_LOCAL_OUT));
660 -
661 -               /* Hooks should be first three */
662 -               assert(h->info.hook_entry[NF_IP_LOCAL_IN] == 0);
663 -
664 -               n = get_chain_end(h, 0);
665 -               n += get_entry(h, n)->next_offset;
666 -               assert(h->info.hook_entry[NF_IP_FORWARD] == n);
667 -
668 -               n = get_chain_end(h, n);
669 -               n += get_entry(h, n)->next_offset;
670 -               assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
671 -
672 -               user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
673 -       } else if (strcmp(h->info.name, "nat") == 0) {
674 -               assert((h->info.valid_hooks
675 -                       == (1 << NF_IP_PRE_ROUTING
676 -                           | 1 << NF_IP_POST_ROUTING
677 -                           | 1 << NF_IP_LOCAL_OUT)) ||
678 -                      (h->info.valid_hooks
679 -                       == (1 << NF_IP_PRE_ROUTING
680 -                           | 1 << NF_IP_LOCAL_IN
681 -                           | 1 << NF_IP_POST_ROUTING
682 -                           | 1 << NF_IP_LOCAL_OUT)));
683 -
684 -               assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0);
685 -
686 -               n = get_chain_end(h, 0);
687 -
688 -               n += get_entry(h, n)->next_offset;
689 -               assert(h->info.hook_entry[NF_IP_POST_ROUTING] == n);
690 -               n = get_chain_end(h, n);
691 -
692 -               n += get_entry(h, n)->next_offset;
693 -               assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
694 -               user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
695 -
696 -               if (h->info.valid_hooks & (1 << NF_IP_LOCAL_IN)) {
697 -                       n = get_chain_end(h, n);
698 -                       n += get_entry(h, n)->next_offset;
699 -                       assert(h->info.hook_entry[NF_IP_LOCAL_IN] == n);
700 -                       user_offset = h->info.hook_entry[NF_IP_LOCAL_IN];
701 -               }
702 -
703 -       } else if (strcmp(h->info.name, "mangle") == 0) {
704 -               /* This code is getting ugly because linux < 2.4.18-pre6 had
705 -                * two mangle hooks, linux >= 2.4.18-pre6 has five mangle hooks
706 -                * */
707 -               assert((h->info.valid_hooks
708 -                       == (1 << NF_IP_PRE_ROUTING
709 -                           | 1 << NF_IP_LOCAL_OUT)) || 
710 -                      (h->info.valid_hooks
711 -                       == (1 << NF_IP_PRE_ROUTING
712 -                           | 1 << NF_IP_LOCAL_IN
713 -                           | 1 << NF_IP_FORWARD
714 -                           | 1 << NF_IP_LOCAL_OUT
715 -                           | 1 << NF_IP_POST_ROUTING)));
716 -
717 -               /* Hooks should be first five */
718 -               assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0);
719 -
720 -               n = get_chain_end(h, 0);
721 -
722 -               if (h->info.valid_hooks & (1 << NF_IP_LOCAL_IN)) {
723 -                       n += get_entry(h, n)->next_offset;
724 -                       assert(h->info.hook_entry[NF_IP_LOCAL_IN] == n);
725 -                       n = get_chain_end(h, n);
726 -               }
727 -
728 -               if (h->info.valid_hooks & (1 << NF_IP_FORWARD)) {
729 -                       n += get_entry(h, n)->next_offset;
730 -                       assert(h->info.hook_entry[NF_IP_FORWARD] == n);
731 -                       n = get_chain_end(h, n);
732 -               }
733 -
734 -               n += get_entry(h, n)->next_offset;
735 -               assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
736 -               user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
737 -
738 -               if (h->info.valid_hooks & (1 << NF_IP_POST_ROUTING)) {
739 -                       n = get_chain_end(h, n);
740 -                       n += get_entry(h, n)->next_offset;
741 -                       assert(h->info.hook_entry[NF_IP_POST_ROUTING] == n);
742 -                       user_offset = h->info.hook_entry[NF_IP_POST_ROUTING];
743 -               }
744 -       } else if (strcmp(h->info.name, "raw") == 0) {
745 -               assert(h->info.valid_hooks
746 -                      == (1 << NF_IP_PRE_ROUTING
747 -                          | 1 << NF_IP_LOCAL_OUT));
748 -
749 -               /* Hooks should be first three */
750 -               assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0);
751 -
752 -               n = get_chain_end(h, n);
753 -               n += get_entry(h, n)->next_offset;
754 -               assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
755 -
756 -               user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
757 -
758 -#ifdef NF_IP_DROPPING
759 -       } else if (strcmp(h->info.name, "drop") == 0) {
760 -               assert(h->info.valid_hooks == (1 << NF_IP_DROPPING));
761 -
762 -               /* Hook should be first */
763 -               assert(h->info.hook_entry[NF_IP_DROPPING] == 0);
764 -               user_offset = 0;
765 -#endif
766 -       } else {
767 -               fprintf(stderr, "Unknown table `%s'\n", h->info.name);
768 -               abort();
769 -       }
770 -
771 -       /* User chain == end of last builtin + policy entry */
772 -       user_offset = get_chain_end(h, user_offset);
773 -       user_offset += get_entry(h, user_offset)->next_offset;
774 -
775 -       /* Overflows should be end of entry chains, and unconditional
776 -           policy nodes. */
777 -       for (i = 0; i < NUMHOOKS; i++) {
778 -               STRUCT_ENTRY *e;
779 -               STRUCT_STANDARD_TARGET *t;
780 -
781 -               if (!(h->info.valid_hooks & (1 << i)))
782 -                       continue;
783 -               assert(h->info.underflow[i]
784 -                      == get_chain_end(h, h->info.hook_entry[i]));
785 -
786 -               e = get_entry(h, get_chain_end(h, h->info.hook_entry[i]));
787 -               assert(unconditional(&e->ip));
788 -               assert(e->target_offset == sizeof(*e));
789 -               t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
790 -               assert(t->target.u.target_size == ALIGN(sizeof(*t)));
791 -               assert(e->next_offset == sizeof(*e) + ALIGN(sizeof(*t)));
792 -
793 -               assert(strcmp(t->target.u.user.name, STANDARD_TARGET)==0);
794 -               assert(t->verdict == -NF_DROP-1 || t->verdict == -NF_ACCEPT-1);
795 -
796 -               /* Hooks and underflows must be valid entries */
797 -               entry2index(h, get_entry(h, h->info.hook_entry[i]));
798 -               entry2index(h, get_entry(h, h->info.underflow[i]));
799 -       }
800 -
801 -       assert(h->info.size
802 -              >= h->info.num_entries * (sizeof(STRUCT_ENTRY)
803 -                                        +sizeof(STRUCT_STANDARD_TARGET)));
804 -
805 -       assert(h->entries.size
806 -              >= (h->new_number
807 -                  * (sizeof(STRUCT_ENTRY)
808 -                     + sizeof(STRUCT_STANDARD_TARGET))));
809 -       assert(strcmp(h->info.name, h->entries.name) == 0);
810 -
811 -       i = 0; n = 0;
812 -       was_return = 0;
813 -       /* Check all the entries. */
814 -       ENTRY_ITERATE(h->entries.entrytable, h->entries.size,
815 -                     check_entry, &i, &n, user_offset, &was_return, h);
816 -
817 -       assert(i == h->new_number);
818 -       assert(n == h->entries.size);
819 -
820 -       /* Final entry must be error node */
821 -       assert(strcmp(GET_TARGET(index2entry(h, h->new_number-1))
822 -                     ->u.user.name,
823 -                     ERROR_TARGET) == 0);
824 -}
825 -#endif /*IPTC_DEBUG*/
826 -
827 -#endif
828 diff --git a/src/owniptc/libip6tc.c b/src/owniptc/libip6tc.c
829 deleted file mode 100644
830 index 672dae1..0000000
831 --- a/src/owniptc/libip6tc.c
832 +++ /dev/null
833 @@ -1,456 +0,0 @@
834 -/**
835 - * This file was imported from the iptables sources.
836 - * Copyright (C) 1999-2008 Netfilter Core Team
837 - *
838 - * This program is free software; you can redistribute it and/or modify it
839 - * under the terms of the GNU General Public License as published by the
840 - * Free Software Foundation; only version 2 of the License is applicable.
841 - *
842 - * This program is distributed in the hope that it will be useful, but
843 - * WITHOUT ANY WARRANTY; without even the implied warranty of
844 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
845 - * General Public License for more details.
846 - *
847 - * You should have received a copy of the GNU General Public License along
848 - * with this program; if not, write to the Free Software Foundation, Inc.,
849 - * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
850 - */
851 -
852 -/* Library which manipulates firewall rules.  Version 0.1. */
853 -
854 -/* Architecture of firewall rules is as follows:
855 - *
856 - * Chains go INPUT, FORWARD, OUTPUT then user chains.
857 - * Each user chain starts with an ERROR node.
858 - * Every chain ends with an unconditional jump: a RETURN for user chains,
859 - * and a POLICY for built-ins.
860 - */
861 -
862 -/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
863 -   COPYING for details). */
864 -
865 -#include <assert.h>
866 -#include <string.h>
867 -#include <errno.h>
868 -#include <stdlib.h>
869 -#include <stdio.h>
870 -#include <unistd.h>
871 -#include <arpa/inet.h>
872 -
873 -#ifdef DEBUG_CONNTRACK
874 -#define inline
875 -#endif
876 -
877 -#if !defined(__GLIBC__) || (__GLIBC__ < 2)
878 -typedef unsigned int socklen_t;
879 -#endif
880 -
881 -#include "libip6tc.h"
882 -
883 -#define HOOK_PRE_ROUTING       NF_IP6_PRE_ROUTING
884 -#define HOOK_LOCAL_IN          NF_IP6_LOCAL_IN
885 -#define HOOK_FORWARD           NF_IP6_FORWARD
886 -#define HOOK_LOCAL_OUT         NF_IP6_LOCAL_OUT
887 -#define HOOK_POST_ROUTING      NF_IP6_POST_ROUTING
888 -
889 -#define STRUCT_ENTRY_TARGET    struct ip6t_entry_target
890 -#define STRUCT_ENTRY           struct ip6t_entry
891 -#define STRUCT_ENTRY_MATCH     struct ip6t_entry_match
892 -#define STRUCT_GETINFO         struct ip6t_getinfo
893 -#define STRUCT_GET_ENTRIES     struct ip6t_get_entries
894 -#define STRUCT_COUNTERS                struct ip6t_counters
895 -#define STRUCT_COUNTERS_INFO   struct ip6t_counters_info
896 -#define STRUCT_STANDARD_TARGET struct ip6t_standard_target
897 -#define STRUCT_REPLACE         struct ip6t_replace
898 -
899 -#define STRUCT_TC_HANDLE       struct ip6tc_handle
900 -#define TC_HANDLE_T            ip6tc_handle_t
901 -
902 -#define ENTRY_ITERATE          IP6T_ENTRY_ITERATE
903 -#define TABLE_MAXNAMELEN       IP6T_TABLE_MAXNAMELEN
904 -#define FUNCTION_MAXNAMELEN    IP6T_FUNCTION_MAXNAMELEN
905 -
906 -#define GET_TARGET             ip6t_get_target
907 -
908 -#define ERROR_TARGET           IP6T_ERROR_TARGET
909 -#define NUMHOOKS               NF_IP6_NUMHOOKS
910 -
911 -#define IPT_CHAINLABEL         ip6t_chainlabel
912 -
913 -#define TC_DUMP_ENTRIES                dump_entries6
914 -#define TC_IS_CHAIN            ip6tc_is_chain
915 -#define TC_FIRST_CHAIN         ip6tc_first_chain
916 -#define TC_NEXT_CHAIN          ip6tc_next_chain
917 -#define TC_FIRST_RULE          ip6tc_first_rule
918 -#define TC_NEXT_RULE           ip6tc_next_rule
919 -#define TC_GET_TARGET          ip6tc_get_target
920 -#define TC_BUILTIN             ip6tc_builtin
921 -#define TC_GET_POLICY          ip6tc_get_policy
922 -#define TC_INSERT_ENTRY                ip6tc_insert_entry
923 -#define TC_REPLACE_ENTRY       ip6tc_replace_entry
924 -#define TC_APPEND_ENTRY                ip6tc_append_entry
925 -#define TC_DELETE_ENTRY                ip6tc_delete_entry
926 -#define TC_DELETE_NUM_ENTRY    ip6tc_delete_num_entry
927 -#define TC_CHECK_PACKET                ip6tc_check_packet
928 -#define TC_FLUSH_ENTRIES       ip6tc_flush_entries
929 -#define TC_ZERO_ENTRIES                ip6tc_zero_entries
930 -#define TC_ZERO_COUNTER                ip6tc_zero_counter
931 -#define TC_READ_COUNTER                ip6tc_read_counter
932 -#define TC_SET_COUNTER         ip6tc_set_counter
933 -#define TC_CREATE_CHAIN                ip6tc_create_chain
934 -#define TC_GET_REFERENCES      ip6tc_get_references
935 -#define TC_DELETE_CHAIN                ip6tc_delete_chain
936 -#define TC_RENAME_CHAIN                ip6tc_rename_chain
937 -#define TC_SET_POLICY          ip6tc_set_policy
938 -#define TC_GET_RAW_SOCKET      ip6tc_get_raw_socket
939 -#define TC_INIT                        ip6tc_init
940 -#define TC_FREE                        ip6tc_free
941 -#define TC_COMMIT              ip6tc_commit
942 -#define TC_STRERROR            ip6tc_strerror
943 -#define TC_NUM_RULES           ip6tc_num_rules
944 -#define TC_GET_RULE            ip6tc_get_rule
945 -
946 -#define TC_AF                  AF_INET6
947 -#define TC_IPPROTO             IPPROTO_IPV6
948 -
949 -#define SO_SET_REPLACE         IP6T_SO_SET_REPLACE
950 -#define SO_SET_ADD_COUNTERS    IP6T_SO_SET_ADD_COUNTERS
951 -#define SO_GET_INFO            IP6T_SO_GET_INFO
952 -#define SO_GET_ENTRIES         IP6T_SO_GET_ENTRIES
953 -#define SO_GET_VERSION         IP6T_SO_GET_VERSION
954 -
955 -#define STANDARD_TARGET                IP6T_STANDARD_TARGET
956 -#define LABEL_RETURN           IP6TC_LABEL_RETURN
957 -#define LABEL_ACCEPT           IP6TC_LABEL_ACCEPT
958 -#define LABEL_DROP             IP6TC_LABEL_DROP
959 -#define LABEL_QUEUE            IP6TC_LABEL_QUEUE
960 -
961 -#define ALIGN                  IP6T_ALIGN
962 -#define RETURN                 IP6T_RETURN
963 -
964 -#include "libiptc.c"
965 -
966 -#define BIT6(a, l) \
967 - ((ntohl(a->s6_addr32[(l) / 32]) >> (31 - ((l) & 31))) & 1)
968 -
969 -int
970 -ipv6_prefix_length(const struct in6_addr *a)
971 -{
972 -       int l, i;
973 -       for (l = 0; l < 128; l++) {
974 -               if (BIT6(a, l) == 0)
975 -                       break;
976 -       }
977 -       for (i = l + 1; i < 128; i++) {
978 -               if (BIT6(a, i) == 1)
979 -                       return -1;
980 -       }
981 -       return l;
982 -}
983 -
984 -static int
985 -dump_entry(struct ip6t_entry *e, const ip6tc_handle_t handle)
986 -{
987 -       size_t i;
988 -       char buf[40];
989 -       int len;
990 -       struct ip6t_entry_target *t;
991 -       
992 -       printf("Entry %u (%lu):\n", iptcb_entry2index(handle, e),
993 -              iptcb_entry2offset(handle, e));
994 -       puts("SRC IP: ");
995 -       inet_ntop(AF_INET6, &e->ipv6.src, buf, sizeof buf);
996 -       puts(buf);
997 -       putchar('/');
998 -       len = ipv6_prefix_length(&e->ipv6.smsk);
999 -       if (len != -1)
1000 -               printf("%d", len);
1001 -       else {
1002 -               inet_ntop(AF_INET6, &e->ipv6.smsk, buf, sizeof buf);
1003 -               puts(buf);
1004 -       }
1005 -       putchar('\n');
1006 -       
1007 -       puts("DST IP: ");
1008 -       inet_ntop(AF_INET6, &e->ipv6.dst, buf, sizeof buf);
1009 -       puts(buf);
1010 -       putchar('/');
1011 -       len = ipv6_prefix_length(&e->ipv6.dmsk);
1012 -       if (len != -1)
1013 -               printf("%d", len);
1014 -       else {
1015 -               inet_ntop(AF_INET6, &e->ipv6.dmsk, buf, sizeof buf);
1016 -               puts(buf);
1017 -       }
1018 -       putchar('\n');
1019 -       
1020 -       printf("Interface: `%s'/", e->ipv6.iniface);
1021 -       for (i = 0; i < IFNAMSIZ; i++)
1022 -               printf("%c", e->ipv6.iniface_mask[i] ? 'X' : '.');
1023 -       printf("to `%s'/", e->ipv6.outiface);
1024 -       for (i = 0; i < IFNAMSIZ; i++)
1025 -               printf("%c", e->ipv6.outiface_mask[i] ? 'X' : '.');
1026 -       printf("\nProtocol: %u\n", e->ipv6.proto);
1027 -       if (e->ipv6.flags & IP6T_F_TOS)
1028 -               printf("TOS: %u\n", e->ipv6.tos);
1029 -       printf("Flags: %02X\n", e->ipv6.flags);
1030 -       printf("Invflags: %02X\n", e->ipv6.invflags);
1031 -       printf("Counters: %llu packets, %llu bytes\n",
1032 -              (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
1033 -       printf("Cache: %08X\n", e->nfcache);
1034 -       
1035 -       IP6T_MATCH_ITERATE(e, print_match);
1036 -
1037 -       t = ip6t_get_target(e);
1038 -       printf("Target name: `%s' [%u]\n", t->u.user.name, t->u.target_size);
1039 -       if (strcmp(t->u.user.name, IP6T_STANDARD_TARGET) == 0) {
1040 -               const unsigned char *data = t->data;
1041 -               int pos = *(const int *)data;
1042 -               if (pos < 0)
1043 -                       printf("verdict=%s\n",
1044 -                              pos == -NF_ACCEPT-1 ? "NF_ACCEPT"
1045 -                              : pos == -NF_DROP-1 ? "NF_DROP"
1046 -                              : pos == IP6T_RETURN ? "RETURN"
1047 -                              : "UNKNOWN");
1048 -               else
1049 -                       printf("verdict=%u\n", pos);
1050 -       } else if (strcmp(t->u.user.name, IP6T_ERROR_TARGET) == 0)
1051 -               printf("error=`%s'\n", t->data);
1052 -
1053 -       printf("\n");
1054 -       return 0;
1055 -}
1056 -
1057 -static unsigned char *
1058 -is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b,
1059 -       unsigned char *matchmask)
1060 -{
1061 -       unsigned int i;
1062 -       unsigned char *mptr;
1063 -
1064 -       /* Always compare head structures: ignore mask here. */
1065 -       if (memcmp(&a->ipv6.src, &b->ipv6.src, sizeof(struct in6_addr))
1066 -           || memcmp(&a->ipv6.dst, &b->ipv6.dst, sizeof(struct in6_addr))
1067 -           || memcmp(&a->ipv6.smsk, &b->ipv6.smsk, sizeof(struct in6_addr))
1068 -           || memcmp(&a->ipv6.dmsk, &b->ipv6.dmsk, sizeof(struct in6_addr))
1069 -           || a->ipv6.proto != b->ipv6.proto
1070 -           || a->ipv6.tos != b->ipv6.tos
1071 -           || a->ipv6.flags != b->ipv6.flags
1072 -           || a->ipv6.invflags != b->ipv6.invflags)
1073 -               return NULL;
1074 -
1075 -       for (i = 0; i < IFNAMSIZ; i++) {
1076 -               if (a->ipv6.iniface_mask[i] != b->ipv6.iniface_mask[i])
1077 -                       return NULL;
1078 -               if ((a->ipv6.iniface[i] & a->ipv6.iniface_mask[i])
1079 -                   != (b->ipv6.iniface[i] & b->ipv6.iniface_mask[i]))
1080 -                       return NULL;
1081 -               if (a->ipv6.outiface_mask[i] != b->ipv6.outiface_mask[i])
1082 -                       return NULL;
1083 -               if ((a->ipv6.outiface[i] & a->ipv6.outiface_mask[i])
1084 -                   != (b->ipv6.outiface[i] & b->ipv6.outiface_mask[i]))
1085 -                       return NULL;
1086 -       }
1087 -
1088 -       if (a->target_offset != b->target_offset
1089 -           || a->next_offset != b->next_offset)
1090 -               return NULL;
1091 -
1092 -       mptr = matchmask + sizeof(STRUCT_ENTRY);
1093 -       if (IP6T_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
1094 -               return NULL;
1095 -       mptr += IP6T_ALIGN(sizeof(struct ip6t_entry_target));
1096 -
1097 -       return mptr;
1098 -}
1099 -
1100 -/* All zeroes == unconditional rule. */
1101 -static inline int
1102 -unconditional(const struct ip6t_ip6 *ipv6)
1103 -{
1104 -       unsigned int i;
1105 -
1106 -       for (i = 0; i < sizeof(*ipv6); i++)
1107 -               if (((char *)ipv6)[i])
1108 -                       break;
1109 -
1110 -       return (i == sizeof(*ipv6));
1111 -}
1112 -
1113 -#ifdef IPTC_DEBUG
1114 -/* Do every conceivable sanity check on the handle */
1115 -static void
1116 -do_check(TC_HANDLE_T h, unsigned int line)
1117 -{
1118 -       unsigned int i, n;
1119 -       unsigned int user_offset; /* Offset of first user chain */
1120 -       int was_return;
1121 -
1122 -       assert(h->changed == 0 || h->changed == 1);
1123 -       if (strcmp(h->info.name, "filter") == 0) {
1124 -               assert(h->info.valid_hooks
1125 -                      == (1 << NF_IP6_LOCAL_IN
1126 -                          | 1 << NF_IP6_FORWARD
1127 -                          | 1 << NF_IP6_LOCAL_OUT));
1128 -
1129 -               /* Hooks should be first three */
1130 -               assert(h->info.hook_entry[NF_IP6_LOCAL_IN] == 0);
1131 -
1132 -               n = get_chain_end(h, 0);
1133 -               n += get_entry(h, n)->next_offset;
1134 -               assert(h->info.hook_entry[NF_IP6_FORWARD] == n);
1135 -
1136 -               n = get_chain_end(h, n);
1137 -               n += get_entry(h, n)->next_offset;
1138 -               assert(h->info.hook_entry[NF_IP6_LOCAL_OUT] == n);
1139 -
1140 -               user_offset = h->info.hook_entry[NF_IP6_LOCAL_OUT];
1141 -       } else if (strcmp(h->info.name, "nat") == 0) {
1142 -               assert((h->info.valid_hooks
1143 -                       == (1 << NF_IP6_PRE_ROUTING
1144 -                           | 1 << NF_IP6_LOCAL_OUT
1145 -                           | 1 << NF_IP6_POST_ROUTING)) ||
1146 -                      (h->info.valid_hooks
1147 -                       == (1 << NF_IP6_PRE_ROUTING
1148 -                           | 1 << NF_IP6_LOCAL_IN
1149 -                           | 1 << NF_IP6_LOCAL_OUT
1150 -                           | 1 << NF_IP6_POST_ROUTING)));
1151 -
1152 -               assert(h->info.hook_entry[NF_IP6_PRE_ROUTING] == 0);
1153 -
1154 -               n = get_chain_end(h, 0);
1155 -
1156 -               n += get_entry(h, n)->next_offset;
1157 -               assert(h->info.hook_entry[NF_IP6_POST_ROUTING] == n);
1158 -               n = get_chain_end(h, n);
1159 -
1160 -               n += get_entry(h, n)->next_offset;
1161 -               assert(h->info.hook_entry[NF_IP6_LOCAL_OUT] == n);
1162 -               user_offset = h->info.hook_entry[NF_IP6_LOCAL_OUT];
1163 -
1164 -               if (h->info.valid_hooks & (1 << NF_IP6_LOCAL_IN)) {
1165 -                       n = get_chain_end(h, n);
1166 -                       n += get_entry(h, n)->next_offset;
1167 -                       assert(h->info.hook_entry[NF_IP6_LOCAL_IN] == n);
1168 -                       user_offset = h->info.hook_entry[NF_IP6_LOCAL_IN];
1169 -               }
1170 -
1171 -       } else if (strcmp(h->info.name, "mangle") == 0) {
1172 -               /* This code is getting ugly because linux < 2.4.18-pre6 had
1173 -                * two mangle hooks, linux >= 2.4.18-pre6 has five mangle hooks
1174 -                * */
1175 -               assert((h->info.valid_hooks
1176 -                       == (1 << NF_IP6_PRE_ROUTING
1177 -                           | 1 << NF_IP6_LOCAL_OUT)) ||
1178 -                      (h->info.valid_hooks
1179 -                       == (1 << NF_IP6_PRE_ROUTING
1180 -                           | 1 << NF_IP6_LOCAL_IN
1181 -                           | 1 << NF_IP6_FORWARD
1182 -                           | 1 << NF_IP6_LOCAL_OUT
1183 -                           | 1 << NF_IP6_POST_ROUTING)));
1184 -
1185 -               /* Hooks should be first five */
1186 -               assert(h->info.hook_entry[NF_IP6_PRE_ROUTING] == 0);
1187 -
1188 -               n = get_chain_end(h, 0);
1189 -
1190 -               if (h->info.valid_hooks & (1 << NF_IP6_LOCAL_IN)) {
1191 -                       n += get_entry(h, n)->next_offset;
1192 -                       assert(h->info.hook_entry[NF_IP6_LOCAL_IN] == n);
1193 -                       n = get_chain_end(h, n);
1194 -               }
1195 -
1196 -               if (h->info.valid_hooks & (1 << NF_IP6_FORWARD)) {
1197 -                       n += get_entry(h, n)->next_offset;
1198 -                       assert(h->info.hook_entry[NF_IP6_FORWARD] == n);
1199 -                       n = get_chain_end(h, n);
1200 -               }
1201 -
1202 -               n += get_entry(h, n)->next_offset;
1203 -               assert(h->info.hook_entry[NF_IP6_LOCAL_OUT] == n);
1204 -               user_offset = h->info.hook_entry[NF_IP6_LOCAL_OUT];
1205 -
1206 -               if (h->info.valid_hooks & (1 << NF_IP6_POST_ROUTING)) {
1207 -                       n = get_chain_end(h, n);
1208 -                       n += get_entry(h, n)->next_offset;
1209 -                       assert(h->info.hook_entry[NF_IP6_POST_ROUTING] == n);
1210 -                       user_offset = h->info.hook_entry[NF_IP6_POST_ROUTING];
1211 -               }
1212 -       } else if (strcmp(h->info.name, "raw") == 0) {
1213 -               assert(h->info.valid_hooks
1214 -                      == (1 << NF_IP6_PRE_ROUTING
1215 -                          | 1 << NF_IP6_LOCAL_OUT));
1216 -
1217 -               /* Hooks should be first three */
1218 -               assert(h->info.hook_entry[NF_IP6_PRE_ROUTING] == 0);
1219 -
1220 -               n = get_chain_end(h, n);
1221 -               n += get_entry(h, n)->next_offset;
1222 -               assert(h->info.hook_entry[NF_IP6_LOCAL_OUT] == n);
1223 -
1224 -               user_offset = h->info.hook_entry[NF_IP6_LOCAL_OUT];
1225 -       } else {
1226 -                fprintf(stderr, "Unknown table `%s'\n", h->info.name);
1227 -               abort();
1228 -       }
1229 -
1230 -       /* User chain == end of last builtin + policy entry */
1231 -       user_offset = get_chain_end(h, user_offset);
1232 -       user_offset += get_entry(h, user_offset)->next_offset;
1233 -
1234 -       /* Overflows should be end of entry chains, and unconditional
1235 -           policy nodes. */
1236 -       for (i = 0; i < NUMHOOKS; i++) {
1237 -               STRUCT_ENTRY *e;
1238 -               STRUCT_STANDARD_TARGET *t;
1239 -
1240 -               if (!(h->info.valid_hooks & (1 << i)))
1241 -                       continue;
1242 -               assert(h->info.underflow[i]
1243 -                      == get_chain_end(h, h->info.hook_entry[i]));
1244 -
1245 -               e = get_entry(h, get_chain_end(h, h->info.hook_entry[i]));
1246 -               assert(unconditional(&e->ipv6));
1247 -               assert(e->target_offset == sizeof(*e));
1248 -               t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
1249 -               printf("target_size=%u, align=%u\n",
1250 -                       t->target.u.target_size, ALIGN(sizeof(*t)));
1251 -               assert(t->target.u.target_size == ALIGN(sizeof(*t)));
1252 -               assert(e->next_offset == sizeof(*e) + ALIGN(sizeof(*t)));
1253 -
1254 -               assert(strcmp(t->target.u.user.name, STANDARD_TARGET)==0);
1255 -               assert(t->verdict == -NF_DROP-1 || t->verdict == -NF_ACCEPT-1);
1256 -
1257 -               /* Hooks and underflows must be valid entries */
1258 -               iptcb_entry2index(h, get_entry(h, h->info.hook_entry[i]));
1259 -               iptcb_entry2index(h, get_entry(h, h->info.underflow[i]));
1260 -       }
1261 -
1262 -       assert(h->info.size
1263 -              >= h->info.num_entries * (sizeof(STRUCT_ENTRY)
1264 -                                        +sizeof(STRUCT_STANDARD_TARGET)));
1265 -
1266 -       assert(h->entries.size
1267 -              >= (h->new_number
1268 -                  * (sizeof(STRUCT_ENTRY)
1269 -                     + sizeof(STRUCT_STANDARD_TARGET))));
1270 -       assert(strcmp(h->info.name, h->entries.name) == 0);
1271 -
1272 -       i = 0; n = 0;
1273 -       was_return = 0;
1274 -
1275 -#if 0
1276 -       /* Check all the entries. */
1277 -       ENTRY_ITERATE(h->entries.entrytable, h->entries.size,
1278 -                     check_entry, &i, &n, user_offset, &was_return, h);
1279 -
1280 -       assert(i == h->new_number);
1281 -       assert(n == h->entries.size);
1282 -
1283 -       /* Final entry must be error node */
1284 -       assert(strcmp(GET_TARGET(index2entry(h, h->new_number-1))
1285 -                     ->u.user.name,
1286 -                     ERROR_TARGET) == 0);
1287 -#endif
1288 -}
1289 -#endif /*IPTC_DEBUG*/
1290 diff --git a/src/owniptc/libip6tc.h b/src/owniptc/libip6tc.h
1291 deleted file mode 100644
1292 index 9253e11..0000000
1293 --- a/src/owniptc/libip6tc.h
1294 +++ /dev/null
1295 @@ -1,175 +0,0 @@
1296 -/**
1297 - * This file was imported from the iptables sources.
1298 - * Copyright (C) 1999-2008 Netfilter Core Team
1299 - *
1300 - * This program is free software; you can redistribute it and/or modify it
1301 - * under the terms of the GNU General Public License as published by the
1302 - * Free Software Foundation; only version 2 of the License is applicable.
1303 - *
1304 - * This program is distributed in the hope that it will be useful, but
1305 - * WITHOUT ANY WARRANTY; without even the implied warranty of
1306 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1307 - * General Public License for more details.
1308 - *
1309 - * You should have received a copy of the GNU General Public License along
1310 - * with this program; if not, write to the Free Software Foundation, Inc.,
1311 - * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
1312 - */
1313 -
1314 -#ifndef _LIBIP6TC_H
1315 -#define _LIBIP6TC_H
1316 -/* Library which manipulates firewall rules. Version 0.2. */
1317 -
1318 -#include <linux/types.h>
1319 -#include "ipt_kernel_headers.h"
1320 -#include <linux/netfilter_ipv6/ip6_tables.h>
1321 -
1322 -#ifndef IP6T_MIN_ALIGN
1323 -#define IP6T_MIN_ALIGN (__alignof__(struct ip6t_entry))
1324 -#endif
1325 -#define IP6T_ALIGN(s) (((s) + (IP6T_MIN_ALIGN-1)) & ~(IP6T_MIN_ALIGN-1))
1326 -
1327 -typedef char ip6t_chainlabel[32];
1328 -
1329 -#define IP6TC_LABEL_ACCEPT "ACCEPT"
1330 -#define IP6TC_LABEL_DROP "DROP"
1331 -#define IP6TC_LABEL_QUEUE   "QUEUE"
1332 -#define IP6TC_LABEL_RETURN "RETURN"
1333 -
1334 -/* Transparent handle type. */
1335 -typedef struct ip6tc_handle *ip6tc_handle_t;
1336 -
1337 -/* Does this chain exist? */
1338 -int ip6tc_is_chain(const char *chain, const ip6tc_handle_t handle);
1339 -
1340 -/* Take a snapshot of the rules. Returns NULL on error. */
1341 -ip6tc_handle_t ip6tc_init(const char *tablename);
1342 -
1343 -/* Cleanup after ip6tc_init(). */
1344 -void ip6tc_free(ip6tc_handle_t *h);
1345 -
1346 -/* Iterator functions to run through the chains.  Returns NULL at end. */
1347 -const char *ip6tc_first_chain(ip6tc_handle_t *handle);
1348 -const char *ip6tc_next_chain(ip6tc_handle_t *handle);
1349 -
1350 -/* Get first rule in the given chain: NULL for empty chain. */
1351 -const struct ip6t_entry *ip6tc_first_rule(const char *chain,
1352 -                                         ip6tc_handle_t *handle);
1353 -
1354 -/* Returns NULL when rules run out. */
1355 -const struct ip6t_entry *ip6tc_next_rule(const struct ip6t_entry *prev,
1356 -                                        ip6tc_handle_t *handle);
1357 -
1358 -/* Returns a pointer to the target name of this position. */
1359 -const char *ip6tc_get_target(const struct ip6t_entry *e,
1360 -                            ip6tc_handle_t *handle);
1361 -
1362 -/* Is this a built-in chain? */
1363 -int ip6tc_builtin(const char *chain, const ip6tc_handle_t handle);
1364 -
1365 -/* Get the policy of a given built-in chain */
1366 -const char *ip6tc_get_policy(const char *chain,
1367 -                            struct ip6t_counters *counters,
1368 -                            ip6tc_handle_t *handle);
1369 -
1370 -/* These functions return TRUE for OK or 0 and set errno. If errno ==
1371 -   0, it means there was a version error (ie. upgrade libiptc). */
1372 -/* Rule numbers start at 1 for the first rule. */
1373 -
1374 -/* Insert the entry `fw' in chain `chain' into position `rulenum'. */
1375 -int ip6tc_insert_entry(const ip6t_chainlabel chain,
1376 -                      const struct ip6t_entry *e,
1377 -                      unsigned int rulenum,
1378 -                      ip6tc_handle_t *handle);
1379 -
1380 -/* Atomically replace rule `rulenum' in `chain' with `fw'. */
1381 -int ip6tc_replace_entry(const ip6t_chainlabel chain,
1382 -                       const struct ip6t_entry *e,
1383 -                       unsigned int rulenum,
1384 -                       ip6tc_handle_t *handle);
1385 -
1386 -/* Append entry `fw' to chain `chain'. Equivalent to insert with
1387 -   rulenum = length of chain. */
1388 -int ip6tc_append_entry(const ip6t_chainlabel chain,
1389 -                      const struct ip6t_entry *e,
1390 -                      ip6tc_handle_t *handle);
1391 -
1392 -/* Delete the first rule in `chain' which matches `fw'. */
1393 -int ip6tc_delete_entry(const ip6t_chainlabel chain,
1394 -                      const struct ip6t_entry *origfw,
1395 -                      unsigned char *matchmask,
1396 -                      ip6tc_handle_t *handle);
1397 -
1398 -/* Delete the rule in position `rulenum' in `chain'. */
1399 -int ip6tc_delete_num_entry(const ip6t_chainlabel chain,
1400 -                          unsigned int rulenum,
1401 -                          ip6tc_handle_t *handle);
1402 -
1403 -/* Check the packet `fw' on chain `chain'. Returns the verdict, or
1404 -   NULL and sets errno. */
1405 -const char *ip6tc_check_packet(const ip6t_chainlabel chain,
1406 -                              struct ip6t_entry *,
1407 -                              ip6tc_handle_t *handle);
1408 -
1409 -/* Flushes the entries in the given chain (ie. empties chain). */
1410 -int ip6tc_flush_entries(const ip6t_chainlabel chain,
1411 -                       ip6tc_handle_t *handle);
1412 -
1413 -/* Zeroes the counters in a chain. */
1414 -int ip6tc_zero_entries(const ip6t_chainlabel chain,
1415 -                      ip6tc_handle_t *handle);
1416 -
1417 -/* Creates a new chain. */
1418 -int ip6tc_create_chain(const ip6t_chainlabel chain,
1419 -                      ip6tc_handle_t *handle);
1420 -
1421 -/* Deletes a chain. */
1422 -int ip6tc_delete_chain(const ip6t_chainlabel chain,
1423 -                      ip6tc_handle_t *handle);
1424 -
1425 -/* Renames a chain. */
1426 -int ip6tc_rename_chain(const ip6t_chainlabel oldname,
1427 -                      const ip6t_chainlabel newname,
1428 -                      ip6tc_handle_t *handle);
1429 -
1430 -/* Sets the policy on a built-in chain. */
1431 -int ip6tc_set_policy(const ip6t_chainlabel chain,
1432 -                    const ip6t_chainlabel policy,
1433 -                    struct ip6t_counters *counters,
1434 -                    ip6tc_handle_t *handle);
1435 -
1436 -/* Get the number of references to this chain */
1437 -int ip6tc_get_references(unsigned int *ref, const ip6t_chainlabel chain,
1438 -                        ip6tc_handle_t *handle);
1439 -
1440 -/* read packet and byte counters for a specific rule */
1441 -struct ip6t_counters *ip6tc_read_counter(const ip6t_chainlabel chain,
1442 -                                       unsigned int rulenum,
1443 -                                       ip6tc_handle_t *handle);
1444 -
1445 -/* zero packet and byte counters for a specific rule */
1446 -int ip6tc_zero_counter(const ip6t_chainlabel chain,
1447 -                      unsigned int rulenum,
1448 -                      ip6tc_handle_t *handle);
1449 -
1450 -/* set packet and byte counters for a specific rule */
1451 -int ip6tc_set_counter(const ip6t_chainlabel chain,
1452 -                     unsigned int rulenum,
1453 -                     struct ip6t_counters *counters,
1454 -                     ip6tc_handle_t *handle);
1455 -
1456 -/* Makes the actual changes. */
1457 -int ip6tc_commit(ip6tc_handle_t *handle);
1458 -
1459 -/* Get raw socket. */
1460 -int ip6tc_get_raw_socket(void);
1461 -
1462 -/* Translates errno numbers into more human-readable form than strerror. */
1463 -const char *ip6tc_strerror(int err);
1464 -
1465 -/* Return prefix length, or -1 if not contiguous */
1466 -int ipv6_prefix_length(const struct in6_addr *a);
1467 -
1468 -extern void dump_entries6(const ip6tc_handle_t);
1469 -
1470 -#endif /* _LIBIP6TC_H */
1471 diff --git a/src/owniptc/libiptc.c b/src/owniptc/libiptc.c
1472 deleted file mode 100644
1473 index 8f0b0f0..0000000
1474 --- a/src/owniptc/libiptc.c
1475 +++ /dev/null
1476 @@ -1,2716 +0,0 @@
1477 -/**
1478 - * This file was imported from the iptables sources.
1479 - * Copyright (C) 1999-2008 Netfilter Core Team
1480 - *
1481 - * This program is free software; you can redistribute it and/or modify it
1482 - * under the terms of the GNU General Public License as published by the
1483 - * Free Software Foundation; only version 2 of the License is applicable.
1484 - *
1485 - * This program is distributed in the hope that it will be useful, but
1486 - * WITHOUT ANY WARRANTY; without even the implied warranty of
1487 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1488 - * General Public License for more details.
1489 - *
1490 - * You should have received a copy of the GNU General Public License along
1491 - * with this program; if not, write to the Free Software Foundation, Inc.,
1492 - * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
1493 - */
1494 -
1495 -/* Library which manipulates firewall rules.  Version $Revision$ */
1496 -
1497 -/* Architecture of firewall rules is as follows:
1498 - *
1499 - * Chains go INPUT, FORWARD, OUTPUT then user chains.
1500 - * Each user chain starts with an ERROR node.
1501 - * Every chain ends with an unconditional jump: a RETURN for user chains,
1502 - * and a POLICY for built-ins.
1503 - */
1504 -
1505 -/* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
1506 - * COPYING for details). 
1507 - * (C) 2000-2004 by the Netfilter Core Team <coreteam@netfilter.org>
1508 - *
1509 - * 2003-Jun-20: Harald Welte <laforge@netfilter.org>:
1510 - *     - Reimplementation of chain cache to use offsets instead of entries
1511 - * 2003-Jun-23: Harald Welte <laforge@netfilter.org>:
1512 - *     - performance optimization, sponsored by Astaro AG (http://www.astaro.com/)
1513 - *       don't rebuild the chain cache after every operation, instead fix it
1514 - *       up after a ruleset change.  
1515 - * 2004-Aug-18: Harald Welte <laforge@netfilter.org>:
1516 - *     - futher performance work: total reimplementation of libiptc.
1517 - *     - libiptc now has a real internal (linked-list) represntation of the
1518 - *       ruleset and a parser/compiler from/to this internal representation
1519 - *     - again sponsored by Astaro AG (http://www.astaro.com/)
1520 - */
1521 -#include <sys/types.h>
1522 -#include <sys/socket.h>
1523 -#include "xtables.h"
1524 -
1525 -#include "linux_list.h"
1526 -
1527 -//#define IPTC_DEBUG2 1
1528 -
1529 -#ifdef IPTC_DEBUG2
1530 -#include <fcntl.h>
1531 -#define DEBUGP(x, args...)     fprintf(stderr, "%s: " x, __FUNCTION__, ## args)
1532 -#define DEBUGP_C(x, args...)   fprintf(stderr, x, ## args)
1533 -#else
1534 -#define DEBUGP(x, args...)
1535 -#define DEBUGP_C(x, args...)
1536 -#endif
1537 -
1538 -#ifdef DEBUG
1539 -#define debug(x, args...)      fprintf(stderr, x, ## args)
1540 -#else
1541 -#define debug(x, args...)
1542 -#endif
1543 -
1544 -static int sockfd = -1;
1545 -static int sockfd_use = 0;
1546 -static void *iptc_fn = NULL;
1547 -
1548 -static const char *hooknames[] = {
1549 -       [HOOK_PRE_ROUTING]      = "PREROUTING",
1550 -       [HOOK_LOCAL_IN]         = "INPUT",
1551 -       [HOOK_FORWARD]          = "FORWARD",
1552 -       [HOOK_LOCAL_OUT]        = "OUTPUT",
1553 -       [HOOK_POST_ROUTING]     = "POSTROUTING",
1554 -#ifdef HOOK_DROPPING
1555 -       [HOOK_DROPPING]         = "DROPPING"
1556 -#endif
1557 -};
1558 -
1559 -/* Convenience structures */
1560 -struct ipt_error_target
1561 -{
1562 -       STRUCT_ENTRY_TARGET t;
1563 -       char error[TABLE_MAXNAMELEN];
1564 -};
1565 -
1566 -struct chain_head;
1567 -struct rule_head;
1568 -
1569 -struct counter_map
1570 -{
1571 -       enum {
1572 -               COUNTER_MAP_NOMAP,
1573 -               COUNTER_MAP_NORMAL_MAP,
1574 -               COUNTER_MAP_ZEROED,
1575 -               COUNTER_MAP_SET
1576 -       } maptype;
1577 -       unsigned int mappos;
1578 -};
1579 -
1580 -enum iptcc_rule_type {
1581 -       IPTCC_R_STANDARD,               /* standard target (ACCEPT, ...) */
1582 -       IPTCC_R_MODULE,                 /* extension module (SNAT, ...) */
1583 -       IPTCC_R_FALLTHROUGH,            /* fallthrough rule */
1584 -       IPTCC_R_JUMP,                   /* jump to other chain */
1585 -};
1586 -
1587 -struct rule_head
1588 -{
1589 -       struct list_head list;
1590 -       struct chain_head *chain;
1591 -       struct counter_map counter_map;
1592 -
1593 -       unsigned int index;             /* index (needed for counter_map) */
1594 -       unsigned int offset;            /* offset in rule blob */
1595 -
1596 -       enum iptcc_rule_type type;
1597 -       struct chain_head *jump;        /* jump target, if IPTCC_R_JUMP */
1598 -
1599 -       unsigned int size;              /* size of entry data */
1600 -       STRUCT_ENTRY entry[0];
1601 -};
1602 -
1603 -struct chain_head
1604 -{
1605 -       struct list_head list;
1606 -       char name[TABLE_MAXNAMELEN];
1607 -       unsigned int hooknum;           /* hook number+1 if builtin */
1608 -       unsigned int references;        /* how many jumps reference us */
1609 -       int verdict;                    /* verdict if builtin */
1610 -
1611 -       STRUCT_COUNTERS counters;       /* per-chain counters */
1612 -       struct counter_map counter_map;
1613 -
1614 -       unsigned int num_rules;         /* number of rules in list */
1615 -       struct list_head rules;         /* list of rules */
1616 -
1617 -       unsigned int index;             /* index (needed for jump resolval) */
1618 -       unsigned int head_offset;       /* offset in rule blob */
1619 -       unsigned int foot_index;        /* index (needed for counter_map) */
1620 -       unsigned int foot_offset;       /* offset in rule blob */
1621 -};
1622 -
1623 -STRUCT_TC_HANDLE
1624 -{
1625 -       int changed;                     /* Have changes been made? */
1626 -
1627 -       struct list_head chains;
1628 -       
1629 -       struct chain_head *chain_iterator_cur;
1630 -       struct rule_head *rule_iterator_cur;
1631 -
1632 -       unsigned int num_chains;         /* number of user defined chains */
1633 -
1634 -       struct chain_head **chain_index;   /* array for fast chain list access*/
1635 -       unsigned int        chain_index_sz;/* size of chain index array */
1636 -
1637 -       STRUCT_GETINFO info;
1638 -       STRUCT_GET_ENTRIES *entries;
1639 -};
1640 -
1641 -/* allocate a new chain head for the cache */
1642 -static struct chain_head *iptcc_alloc_chain_head(const char *name, int hooknum)
1643 -{
1644 -       struct chain_head *c = malloc(sizeof(*c));
1645 -       if (!c)
1646 -               return NULL;
1647 -       memset(c, 0, sizeof(*c));
1648 -
1649 -       strncpy(c->name, name, TABLE_MAXNAMELEN);
1650 -       c->hooknum = hooknum;
1651 -       INIT_LIST_HEAD(&c->rules);
1652 -
1653 -       return c;
1654 -}
1655 -
1656 -/* allocate and initialize a new rule for the cache */
1657 -static struct rule_head *iptcc_alloc_rule(struct chain_head *c, unsigned int size)
1658 -{
1659 -       struct rule_head *r = malloc(sizeof(*r)+size);
1660 -       if (!r)
1661 -               return NULL;
1662 -       memset(r, 0, sizeof(*r));
1663 -
1664 -       r->chain = c;
1665 -       r->size = size;
1666 -
1667 -       return r;
1668 -}
1669 -
1670 -/* notify us that the ruleset has been modified by the user */
1671 -static inline void
1672 -set_changed(TC_HANDLE_T h)
1673 -{
1674 -       h->changed = 1;
1675 -}
1676 -
1677 -#ifdef IPTC_DEBUG
1678 -static void do_check(TC_HANDLE_T h, unsigned int line);
1679 -#define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0)
1680 -#else
1681 -#define CHECK(h)
1682 -#endif
1683 -
1684 -
1685 -/**********************************************************************
1686 - * iptc blob utility functions (iptcb_*)
1687 - **********************************************************************/
1688 -
1689 -static inline int
1690 -iptcb_get_number(const STRUCT_ENTRY *i,
1691 -          const STRUCT_ENTRY *seek,
1692 -          unsigned int *pos)
1693 -{
1694 -       if (i == seek)
1695 -               return 1;
1696 -       (*pos)++;
1697 -       return 0;
1698 -}
1699 -
1700 -static inline int
1701 -iptcb_get_entry_n(STRUCT_ENTRY *i,
1702 -           unsigned int number,
1703 -           unsigned int *pos,
1704 -           STRUCT_ENTRY **pe)
1705 -{
1706 -       if (*pos == number) {
1707 -               *pe = i;
1708 -               return 1;
1709 -       }
1710 -       (*pos)++;
1711 -       return 0;
1712 -}
1713 -
1714 -static inline STRUCT_ENTRY *
1715 -iptcb_get_entry(TC_HANDLE_T h, unsigned int offset)
1716 -{
1717 -       return (STRUCT_ENTRY *)((char *)h->entries->entrytable + offset);
1718 -}
1719 -
1720 -static unsigned int
1721 -iptcb_entry2index(const TC_HANDLE_T h, const STRUCT_ENTRY *seek)
1722 -{
1723 -       unsigned int pos = 0;
1724 -
1725 -       if (ENTRY_ITERATE(h->entries->entrytable, h->entries->size,
1726 -                         iptcb_get_number, seek, &pos) == 0) {
1727 -               fprintf(stderr, "ERROR: offset %u not an entry!\n",
1728 -                       (unsigned int)((char *)seek - (char *)h->entries->entrytable));
1729 -               abort();
1730 -       }
1731 -       return pos;
1732 -}
1733 -
1734 -static inline STRUCT_ENTRY *
1735 -iptcb_offset2entry(TC_HANDLE_T h, unsigned int offset)
1736 -{
1737 -       return (STRUCT_ENTRY *) ((void *)h->entries->entrytable+offset);
1738 -}
1739 -
1740 -
1741 -static inline unsigned long
1742 -iptcb_entry2offset(const TC_HANDLE_T h, const STRUCT_ENTRY *e)
1743 -{
1744 -       return (void *)e - (void *)h->entries->entrytable;
1745 -}
1746 -
1747 -static inline unsigned int
1748 -iptcb_offset2index(const TC_HANDLE_T h, unsigned int offset)
1749 -{
1750 -       return iptcb_entry2index(h, iptcb_offset2entry(h, offset));
1751 -}
1752 -
1753 -/* Returns 0 if not hook entry, else hooknumber + 1 */
1754 -static inline unsigned int
1755 -iptcb_ent_is_hook_entry(STRUCT_ENTRY *e, TC_HANDLE_T h)
1756 -{
1757 -       unsigned int i;
1758 -
1759 -       for (i = 0; i < NUMHOOKS; i++) {
1760 -               if ((h->info.valid_hooks & (1 << i))
1761 -                   && iptcb_get_entry(h, h->info.hook_entry[i]) == e)
1762 -                       return i+1;
1763 -       }
1764 -       return 0;
1765 -}
1766 -
1767 -
1768 -/**********************************************************************
1769 - * Chain index (cache utility) functions
1770 - **********************************************************************
1771 - * The chain index is an array with pointers into the chain list, with
1772 - * CHAIN_INDEX_BUCKET_LEN spacing.  This facilitates the ability to
1773 - * speedup chain list searching, by find a more optimal starting
1774 - * points when searching the linked list.
1775 - *
1776 - * The starting point can be found fast by using a binary search of
1777 - * the chain index. Thus, reducing the previous search complexity of
1778 - * O(n) to O(log(n/k) + k) where k is CHAIN_INDEX_BUCKET_LEN.
1779 - *
1780 - * A nice property of the chain index, is that the "bucket" list
1781 - * length is max CHAIN_INDEX_BUCKET_LEN (when just build, inserts will
1782 - * change this). Oppose to hashing, where the "bucket" list length can
1783 - * vary a lot.
1784 - */
1785 -#ifndef CHAIN_INDEX_BUCKET_LEN
1786 -#define CHAIN_INDEX_BUCKET_LEN 40
1787 -#endif
1788 -
1789 -/* Another nice property of the chain index is that inserting/creating
1790 - * chains in chain list don't change the correctness of the chain
1791 - * index, it only causes longer lists in the buckets.
1792 - *
1793 - * To mitigate the performance penalty of longer bucket lists and the
1794 - * penalty of rebuilding, the chain index is rebuild only when
1795 - * CHAIN_INDEX_INSERT_MAX chains has been added.
1796 - */
1797 -#ifndef CHAIN_INDEX_INSERT_MAX
1798 -#define CHAIN_INDEX_INSERT_MAX 355
1799 -#endif
1800 -
1801 -static inline unsigned int iptcc_is_builtin(struct chain_head *c);
1802 -
1803 -
1804 -/* Use binary search in the chain index array, to find a chain_head
1805 - * pointer closest to the place of the searched name element.
1806 - *
1807 - * Notes that, binary search (obviously) requires that the chain list
1808 - * is sorted by name.
1809 - */
1810 -static struct list_head *
1811 -iptcc_bsearch_chain_index(const char *name, unsigned int *idx, TC_HANDLE_T handle)
1812 -{
1813 -       unsigned int pos, end;
1814 -       int res;
1815 -
1816 -       struct list_head *list_pos;
1817 -       list_pos=&handle->chains;
1818 -
1819 -       /* Check for empty array, e.g. no user defined chains */
1820 -       if (handle->chain_index_sz == 0) {
1821 -               debug("WARNING: handle->chain_index_sz == 0\n");
1822 -               return list_pos;
1823 -       }
1824 -
1825 -       /* Init */
1826 -       end = handle->chain_index_sz;
1827 -       pos = end / 2;
1828 -
1829 -       debug("bsearch Find chain:%s (pos:%d end:%d)\n", name, pos, end);
1830 -
1831 -       /* Loop */
1832 - loop:
1833 -       if (!handle->chain_index[pos]) {
1834 -               fprintf(stderr, "ERROR: NULL pointer chain_index[%d]\n", pos);
1835 -               return &handle->chains; /* Be safe, return orig start pos */
1836 -       }
1837 -
1838 -       res = strcmp(name, handle->chain_index[pos]->name);
1839 -       list_pos = &handle->chain_index[pos]->list;
1840 -       *idx = pos;
1841 -
1842 -       debug("bsearch Index[%d] name:%s res:%d ",
1843 -             pos, handle->chain_index[pos]->name, res);
1844 -
1845 -       if (res == 0) { /* Found element, by direct hit */
1846 -               debug("[found] Direct hit pos:%d end:%d\n", pos, end);
1847 -               return list_pos;
1848 -       } else if (res < 0) { /* Too far, jump back */
1849 -               end = pos;
1850 -               pos = pos / 2;
1851 -
1852 -               /* Exit case: First element of array */
1853 -               if (end == 0) {
1854 -                       debug("[found] Reached first array elem (end%d)\n",end);
1855 -                       return list_pos;
1856 -               }
1857 -               debug("jump back to pos:%d (end:%d)\n", pos, end);
1858 -               goto loop;
1859 -       } else if (res > 0 ){ /* Not far enough, jump forward */
1860 -
1861 -               /* Exit case: Last element of array */
1862 -               if (pos == handle->chain_index_sz-1) {
1863 -                       debug("[found] Last array elem (end:%d)\n", end);
1864 -                       return list_pos;
1865 -               }
1866 -
1867 -               /* Exit case: Next index less, thus elem in this list section */
1868 -               res = strcmp(name, handle->chain_index[pos+1]->name);
1869 -               if (res < 0) {
1870 -                       debug("[found] closest list (end:%d)\n", end);
1871 -                       return list_pos;
1872 -               }
1873 -
1874 -               pos = (pos+end)/2;
1875 -               debug("jump forward to pos:%d (end:%d)\n", pos, end);
1876 -               goto loop;
1877 -       }
1878 -
1879 -       return list_pos;
1880 -}
1881 -
1882 -#ifdef DEBUG
1883 -/* Trivial linear search of chain index. Function used for verifying
1884 -   the output of bsearch function */
1885 -static struct list_head *
1886 -iptcc_linearly_search_chain_index(const char *name, TC_HANDLE_T handle)
1887 -{
1888 -       unsigned int i=0;
1889 -       int res=0;
1890 -
1891 -       struct list_head *list_pos;
1892 -       list_pos = &handle->chains;
1893 -
1894 -       if (handle->chain_index_sz)
1895 -               list_pos = &handle->chain_index[0]->list;
1896 -
1897 -       /* Linearly walk of chain index array */
1898 -
1899 -       for (i=0; i < handle->chain_index_sz; i++) {
1900 -               if (handle->chain_index[i]) {
1901 -                       res = strcmp(handle->chain_index[i]->name, name);
1902 -                       if (res > 0)
1903 -                               break; // One step too far
1904 -                       list_pos = &handle->chain_index[i]->list;
1905 -                       if (res == 0)
1906 -                               break; // Direct hit
1907 -               }
1908 -       }
1909 -
1910 -       return list_pos;
1911 -}
1912 -#endif
1913 -
1914 -static int iptcc_chain_index_alloc(TC_HANDLE_T h)
1915 -{
1916 -       unsigned int list_length = CHAIN_INDEX_BUCKET_LEN;
1917 -       unsigned int array_elems;
1918 -       unsigned int array_mem;
1919 -
1920 -       /* Allocate memory for the chain index array */
1921 -       array_elems = (h->num_chains / list_length) +
1922 -                      (h->num_chains % list_length ? 1 : 0);
1923 -       array_mem   = sizeof(h->chain_index) * array_elems;
1924 -
1925 -       debug("Alloc Chain index, elems:%d mem:%d bytes\n",
1926 -             array_elems, array_mem);
1927 -
1928 -       h->chain_index = malloc(array_mem);
1929 -       if (!h->chain_index) {
1930 -               h->chain_index_sz = 0;
1931 -               return -ENOMEM;
1932 -       }
1933 -       memset(h->chain_index, 0, array_mem);
1934 -       h->chain_index_sz = array_elems;
1935 -
1936 -       return 1;
1937 -}
1938 -
1939 -static void iptcc_chain_index_free(TC_HANDLE_T h)
1940 -{
1941 -       h->chain_index_sz = 0;
1942 -       free(h->chain_index);
1943 -}
1944 -
1945 -
1946 -#ifdef DEBUG
1947 -static void iptcc_chain_index_dump(TC_HANDLE_T h)
1948 -{
1949 -       unsigned int i = 0;
1950 -
1951 -       /* Dump: contents of chain index array */
1952 -       for (i=0; i < h->chain_index_sz; i++) {
1953 -               if (h->chain_index[i]) {
1954 -                       fprintf(stderr, "Chain index[%d].name: %s\n",
1955 -                               i, h->chain_index[i]->name);
1956 -               }
1957 -       }
1958 -}
1959 -#endif
1960 -
1961 -/* Build the chain index */
1962 -static int iptcc_chain_index_build(TC_HANDLE_T h)
1963 -{
1964 -       unsigned int list_length = CHAIN_INDEX_BUCKET_LEN;
1965 -       unsigned int chains = 0;
1966 -       unsigned int cindex = 0;
1967 -       struct chain_head *c;
1968 -
1969 -       /* Build up the chain index array here */
1970 -       debug("Building chain index\n");
1971 -
1972 -       debug("Number of user defined chains:%d bucket_sz:%d array_sz:%d\n",
1973 -               h->num_chains, list_length, h->chain_index_sz);
1974 -
1975 -       if (h->chain_index_sz == 0)
1976 -               return 0;
1977 -
1978 -       list_for_each_entry(c, &h->chains, list) {
1979 -
1980 -               /* Issue: The index array needs to start after the
1981 -                * builtin chains, as they are not sorted */
1982 -               if (!iptcc_is_builtin(c)) {
1983 -                       cindex=chains / list_length;
1984 -
1985 -                       /* Safe guard, break out on array limit, this
1986 -                        * is useful if chains are added and array is
1987 -                        * rebuild, without realloc of memory. */
1988 -                       if (cindex >= h->chain_index_sz)
1989 -                               break;
1990 -
1991 -                       if ((chains % list_length)== 0) {
1992 -                               debug("\nIndex[%d] Chains:", cindex);
1993 -                               h->chain_index[cindex] = c;
1994 -                       }
1995 -                       chains++;
1996 -               }
1997 -               debug("%s, ", c->name);
1998 -       }
1999 -       debug("\n");
2000 -
2001 -       return 1;
2002 -}
2003 -
2004 -static int iptcc_chain_index_rebuild(TC_HANDLE_T h)
2005 -{
2006 -       debug("REBUILD chain index array\n");
2007 -       iptcc_chain_index_free(h);
2008 -       if ((iptcc_chain_index_alloc(h)) < 0)
2009 -               return -ENOMEM;
2010 -       iptcc_chain_index_build(h);
2011 -       return 1;
2012 -}
2013 -
2014 -/* Delete chain (pointer) from index array.  Removing an element from
2015 - * the chain list only affects the chain index array, if the chain
2016 - * index points-to/uses that list pointer.
2017 - *
2018 - * There are different strategies, the simple and safe is to rebuild
2019 - * the chain index every time.  The more advanced is to update the
2020 - * array index to point to the next element, but that requires some
2021 - * house keeping and boundry checks.  The advanced is implemented, as
2022 - * the simple approach behaves badly when all chains are deleted
2023 - * because list_for_each processing will always hit the first chain
2024 - * index, thus causing a rebuild for every chain.
2025 - */
2026 -static int iptcc_chain_index_delete_chain(struct chain_head *c, TC_HANDLE_T h)
2027 -{
2028 -       struct list_head *index_ptr, *index_ptr2, *next;
2029 -       struct chain_head *c2;
2030 -       unsigned int idx, idx2;
2031 -
2032 -       index_ptr = iptcc_bsearch_chain_index(c->name, &idx, h);
2033 -
2034 -       debug("Del chain[%s] c->list:%p index_ptr:%p\n",
2035 -             c->name, &c->list, index_ptr);
2036 -
2037 -       /* Save the next pointer */
2038 -       next = c->list.next;
2039 -       list_del(&c->list);
2040 -
2041 -       if (index_ptr == &c->list) { /* Chain used as index ptr */
2042 -
2043 -               /* See if its possible to avoid a rebuild, by shifting
2044 -                * to next pointer.  Its possible if the next pointer
2045 -                * is located in the same index bucket.
2046 -                */
2047 -               c2         = list_entry(next, struct chain_head, list);
2048 -               index_ptr2 = iptcc_bsearch_chain_index(c2->name, &idx2, h);
2049 -               if (idx != idx2) {
2050 -                       /* Rebuild needed */
2051 -                       return iptcc_chain_index_rebuild(h);
2052 -               } else {
2053 -                       /* Avoiding rebuild */
2054 -                       debug("Update cindex[%d] with next ptr name:[%s]\n",
2055 -                             idx, c2->name);
2056 -                       h->chain_index[idx]=c2;
2057 -                       return 0;
2058 -               }
2059 -       }
2060 -       return 0;
2061 -}
2062 -
2063 -
2064 -/**********************************************************************
2065 - * iptc cache utility functions (iptcc_*)
2066 - **********************************************************************/
2067 -
2068 -/* Is the given chain builtin (1) or user-defined (0) */
2069 -static inline unsigned int iptcc_is_builtin(struct chain_head *c)
2070 -{
2071 -       return (c->hooknum ? 1 : 0);
2072 -}
2073 -
2074 -/* Get a specific rule within a chain */
2075 -static struct rule_head *iptcc_get_rule_num(struct chain_head *c,
2076 -                                           unsigned int rulenum)
2077 -{
2078 -       struct rule_head *r;
2079 -       unsigned int num = 0;
2080 -
2081 -       list_for_each_entry(r, &c->rules, list) {
2082 -               num++;
2083 -               if (num == rulenum)
2084 -                       return r;
2085 -       }
2086 -       return NULL;
2087 -}
2088 -
2089 -/* Get a specific rule within a chain backwards */
2090 -static struct rule_head *iptcc_get_rule_num_reverse(struct chain_head *c,
2091 -                                           unsigned int rulenum)
2092 -{
2093 -       struct rule_head *r;
2094 -       unsigned int num = 0;
2095 -
2096 -       list_for_each_entry_reverse(r, &c->rules, list) {
2097 -               num++;
2098 -               if (num == rulenum)
2099 -                       return r;
2100 -       }
2101 -       return NULL;
2102 -}
2103 -
2104 -/* Returns chain head if found, otherwise NULL. */
2105 -static struct chain_head *
2106 -iptcc_find_chain_by_offset(TC_HANDLE_T handle, unsigned int offset)
2107 -{
2108 -       struct list_head *pos;
2109 -
2110 -       if (list_empty(&handle->chains))
2111 -               return NULL;
2112 -
2113 -       list_for_each(pos, &handle->chains) {
2114 -               struct chain_head *c = list_entry(pos, struct chain_head, list);
2115 -               if (offset >= c->head_offset && offset <= c->foot_offset)
2116 -                       return c;
2117 -       }
2118 -
2119 -       return NULL;
2120 -}
2121 -
2122 -/* Returns chain head if found, otherwise NULL. */
2123 -static struct chain_head *
2124 -iptcc_find_label(const char *name, TC_HANDLE_T handle)
2125 -{
2126 -       struct list_head *pos;
2127 -       struct list_head *list_start_pos;
2128 -       unsigned int i=0;
2129 -       int res;
2130 -
2131 -       if (list_empty(&handle->chains))
2132 -               return NULL;
2133 -
2134 -       /* First look at builtin chains */
2135 -       list_for_each(pos, &handle->chains) {
2136 -               struct chain_head *c = list_entry(pos, struct chain_head, list);
2137 -               if (!iptcc_is_builtin(c))
2138 -                       break;
2139 -               if (!strcmp(c->name, name))
2140 -                       return c;
2141 -       }
2142 -
2143 -       /* Find a smart place to start the search via chain index */
2144 -       //list_start_pos = iptcc_linearly_search_chain_index(name, handle);
2145 -       list_start_pos = iptcc_bsearch_chain_index(name, &i, handle);
2146 -
2147 -       /* Handel if bsearch bails out early */
2148 -       if (list_start_pos == &handle->chains) {
2149 -               list_start_pos = pos;
2150 -       }
2151 -#ifdef DEBUG
2152 -       else {
2153 -               /* Verify result of bsearch against linearly index search */
2154 -               struct list_head *test_pos;
2155 -               struct chain_head *test_c, *tmp_c;
2156 -               test_pos = iptcc_linearly_search_chain_index(name, handle);
2157 -               if (list_start_pos != test_pos) {
2158 -                       debug("BUG in chain_index search\n");
2159 -                       test_c=list_entry(test_pos,      struct chain_head,list);
2160 -                       tmp_c =list_entry(list_start_pos,struct chain_head,list);
2161 -                       debug("Verify search found:\n");
2162 -                       debug(" Chain:%s\n", test_c->name);
2163 -                       debug("BSearch found:\n");
2164 -                       debug(" Chain:%s\n", tmp_c->name);
2165 -                       exit(42);
2166 -               }
2167 -       }
2168 -#endif
2169 -
2170 -       /* Initial/special case, no user defined chains */
2171 -       if (handle->num_chains == 0)
2172 -               return NULL;
2173 -
2174 -       /* Start searching through the chain list */
2175 -       list_for_each(pos, list_start_pos->prev) {
2176 -               struct chain_head *c = list_entry(pos, struct chain_head, list);
2177 -               res = strcmp(c->name, name);
2178 -               debug("List search name:%s == %s res:%d\n", name, c->name, res);
2179 -               if (res==0)
2180 -                       return c;
2181 -
2182 -               /* We can stop earlier as we know list is sorted */
2183 -               if (res>0 && !iptcc_is_builtin(c)) { /* Walked too far*/
2184 -                       debug(" Not in list, walked too far, sorted list\n");
2185 -                       return NULL;
2186 -               }
2187 -
2188 -               /* Stop on wrap around, if list head is reached */
2189 -               if (pos == &handle->chains) {
2190 -                       debug("Stop, list head reached\n");
2191 -                       return NULL;
2192 -               }
2193 -       }
2194 -
2195 -       debug("List search NOT found name:%s\n", name);
2196 -       return NULL;
2197 -}
2198 -
2199 -/* called when rule is to be removed from cache */
2200 -static void iptcc_delete_rule(struct rule_head *r)
2201 -{
2202 -       DEBUGP("deleting rule %p (offset %u)\n", r, r->offset);
2203 -       /* clean up reference count of called chain */
2204 -       if (r->type == IPTCC_R_JUMP
2205 -           && r->jump)
2206 -               r->jump->references--;
2207 -
2208 -       list_del(&r->list);
2209 -       free(r);
2210 -}
2211 -
2212 -
2213 -/**********************************************************************
2214 - * RULESET PARSER (blob -> cache)
2215 - **********************************************************************/
2216 -
2217 -/* Delete policy rule of previous chain, since cache doesn't contain
2218 - * chain policy rules.
2219 - * WARNING: This function has ugly design and relies on a lot of context, only
2220 - * to be called from specific places within the parser */
2221 -static int __iptcc_p_del_policy(TC_HANDLE_T h, unsigned int num)
2222 -{
2223 -       const unsigned char *data;
2224 -
2225 -       if (h->chain_iterator_cur) {
2226 -               /* policy rule is last rule */
2227 -               struct rule_head *pr = (struct rule_head *)
2228 -                       h->chain_iterator_cur->rules.prev;
2229 -
2230 -               /* save verdict */
2231 -               data = GET_TARGET(pr->entry)->data;
2232 -               h->chain_iterator_cur->verdict = *(const int *)data;
2233 -
2234 -               /* save counter and counter_map information */
2235 -               h->chain_iterator_cur->counter_map.maptype = 
2236 -                                               COUNTER_MAP_NORMAL_MAP;
2237 -               h->chain_iterator_cur->counter_map.mappos = num-1;
2238 -               memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters, 
2239 -                       sizeof(h->chain_iterator_cur->counters));
2240 -
2241 -               /* foot_offset points to verdict rule */
2242 -               h->chain_iterator_cur->foot_index = num;
2243 -               h->chain_iterator_cur->foot_offset = pr->offset;
2244 -
2245 -               /* delete rule from cache */
2246 -               iptcc_delete_rule(pr);
2247 -               h->chain_iterator_cur->num_rules--;
2248 -
2249 -               return 1;
2250 -       }
2251 -       return 0;
2252 -}
2253 -
2254 -/* alphabetically insert a chain into the list */
2255 -static inline void iptc_insert_chain(TC_HANDLE_T h, struct chain_head *c)
2256 -{
2257 -       struct chain_head *tmp;
2258 -       struct list_head  *list_start_pos;
2259 -       unsigned int i=1;
2260 -
2261 -       /* Find a smart place to start the insert search */
2262 -       list_start_pos = iptcc_bsearch_chain_index(c->name, &i, h);
2263 -
2264 -       /* Handle the case, where chain.name is smaller than index[0] */
2265 -       if (i==0 && strcmp(c->name, h->chain_index[0]->name) <= 0) {
2266 -               h->chain_index[0] = c; /* Update chain index head */
2267 -               list_start_pos = h->chains.next;
2268 -               debug("Update chain_index[0] with %s\n", c->name);
2269 -       }
2270 -
2271 -       /* Handel if bsearch bails out early */
2272 -       if (list_start_pos == &h->chains) {
2273 -               list_start_pos = h->chains.next;
2274 -       }
2275 -
2276 -       /* sort only user defined chains */
2277 -       if (!c->hooknum) {
2278 -               list_for_each_entry(tmp, list_start_pos->prev, list) {
2279 -                       if (!tmp->hooknum && strcmp(c->name, tmp->name) <= 0) {
2280 -                               list_add(&c->list, tmp->list.prev);
2281 -                               return;
2282 -                       }
2283 -
2284 -                       /* Stop if list head is reached */
2285 -                       if (&tmp->list == &h->chains) {
2286 -                               debug("Insert, list head reached add to tail\n");
2287 -                               break;
2288 -                       }
2289 -               }
2290 -       }
2291 -
2292 -       /* survived till end of list: add at tail */
2293 -       list_add_tail(&c->list, &h->chains);
2294 -}
2295 -
2296 -/* Another ugly helper function split out of cache_add_entry to make it less
2297 - * spaghetti code */
2298 -static void __iptcc_p_add_chain(TC_HANDLE_T h, struct chain_head *c,
2299 -                               unsigned int offset, unsigned int *num)
2300 -{
2301 -       struct list_head  *tail = h->chains.prev;
2302 -       struct chain_head *ctail;
2303 -
2304 -       __iptcc_p_del_policy(h, *num);
2305 -
2306 -       c->head_offset = offset;
2307 -       c->index = *num;
2308 -
2309 -       /* Chains from kernel are already sorted, as they are inserted
2310 -        * sorted. But there exists an issue when shifting to 1.4.0
2311 -        * from an older version, as old versions allow last created
2312 -        * chain to be unsorted.
2313 -        */
2314 -       if (iptcc_is_builtin(c)) /* Only user defined chains are sorted*/
2315 -               list_add_tail(&c->list, &h->chains);
2316 -       else {
2317 -               ctail = list_entry(tail, struct chain_head, list);
2318 -               if (strcmp(c->name, ctail->name) > 0)
2319 -                       list_add_tail(&c->list, &h->chains);/* Already sorted*/
2320 -               else
2321 -                       iptc_insert_chain(h, c);/* Was not sorted */
2322 -       }
2323 -
2324 -       h->chain_iterator_cur = c;
2325 -}
2326 -
2327 -/* main parser function: add an entry from the blob to the cache */
2328 -static int cache_add_entry(STRUCT_ENTRY *e, 
2329 -                          TC_HANDLE_T h, 
2330 -                          STRUCT_ENTRY **prev,
2331 -                          unsigned int *num)
2332 -{
2333 -       unsigned int builtin;
2334 -       unsigned int offset = (char *)e - (char *)h->entries->entrytable;
2335 -
2336 -       DEBUGP("entering...");
2337 -
2338 -       /* Last entry ("policy rule"). End it.*/
2339 -       if (iptcb_entry2offset(h,e) + e->next_offset == h->entries->size) {
2340 -               /* This is the ERROR node at the end of the chain */
2341 -               DEBUGP_C("%u:%u: end of table:\n", *num, offset);
2342 -
2343 -               __iptcc_p_del_policy(h, *num);
2344 -
2345 -               h->chain_iterator_cur = NULL;
2346 -               goto out_inc;
2347 -       }
2348 -
2349 -       /* We know this is the start of a new chain if it's an ERROR
2350 -        * target, or a hook entry point */
2351 -
2352 -       if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) {
2353 -               struct chain_head *c = 
2354 -                       iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0);
2355 -               DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset, 
2356 -                       (char *)c->name, c);
2357 -               if (!c) {
2358 -                       errno = -ENOMEM;
2359 -                       return -1;
2360 -               }
2361 -               h->num_chains++; /* New user defined chain */
2362 -
2363 -               __iptcc_p_add_chain(h, c, offset, num);
2364 -
2365 -       } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) {
2366 -               struct chain_head *c =
2367 -                       iptcc_alloc_chain_head((char *)hooknames[builtin-1], 
2368 -                                               builtin);
2369 -               DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n", 
2370 -                       *num, offset, c, &c->rules);
2371 -               if (!c) {
2372 -                       errno = -ENOMEM;
2373 -                       return -1;
2374 -               }
2375 -
2376 -               c->hooknum = builtin;
2377 -
2378 -               __iptcc_p_add_chain(h, c, offset, num);
2379 -
2380 -               /* FIXME: this is ugly. */
2381 -               goto new_rule;
2382 -       } else {
2383 -               /* has to be normal rule */
2384 -               struct rule_head *r;
2385 -new_rule:
2386 -
2387 -               if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, 
2388 -                                          e->next_offset))) {
2389 -                       errno = ENOMEM;
2390 -                       return -1;
2391 -               }
2392 -               DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r);
2393 -
2394 -               r->index = *num;
2395 -               r->offset = offset;
2396 -               memcpy(r->entry, e, e->next_offset);
2397 -               r->counter_map.maptype = COUNTER_MAP_NORMAL_MAP;
2398 -               r->counter_map.mappos = r->index;
2399 -
2400 -               /* handling of jumps, etc. */
2401 -               if (!strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET)) {
2402 -                       STRUCT_STANDARD_TARGET *t;
2403 -
2404 -                       t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
2405 -                       if (t->target.u.target_size
2406 -                           != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) {
2407 -                               errno = EINVAL;
2408 -                               return -1;
2409 -                       }
2410 -
2411 -                       if (t->verdict < 0) {
2412 -                               DEBUGP_C("standard, verdict=%d\n", t->verdict);
2413 -                               r->type = IPTCC_R_STANDARD;
2414 -                       } else if (t->verdict == r->offset+e->next_offset) {
2415 -                               DEBUGP_C("fallthrough\n");
2416 -                               r->type = IPTCC_R_FALLTHROUGH;
2417 -                       } else {
2418 -                               DEBUGP_C("jump, target=%u\n", t->verdict);
2419 -                               r->type = IPTCC_R_JUMP;
2420 -                               /* Jump target fixup has to be deferred
2421 -                                * until second pass, since we migh not
2422 -                                * yet have parsed the target */
2423 -                       }
2424 -               } else {
2425 -                       DEBUGP_C("module, target=%s\n", GET_TARGET(e)->u.user.name);
2426 -                       r->type = IPTCC_R_MODULE;
2427 -               }
2428 -
2429 -               list_add_tail(&r->list, &h->chain_iterator_cur->rules);
2430 -               h->chain_iterator_cur->num_rules++;
2431 -       }
2432 -out_inc:
2433 -       (*num)++;
2434 -       return 0;
2435 -}
2436 -
2437 -
2438 -/* parse an iptables blob into it's pieces */
2439 -static int parse_table(TC_HANDLE_T h)
2440 -{
2441 -       STRUCT_ENTRY *prev;
2442 -       unsigned int num = 0;
2443 -       struct chain_head *c;
2444 -
2445 -       /* First pass: over ruleset blob */
2446 -       ENTRY_ITERATE(h->entries->entrytable, h->entries->size,
2447 -                       cache_add_entry, h, &prev, &num);
2448 -
2449 -       /* Build the chain index, used for chain list search speedup */
2450 -       if ((iptcc_chain_index_alloc(h)) < 0)
2451 -               return -ENOMEM;
2452 -       iptcc_chain_index_build(h);
2453 -
2454 -       /* Second pass: fixup parsed data from first pass */
2455 -       list_for_each_entry(c, &h->chains, list) {
2456 -               struct rule_head *r;
2457 -               list_for_each_entry(r, &c->rules, list) {
2458 -                       struct chain_head *lc;
2459 -                       STRUCT_STANDARD_TARGET *t;
2460 -
2461 -                       if (r->type != IPTCC_R_JUMP)
2462 -                               continue;
2463 -
2464 -                       t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
2465 -                       lc = iptcc_find_chain_by_offset(h, t->verdict);
2466 -                       if (!lc)
2467 -                               return -1;
2468 -                       r->jump = lc;
2469 -                       lc->references++;
2470 -               }
2471 -       }
2472 -
2473 -       /* FIXME: sort chains */
2474 -
2475 -       return 1;
2476 -}
2477 -
2478 -
2479 -/**********************************************************************
2480 - * RULESET COMPILATION (cache -> blob)
2481 - **********************************************************************/
2482 -
2483 -/* Convenience structures */
2484 -struct iptcb_chain_start{
2485 -       STRUCT_ENTRY e;
2486 -       struct ipt_error_target name;
2487 -};
2488 -#define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) +                 \
2489 -                                ALIGN(sizeof(struct ipt_error_target)))
2490 -
2491 -struct iptcb_chain_foot {
2492 -       STRUCT_ENTRY e;
2493 -       STRUCT_STANDARD_TARGET target;
2494 -};
2495 -#define IPTCB_CHAIN_FOOT_SIZE  (sizeof(STRUCT_ENTRY) +                 \
2496 -                                ALIGN(sizeof(STRUCT_STANDARD_TARGET)))
2497 -
2498 -struct iptcb_chain_error {
2499 -       STRUCT_ENTRY entry;
2500 -       struct ipt_error_target target;
2501 -};
2502 -#define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) +                 \
2503 -                                ALIGN(sizeof(struct ipt_error_target)))
2504 -
2505 -
2506 -
2507 -/* compile rule from cache into blob */
2508 -static inline int iptcc_compile_rule (TC_HANDLE_T h, STRUCT_REPLACE *repl, struct rule_head *r)
2509 -{
2510 -       /* handle jumps */
2511 -       if (r->type == IPTCC_R_JUMP) {
2512 -               STRUCT_STANDARD_TARGET *t;
2513 -               t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
2514 -               /* memset for memcmp convenience on delete/replace */
2515 -               memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
2516 -               strcpy(t->target.u.user.name, STANDARD_TARGET);
2517 -               /* Jumps can only happen to builtin chains, so we
2518 -                * can safely assume that they always have a header */
2519 -               t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE;
2520 -       } else if (r->type == IPTCC_R_FALLTHROUGH) {
2521 -               STRUCT_STANDARD_TARGET *t;
2522 -               t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
2523 -               t->verdict = r->offset + r->size;
2524 -       }
2525 -       
2526 -       /* copy entry from cache to blob */
2527 -       memcpy((char *)repl->entries+r->offset, r->entry, r->size);
2528 -
2529 -       return 1;
2530 -}
2531 -
2532 -/* compile chain from cache into blob */
2533 -static int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain_head *c)
2534 -{
2535 -       int ret;
2536 -       struct rule_head *r;
2537 -       struct iptcb_chain_start *head;
2538 -       struct iptcb_chain_foot *foot;
2539 -
2540 -       /* only user-defined chains have heaer */
2541 -       if (!iptcc_is_builtin(c)) {
2542 -               /* put chain header in place */
2543 -               head = (void *)repl->entries + c->head_offset;
2544 -               head->e.target_offset = sizeof(STRUCT_ENTRY);
2545 -               head->e.next_offset = IPTCB_CHAIN_START_SIZE;
2546 -               strcpy(head->name.t.u.user.name, ERROR_TARGET);
2547 -               head->name.t.u.target_size = 
2548 -                               ALIGN(sizeof(struct ipt_error_target));
2549 -               strcpy(head->name.error, c->name);
2550 -       } else {
2551 -               repl->hook_entry[c->hooknum-1] = c->head_offset;        
2552 -               repl->underflow[c->hooknum-1] = c->foot_offset;
2553 -       }
2554 -
2555 -       /* iterate over rules */
2556 -       list_for_each_entry(r, &c->rules, list) {
2557 -               ret = iptcc_compile_rule(h, repl, r);
2558 -               if (ret < 0)
2559 -                       return ret;
2560 -       }
2561 -
2562 -       /* put chain footer in place */
2563 -       foot = (void *)repl->entries + c->foot_offset;
2564 -       foot->e.target_offset = sizeof(STRUCT_ENTRY);
2565 -       foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE;
2566 -       strcpy(foot->target.target.u.user.name, STANDARD_TARGET);
2567 -       foot->target.target.u.target_size =
2568 -                               ALIGN(sizeof(STRUCT_STANDARD_TARGET));
2569 -       /* builtin targets have verdict, others return */
2570 -       if (iptcc_is_builtin(c))
2571 -               foot->target.verdict = c->verdict;
2572 -       else
2573 -               foot->target.verdict = RETURN;
2574 -       /* set policy-counters */
2575 -       memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS));
2576 -
2577 -       return 0;
2578 -}
2579 -
2580 -/* calculate offset and number for every rule in the cache */
2581 -static int iptcc_compile_chain_offsets(TC_HANDLE_T h, struct chain_head *c,
2582 -                                      unsigned int *offset, unsigned int *num)
2583 -{
2584 -       struct rule_head *r;
2585 -
2586 -       c->head_offset = *offset;
2587 -       DEBUGP("%s: chain_head %u, offset=%u\n", c->name, *num, *offset);
2588 -
2589 -       if (!iptcc_is_builtin(c))  {
2590 -               /* Chain has header */
2591 -               *offset += sizeof(STRUCT_ENTRY) 
2592 -                            + ALIGN(sizeof(struct ipt_error_target));
2593 -               (*num)++;
2594 -       }
2595 -
2596 -       list_for_each_entry(r, &c->rules, list) {
2597 -               DEBUGP("rule %u, offset=%u, index=%u\n", *num, *offset, *num);
2598 -               r->offset = *offset;
2599 -               r->index = *num;
2600 -               *offset += r->size;
2601 -               (*num)++;
2602 -       }
2603 -
2604 -       DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num, 
2605 -               *offset, *num);
2606 -       c->foot_offset = *offset;
2607 -       c->foot_index = *num;
2608 -       *offset += sizeof(STRUCT_ENTRY)
2609 -                  + ALIGN(sizeof(STRUCT_STANDARD_TARGET));
2610 -       (*num)++;
2611 -
2612 -       return 1;
2613 -}
2614 -
2615 -/* put the pieces back together again */
2616 -static int iptcc_compile_table_prep(TC_HANDLE_T h, unsigned int *size)
2617 -{
2618 -       struct chain_head *c;
2619 -       unsigned int offset = 0, num = 0;
2620 -       int ret = 0;
2621 -
2622 -       /* First pass: calculate offset for every rule */
2623 -       list_for_each_entry(c, &h->chains, list) {
2624 -               ret = iptcc_compile_chain_offsets(h, c, &offset, &num);
2625 -               if (ret < 0)
2626 -                       return ret;
2627 -       }
2628 -
2629 -       /* Append one error rule at end of chain */
2630 -       num++;
2631 -       offset += sizeof(STRUCT_ENTRY)
2632 -                 + ALIGN(sizeof(struct ipt_error_target));
2633 -
2634 -       /* ruleset size is now in offset */
2635 -       *size = offset;
2636 -       return num;
2637 -}
2638 -
2639 -static int iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE *repl)
2640 -{
2641 -       struct chain_head *c;
2642 -       struct iptcb_chain_error *error;
2643 -
2644 -       /* Second pass: copy from cache to offsets, fill in jumps */
2645 -       list_for_each_entry(c, &h->chains, list) {
2646 -               int ret = iptcc_compile_chain(h, repl, c);
2647 -               if (ret < 0)
2648 -                       return ret;
2649 -       }
2650 -
2651 -       /* Append error rule at end of chain */
2652 -       error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE;
2653 -       error->entry.target_offset = sizeof(STRUCT_ENTRY);
2654 -       error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE;
2655 -       error->target.t.u.user.target_size = 
2656 -               ALIGN(sizeof(struct ipt_error_target));
2657 -       strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET);
2658 -       strcpy((char *)&error->target.error, "ERROR");
2659 -
2660 -       return 1;
2661 -}
2662 -
2663 -/**********************************************************************
2664 - * EXTERNAL API (operates on cache only)
2665 - **********************************************************************/
2666 -
2667 -/* Allocate handle of given size */
2668 -static TC_HANDLE_T
2669 -alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
2670 -{
2671 -       size_t len;
2672 -       TC_HANDLE_T h;
2673 -
2674 -       len = sizeof(STRUCT_TC_HANDLE) + size;
2675 -
2676 -       h = malloc(sizeof(STRUCT_TC_HANDLE));
2677 -       if (!h) {
2678 -               errno = ENOMEM;
2679 -               return NULL;
2680 -       }
2681 -       memset(h, 0, sizeof(*h));
2682 -       INIT_LIST_HEAD(&h->chains);
2683 -       strcpy(h->info.name, tablename);
2684 -
2685 -       h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size);
2686 -       if (!h->entries)
2687 -               goto out_free_handle;
2688 -
2689 -       strcpy(h->entries->name, tablename);
2690 -       h->entries->size = size;
2691 -
2692 -       return h;
2693 -
2694 -out_free_handle:
2695 -       free(h);
2696 -
2697 -       return NULL;
2698 -}
2699 -
2700 -
2701 -TC_HANDLE_T
2702 -TC_INIT(const char *tablename)
2703 -{
2704 -       TC_HANDLE_T h;
2705 -       STRUCT_GETINFO info;
2706 -       unsigned int tmp;
2707 -       socklen_t s;
2708 -
2709 -       iptc_fn = TC_INIT;
2710 -
2711 -       if (strlen(tablename) >= TABLE_MAXNAMELEN) {
2712 -               errno = EINVAL;
2713 -               return NULL;
2714 -       }
2715 -       
2716 -       if (sockfd_use == 0) {
2717 -               sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);
2718 -               if (sockfd < 0)
2719 -                       return NULL;
2720 -       }
2721 -       sockfd_use++;
2722 -retry:
2723 -       s = sizeof(info);
2724 -
2725 -       strcpy(info.name, tablename);
2726 -       if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) {
2727 -               if (--sockfd_use == 0) {
2728 -                       close(sockfd);
2729 -                       sockfd = -1;
2730 -               }
2731 -               return NULL;
2732 -       }
2733 -
2734 -       DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n",
2735 -               info.valid_hooks, info.num_entries, info.size);
2736 -
2737 -       if ((h = alloc_handle(info.name, info.size, info.num_entries))
2738 -           == NULL) {
2739 -               if (--sockfd_use == 0) {
2740 -                       close(sockfd);
2741 -                       sockfd = -1;
2742 -               }
2743 -               return NULL;
2744 -       }
2745 -
2746 -       /* Initialize current state */
2747 -       h->info = info;
2748 -
2749 -       h->entries->size = h->info.size;
2750 -
2751 -       tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size;
2752 -
2753 -       if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries,
2754 -                      &tmp) < 0)
2755 -               goto error;
2756 -
2757 -#ifdef IPTC_DEBUG2
2758 -       {
2759 -               int fd = open("/tmp/libiptc-so_get_entries.blob", 
2760 -                               O_CREAT|O_WRONLY);
2761 -               if (fd >= 0) {
2762 -                       write(fd, h->entries, tmp);
2763 -                       close(fd);
2764 -               }
2765 -       }
2766 -#endif
2767 -
2768 -       if (parse_table(h) < 0)
2769 -               goto error;
2770 -
2771 -       CHECK(h);
2772 -       return h;
2773 -error:
2774 -       TC_FREE(&h);
2775 -       /* A different process changed the ruleset size, retry */
2776 -       if (errno == EAGAIN)
2777 -               goto retry;
2778 -       return NULL;
2779 -}
2780 -
2781 -void
2782 -TC_FREE(TC_HANDLE_T *h)
2783 -{
2784 -       struct chain_head *c, *tmp;
2785 -
2786 -       iptc_fn = TC_FREE;
2787 -       if (--sockfd_use == 0) {
2788 -               close(sockfd);
2789 -               sockfd = -1;
2790 -       }
2791 -
2792 -       list_for_each_entry_safe(c, tmp, &(*h)->chains, list) {
2793 -               struct rule_head *r, *rtmp;
2794 -
2795 -               list_for_each_entry_safe(r, rtmp, &c->rules, list) {
2796 -                       free(r);
2797 -               }
2798 -
2799 -               free(c);
2800 -       }
2801 -
2802 -       iptcc_chain_index_free(*h);
2803 -
2804 -       free((*h)->entries);
2805 -       free(*h);
2806 -
2807 -       *h = NULL;
2808 -}
2809 -
2810 -static inline int
2811 -print_match(const STRUCT_ENTRY_MATCH *m)
2812 -{
2813 -       printf("Match name: `%s'\n", m->u.user.name);
2814 -       return 0;
2815 -}
2816 -
2817 -static int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle);
2818
2819 -void
2820 -TC_DUMP_ENTRIES(const TC_HANDLE_T handle)
2821 -{
2822 -       iptc_fn = TC_DUMP_ENTRIES;
2823 -       CHECK(handle);
2824 -
2825 -       printf("libiptc v%s. %u bytes.\n",
2826 -              XTABLES_VERSION, handle->entries->size);
2827 -       printf("Table `%s'\n", handle->info.name);
2828 -       printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n",
2829 -              handle->info.hook_entry[HOOK_PRE_ROUTING],
2830 -              handle->info.hook_entry[HOOK_LOCAL_IN],
2831 -              handle->info.hook_entry[HOOK_FORWARD],
2832 -              handle->info.hook_entry[HOOK_LOCAL_OUT],
2833 -              handle->info.hook_entry[HOOK_POST_ROUTING]);
2834 -       printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n",
2835 -              handle->info.underflow[HOOK_PRE_ROUTING],
2836 -              handle->info.underflow[HOOK_LOCAL_IN],
2837 -              handle->info.underflow[HOOK_FORWARD],
2838 -              handle->info.underflow[HOOK_LOCAL_OUT],
2839 -              handle->info.underflow[HOOK_POST_ROUTING]);
2840 -
2841 -       ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size,
2842 -                     dump_entry, handle);
2843 -}
2844 -
2845 -/* Does this chain exist? */
2846 -int TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle)
2847 -{
2848 -       iptc_fn = TC_IS_CHAIN;
2849 -       return iptcc_find_label(chain, handle) != NULL;
2850 -}
2851 -
2852 -static void iptcc_chain_iterator_advance(TC_HANDLE_T handle)
2853 -{
2854 -       struct chain_head *c = handle->chain_iterator_cur;
2855 -
2856 -       if (c->list.next == &handle->chains)
2857 -               handle->chain_iterator_cur = NULL;
2858 -       else
2859 -               handle->chain_iterator_cur = 
2860 -                       list_entry(c->list.next, struct chain_head, list);
2861 -}
2862 -
2863 -/* Iterator functions to run through the chains. */
2864 -const char *
2865 -TC_FIRST_CHAIN(TC_HANDLE_T *handle)
2866 -{
2867 -       struct chain_head *c = list_entry((*handle)->chains.next,
2868 -                                         struct chain_head, list);
2869 -
2870 -       iptc_fn = TC_FIRST_CHAIN;
2871 -
2872 -
2873 -       if (list_empty(&(*handle)->chains)) {
2874 -               DEBUGP(": no chains\n");
2875 -               return NULL;
2876 -       }
2877 -
2878 -       (*handle)->chain_iterator_cur = c;
2879 -       iptcc_chain_iterator_advance(*handle);
2880 -
2881 -       DEBUGP(": returning `%s'\n", c->name);
2882 -       return c->name;
2883 -}
2884 -
2885 -/* Iterator functions to run through the chains.  Returns NULL at end. */
2886 -const char *
2887 -TC_NEXT_CHAIN(TC_HANDLE_T *handle)
2888 -{
2889 -       struct chain_head *c = (*handle)->chain_iterator_cur;
2890 -
2891 -       iptc_fn = TC_NEXT_CHAIN;
2892 -
2893 -       if (!c) {
2894 -               DEBUGP(": no more chains\n");
2895 -               return NULL;
2896 -       }
2897 -
2898 -       iptcc_chain_iterator_advance(*handle);
2899 -       
2900 -       DEBUGP(": returning `%s'\n", c->name);
2901 -       return c->name;
2902 -}
2903 -
2904 -/* Get first rule in the given chain: NULL for empty chain. */
2905 -const STRUCT_ENTRY *
2906 -TC_FIRST_RULE(const char *chain, TC_HANDLE_T *handle)
2907 -{
2908 -       struct chain_head *c;
2909 -       struct rule_head *r;
2910 -
2911 -       iptc_fn = TC_FIRST_RULE;
2912 -
2913 -       DEBUGP("first rule(%s): ", chain);
2914 -
2915 -       c = iptcc_find_label(chain, *handle);
2916 -       if (!c) {
2917 -               errno = ENOENT;
2918 -               return NULL;
2919 -       }
2920 -
2921 -       /* Empty chain: single return/policy rule */
2922 -       if (list_empty(&c->rules)) {
2923 -               DEBUGP_C("no rules, returning NULL\n");
2924 -               return NULL;
2925 -       }
2926 -
2927 -       r = list_entry(c->rules.next, struct rule_head, list);
2928 -       (*handle)->rule_iterator_cur = r;
2929 -       DEBUGP_C("%p\n", r);
2930 -
2931 -       return r->entry;
2932 -}
2933 -
2934 -/* Returns NULL when rules run out. */
2935 -const STRUCT_ENTRY *
2936 -TC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle)
2937 -{
2938 -       struct rule_head *r;
2939 -
2940 -       iptc_fn = TC_NEXT_RULE;
2941 -       DEBUGP("rule_iterator_cur=%p...", (*handle)->rule_iterator_cur);
2942 -
2943 -       if (!(*handle)->rule_iterator_cur) {
2944 -               DEBUGP_C("returning NULL\n");
2945 -               return NULL;
2946 -       }
2947 -       
2948 -       r = list_entry((*handle)->rule_iterator_cur->list.next, 
2949 -                       struct rule_head, list);
2950 -
2951 -       iptc_fn = TC_NEXT_RULE;
2952 -
2953 -       DEBUGP_C("next=%p, head=%p...", &r->list, 
2954 -               &(*handle)->rule_iterator_cur->chain->rules);
2955 -
2956 -       if (&r->list == &(*handle)->rule_iterator_cur->chain->rules) {
2957 -               (*handle)->rule_iterator_cur = NULL;
2958 -               DEBUGP_C("finished, returning NULL\n");
2959 -               return NULL;
2960 -       }
2961 -
2962 -       (*handle)->rule_iterator_cur = r;
2963 -
2964 -       /* NOTE: prev is without any influence ! */
2965 -       DEBUGP_C("returning rule %p\n", r);
2966 -       return r->entry;
2967 -}
2968 -
2969 -/* How many rules in this chain? */
2970 -#if 0
2971 -static unsigned int
2972 -TC_NUM_RULES(const char *chain, TC_HANDLE_T *handle)
2973 -{
2974 -       struct chain_head *c;
2975 -       iptc_fn = TC_NUM_RULES;
2976 -       CHECK(*handle);
2977 -
2978 -       c = iptcc_find_label(chain, *handle);
2979 -       if (!c) {
2980 -               errno = ENOENT;
2981 -               return (unsigned int)-1;
2982 -       }
2983 -       
2984 -       return c->num_rules;
2985 -}
2986 -#endif
2987 -
2988 -#if 0
2989 -static const STRUCT_ENTRY *
2990 -TC_GET_RULE(const char *chain, unsigned int n, TC_HANDLE_T *handle)
2991 -{
2992 -       struct chain_head *c;
2993 -       struct rule_head *r;
2994 -       
2995 -       iptc_fn = TC_GET_RULE;
2996 -
2997 -       CHECK(*handle);
2998 -
2999 -       c = iptcc_find_label(chain, *handle);
3000 -       if (!c) {
3001 -               errno = ENOENT;
3002 -               return NULL;
3003 -       }
3004 -
3005 -       r = iptcc_get_rule_num(c, n);
3006 -       if (!r)
3007 -               return NULL;
3008 -       return r->entry;
3009 -}
3010 -#endif
3011 -
3012 -/* Returns a pointer to the target name of this position. */
3013 -static const char *standard_target_map(int verdict)
3014 -{
3015 -       switch (verdict) {
3016 -               case RETURN:
3017 -                       return LABEL_RETURN;
3018 -                       break;
3019 -               case -NF_ACCEPT-1:
3020 -                       return LABEL_ACCEPT;
3021 -                       break;
3022 -               case -NF_DROP-1:
3023 -                       return LABEL_DROP;
3024 -                       break;
3025 -               case -NF_QUEUE-1:
3026 -                       return LABEL_QUEUE;
3027 -                       break;
3028 -               default:
3029 -                       fprintf(stderr, "ERROR: %d not a valid target)\n",
3030 -                               verdict);
3031 -                       abort();
3032 -                       break;
3033 -       }
3034 -       /* not reached */
3035 -       return NULL;
3036 -}
3037 -
3038 -/* Returns a pointer to the target name of this position. */
3039 -const char *TC_GET_TARGET(const STRUCT_ENTRY *ce,
3040 -                         TC_HANDLE_T *handle)
3041 -{
3042 -       STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce;
3043 -       struct rule_head *r = container_of(e, struct rule_head, entry[0]);
3044 -       const unsigned char *data;
3045 -
3046 -       iptc_fn = TC_GET_TARGET;
3047 -
3048 -       switch(r->type) {
3049 -               int spos;
3050 -               case IPTCC_R_FALLTHROUGH:
3051 -                       return "";
3052 -                       break;
3053 -               case IPTCC_R_JUMP:
3054 -                       DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name);
3055 -                       return r->jump->name;
3056 -                       break;
3057 -               case IPTCC_R_STANDARD:
3058 -                       data = GET_TARGET(e)->data;
3059 -                       spos = *(const int *)data;
3060 -                       DEBUGP("r=%p, spos=%d'\n", r, spos);
3061 -                       return standard_target_map(spos);
3062 -                       break;
3063 -               case IPTCC_R_MODULE:
3064 -                       return GET_TARGET(e)->u.user.name;
3065 -                       break;
3066 -       }
3067 -       return NULL;
3068 -}
3069 -/* Is this a built-in chain?  Actually returns hook + 1. */
3070 -int
3071 -TC_BUILTIN(const char *chain, const TC_HANDLE_T handle)
3072 -{
3073 -       struct chain_head *c;
3074 -       
3075 -       iptc_fn = TC_BUILTIN;
3076 -
3077 -       c = iptcc_find_label(chain, handle);
3078 -       if (!c) {
3079 -               errno = ENOENT;
3080 -               return 0;
3081 -       }
3082 -
3083 -       return iptcc_is_builtin(c);
3084 -}
3085 -
3086 -/* Get the policy of a given built-in chain */
3087 -const char *
3088 -TC_GET_POLICY(const char *chain,
3089 -             STRUCT_COUNTERS *counters,
3090 -             TC_HANDLE_T *handle)
3091 -{
3092 -       struct chain_head *c;
3093 -
3094 -       iptc_fn = TC_GET_POLICY;
3095 -
3096 -       DEBUGP("called for chain %s\n", chain);
3097 -
3098 -       c = iptcc_find_label(chain, *handle);
3099 -       if (!c) {
3100 -               errno = ENOENT;
3101 -               return NULL;
3102 -       }
3103 -
3104 -       if (!iptcc_is_builtin(c))
3105 -               return NULL;
3106 -
3107 -       *counters = c->counters;
3108 -
3109 -       return standard_target_map(c->verdict);
3110 -}
3111 -
3112 -static int
3113 -iptcc_standard_map(struct rule_head *r, int verdict)
3114 -{
3115 -       STRUCT_ENTRY *e = r->entry;
3116 -       STRUCT_STANDARD_TARGET *t;
3117 -
3118 -       t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
3119 -
3120 -       if (t->target.u.target_size
3121 -           != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) {
3122 -               errno = EINVAL;
3123 -               return 0;
3124 -       }
3125 -       /* memset for memcmp convenience on delete/replace */
3126 -       memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
3127 -       strcpy(t->target.u.user.name, STANDARD_TARGET);
3128 -       t->verdict = verdict;
3129 -
3130 -       r->type = IPTCC_R_STANDARD;
3131 -
3132 -       return 1;
3133 -}
3134 -
3135 -static int
3136 -iptcc_map_target(const TC_HANDLE_T handle,
3137 -          struct rule_head *r)
3138 -{
3139 -       STRUCT_ENTRY *e = r->entry;
3140 -       STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
3141 -
3142 -       /* Maybe it's empty (=> fall through) */
3143 -       if (strcmp(t->u.user.name, "") == 0) {
3144 -               r->type = IPTCC_R_FALLTHROUGH;
3145 -               return 1;
3146 -       }
3147 -       /* Maybe it's a standard target name... */
3148 -       else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0)
3149 -               return iptcc_standard_map(r, -NF_ACCEPT - 1);
3150 -       else if (strcmp(t->u.user.name, LABEL_DROP) == 0)
3151 -               return iptcc_standard_map(r, -NF_DROP - 1);
3152 -       else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0)
3153 -               return iptcc_standard_map(r, -NF_QUEUE - 1);
3154 -       else if (strcmp(t->u.user.name, LABEL_RETURN) == 0)
3155 -               return iptcc_standard_map(r, RETURN);
3156 -       else if (TC_BUILTIN(t->u.user.name, handle)) {
3157 -               /* Can't jump to builtins. */
3158 -               errno = EINVAL;
3159 -               return 0;
3160 -       } else {
3161 -               /* Maybe it's an existing chain name. */
3162 -               struct chain_head *c;
3163 -               DEBUGP("trying to find chain `%s': ", t->u.user.name);
3164 -
3165 -               c = iptcc_find_label(t->u.user.name, handle);
3166 -               if (c) {
3167 -                       DEBUGP_C("found!\n");
3168 -                       r->type = IPTCC_R_JUMP;
3169 -                       r->jump = c;
3170 -                       c->references++;
3171 -                       return 1;
3172 -               }
3173 -               DEBUGP_C("not found :(\n");
3174 -       }
3175 -
3176 -       /* Must be a module?  If not, kernel will reject... */
3177 -       /* memset to all 0 for your memcmp convenience: don't clear version */
3178 -       memset(t->u.user.name + strlen(t->u.user.name),
3179 -              0,
3180 -              FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name));
3181 -       r->type = IPTCC_R_MODULE;
3182 -       set_changed(handle);
3183 -       return 1;
3184 -}
3185 -
3186 -/* Insert the entry `fw' in chain `chain' into position `rulenum'. */
3187 -int
3188 -TC_INSERT_ENTRY(const IPT_CHAINLABEL chain,
3189 -               const STRUCT_ENTRY *e,
3190 -               unsigned int rulenum,
3191 -               TC_HANDLE_T *handle)
3192 -{
3193 -       struct chain_head *c;
3194 -       struct rule_head *r;
3195 -       struct list_head *prev;
3196 -
3197 -       iptc_fn = TC_INSERT_ENTRY;
3198 -
3199 -       if (!(c = iptcc_find_label(chain, *handle))) {
3200 -               errno = ENOENT;
3201 -               return 0;
3202 -       }
3203 -
3204 -       /* first rulenum index = 0
3205 -          first c->num_rules index = 1 */
3206 -       if (rulenum > c->num_rules) {
3207 -               errno = E2BIG;
3208 -               return 0;
3209 -       }
3210 -
3211 -       /* If we are inserting at the end just take advantage of the
3212 -          double linked list, insert will happen before the entry
3213 -          prev points to. */
3214 -       if (rulenum == c->num_rules) {
3215 -               prev = &c->rules;
3216 -       } else if (rulenum + 1 <= c->num_rules/2) {
3217 -               r = iptcc_get_rule_num(c, rulenum + 1);
3218 -               prev = &r->list;
3219 -       } else {
3220 -               r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum);
3221 -               prev = &r->list;
3222 -       }
3223 -
3224 -       if (!(r = iptcc_alloc_rule(c, e->next_offset))) {
3225 -               errno = ENOMEM;
3226 -               return 0;
3227 -       }
3228 -
3229 -       memcpy(r->entry, e, e->next_offset);
3230 -       r->counter_map.maptype = COUNTER_MAP_SET;
3231 -
3232 -       if (!iptcc_map_target(*handle, r)) {
3233 -               free(r);
3234 -               return 0;
3235 -       }
3236 -
3237 -       list_add_tail(&r->list, prev);
3238 -       c->num_rules++;
3239 -
3240 -       set_changed(*handle);
3241 -
3242 -       return 1;
3243 -}
3244 -
3245 -/* Atomically replace rule `rulenum' in `chain' with `fw'. */
3246 -int
3247 -TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain,
3248 -                const STRUCT_ENTRY *e,
3249 -                unsigned int rulenum,
3250 -                TC_HANDLE_T *handle)
3251 -{
3252 -       struct chain_head *c;
3253 -       struct rule_head *r, *old;
3254 -
3255 -       iptc_fn = TC_REPLACE_ENTRY;
3256 -
3257 -       if (!(c = iptcc_find_label(chain, *handle))) {
3258 -               errno = ENOENT;
3259 -               return 0;
3260 -       }
3261 -
3262 -       if (rulenum >= c->num_rules) {
3263 -               errno = E2BIG;
3264 -               return 0;
3265 -       }
3266 -
3267 -       /* Take advantage of the double linked list if possible. */
3268 -       if (rulenum + 1 <= c->num_rules/2) {
3269 -               old = iptcc_get_rule_num(c, rulenum + 1);
3270 -       } else {
3271 -               old = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum);
3272 -       }
3273 -
3274 -       if (!(r = iptcc_alloc_rule(c, e->next_offset))) {
3275 -               errno = ENOMEM;
3276 -               return 0;
3277 -       }
3278 -
3279 -       memcpy(r->entry, e, e->next_offset);
3280 -       r->counter_map.maptype = COUNTER_MAP_SET;
3281 -
3282 -       if (!iptcc_map_target(*handle, r)) {
3283 -               free(r);
3284 -               return 0;
3285 -       }
3286 -
3287 -       list_add(&r->list, &old->list);
3288 -       iptcc_delete_rule(old);
3289 -
3290 -       set_changed(*handle);
3291 -
3292 -       return 1;
3293 -}
3294 -
3295 -/* Append entry `fw' to chain `chain'.  Equivalent to insert with
3296 -   rulenum = length of chain. */
3297 -int
3298 -TC_APPEND_ENTRY(const IPT_CHAINLABEL chain,
3299 -               const STRUCT_ENTRY *e,
3300 -               TC_HANDLE_T *handle)
3301 -{
3302 -       struct chain_head *c;
3303 -       struct rule_head *r;
3304 -
3305 -       iptc_fn = TC_APPEND_ENTRY;
3306 -       if (!(c = iptcc_find_label(chain, *handle))) {
3307 -               DEBUGP("unable to find chain `%s'\n", chain);
3308 -               errno = ENOENT;
3309 -               return 0;
3310 -       }
3311 -
3312 -       if (!(r = iptcc_alloc_rule(c, e->next_offset))) {
3313 -               DEBUGP("unable to allocate rule for chain `%s'\n", chain);
3314 -               errno = ENOMEM;
3315 -               return 0;
3316 -       }
3317 -
3318 -       memcpy(r->entry, e, e->next_offset);
3319 -       r->counter_map.maptype = COUNTER_MAP_SET;
3320 -
3321 -       if (!iptcc_map_target(*handle, r)) {
3322 -               DEBUGP("unable to map target of rule for chain `%s'\n", chain);
3323 -               free(r);
3324 -               return 0;
3325 -       }
3326 -
3327 -       list_add_tail(&r->list, &c->rules);
3328 -       c->num_rules++;
3329 -
3330 -       set_changed(*handle);
3331 -
3332 -       return 1;
3333 -}
3334 -
3335 -static inline int
3336 -match_different(const STRUCT_ENTRY_MATCH *a,
3337 -               const unsigned char *a_elems,
3338 -               const unsigned char *b_elems,
3339 -               unsigned char **maskptr)
3340 -{
3341 -       const STRUCT_ENTRY_MATCH *b;
3342 -       unsigned int i;
3343 -
3344 -       /* Offset of b is the same as a. */
3345 -       b = (void *)b_elems + ((unsigned char *)a - a_elems);
3346 -
3347 -       if (a->u.match_size != b->u.match_size)
3348 -               return 1;
3349 -
3350 -       if (strcmp(a->u.user.name, b->u.user.name) != 0)
3351 -               return 1;
3352 -
3353 -       *maskptr += ALIGN(sizeof(*a));
3354 -
3355 -       for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++)
3356 -               if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0)
3357 -                       return 1;
3358 -       *maskptr += i;
3359 -       return 0;
3360 -}
3361 -
3362 -static inline int
3363 -target_same(struct rule_head *a, struct rule_head *b,const unsigned char *mask)
3364 -{
3365 -       unsigned int i;
3366 -       STRUCT_ENTRY_TARGET *ta, *tb;
3367 -
3368 -       if (a->type != b->type)
3369 -               return 0;
3370 -
3371 -       ta = GET_TARGET(a->entry);
3372 -       tb = GET_TARGET(b->entry);
3373 -
3374 -       switch (a->type) {
3375 -       case IPTCC_R_FALLTHROUGH:
3376 -               return 1;
3377 -       case IPTCC_R_JUMP:
3378 -               return a->jump == b->jump;
3379 -       case IPTCC_R_STANDARD:
3380 -               return ((STRUCT_STANDARD_TARGET *)ta)->verdict
3381 -                       == ((STRUCT_STANDARD_TARGET *)tb)->verdict;
3382 -       case IPTCC_R_MODULE:
3383 -               if (ta->u.target_size != tb->u.target_size)
3384 -                       return 0;
3385 -               if (strcmp(ta->u.user.name, tb->u.user.name) != 0)
3386 -                       return 0;
3387 -
3388 -               for (i = 0; i < ta->u.target_size - sizeof(*ta); i++)
3389 -                       if (((ta->data[i] ^ tb->data[i]) & mask[i]) != 0)
3390 -                               return 0;
3391 -               return 1;
3392 -       default:
3393 -               fprintf(stderr, "ERROR: bad type %i\n", a->type);
3394 -               abort();
3395 -       }
3396 -}
3397 -
3398 -static unsigned char *
3399 -is_same(const STRUCT_ENTRY *a,
3400 -       const STRUCT_ENTRY *b,
3401 -       unsigned char *matchmask);
3402 -
3403 -/* Delete the first rule in `chain' which matches `fw'. */
3404 -int
3405 -TC_DELETE_ENTRY(const IPT_CHAINLABEL chain,
3406 -               const STRUCT_ENTRY *origfw,
3407 -               unsigned char *matchmask,
3408 -               TC_HANDLE_T *handle)
3409 -{
3410 -       struct chain_head *c;
3411 -       struct rule_head *r, *i;
3412 -
3413 -       iptc_fn = TC_DELETE_ENTRY;
3414 -       if (!(c = iptcc_find_label(chain, *handle))) {
3415 -               errno = ENOENT;
3416 -               return 0;
3417 -       }
3418 -
3419 -       /* Create a rule_head from origfw. */
3420 -       r = iptcc_alloc_rule(c, origfw->next_offset);
3421 -       if (!r) {
3422 -               errno = ENOMEM;
3423 -               return 0;
3424 -       }
3425 -
3426 -       memcpy(r->entry, origfw, origfw->next_offset);
3427 -       r->counter_map.maptype = COUNTER_MAP_NOMAP;
3428 -       if (!iptcc_map_target(*handle, r)) {
3429 -               DEBUGP("unable to map target of rule for chain `%s'\n", chain);
3430 -               free(r);
3431 -               return 0;
3432 -       } else {
3433 -               /* iptcc_map_target increment target chain references
3434 -                * since this is a fake rule only used for matching
3435 -                * the chain references count is decremented again. 
3436 -                */
3437 -               if (r->type == IPTCC_R_JUMP
3438 -                   && r->jump)
3439 -                       r->jump->references--;
3440 -       }
3441 -
3442 -       list_for_each_entry(i, &c->rules, list) {
3443 -               unsigned char *mask;
3444 -
3445 -               mask = is_same(r->entry, i->entry, matchmask);
3446 -               if (!mask)
3447 -                       continue;
3448 -
3449 -               if (!target_same(r, i, mask))
3450 -                       continue;
3451 -
3452 -               /* If we are about to delete the rule that is the
3453 -                * current iterator, move rule iterator back.  next
3454 -                * pointer will then point to real next node */
3455 -               if (i == (*handle)->rule_iterator_cur) {
3456 -                       (*handle)->rule_iterator_cur = 
3457 -                               list_entry((*handle)->rule_iterator_cur->list.prev,
3458 -                                          struct rule_head, list);
3459 -               }
3460 -
3461 -               c->num_rules--;
3462 -               iptcc_delete_rule(i);
3463 -
3464 -               set_changed(*handle);
3465 -               free(r);
3466 -               return 1;
3467 -       }
3468 -
3469 -       free(r);
3470 -       errno = ENOENT;
3471 -       return 0;
3472 -}
3473 -
3474 -
3475 -/* Delete the rule in position `rulenum' in `chain'. */
3476 -int
3477 -TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain,
3478 -                   unsigned int rulenum,
3479 -                   TC_HANDLE_T *handle)
3480 -{
3481 -       struct chain_head *c;
3482 -       struct rule_head *r;
3483 -
3484 -       iptc_fn = TC_DELETE_NUM_ENTRY;
3485 -
3486 -       if (!(c = iptcc_find_label(chain, *handle))) {
3487 -               errno = ENOENT;
3488 -               return 0;
3489 -       }
3490 -
3491 -       if (rulenum >= c->num_rules) {
3492 -               errno = E2BIG;
3493 -               return 0;
3494 -       }
3495 -
3496 -       /* Take advantage of the double linked list if possible. */
3497 -       if (rulenum + 1 <= c->num_rules/2) {
3498 -               r = iptcc_get_rule_num(c, rulenum + 1);
3499 -       } else {
3500 -               r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum);
3501 -       }
3502 -
3503 -       /* If we are about to delete the rule that is the current
3504 -        * iterator, move rule iterator back.  next pointer will then
3505 -        * point to real next node */
3506 -       if (r == (*handle)->rule_iterator_cur) {
3507 -               (*handle)->rule_iterator_cur =