- libvirt package created only on libvirt bcond
[packages/collectd.git] / netfilter.patch
CommitLineData
537d5e17
AF
1commit 99364c70a7039ed496dbe429fb86ee41e464fc76
2Author: Florian Forster <octo@collectd.org>
3Date: 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
10diff --git a/configure.in b/configure.in
11index 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};'`)"
137diff --git a/src/Makefile.am b/src/Makefile.am
138index 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
162diff --git a/src/iptables.c b/src/iptables.c
163index 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
203diff --git a/src/owniptc/Makefile.am b/src/owniptc/Makefile.am
204deleted file mode 100644
205index 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-
223diff --git a/src/owniptc/README.collectd b/src/owniptc/README.collectd
224deleted file mode 100644
225index 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-
254diff --git a/src/owniptc/ipt_kernel_headers.h b/src/owniptc/ipt_kernel_headers.h
255deleted file mode 100644
256index 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
305diff --git a/src/owniptc/libip4tc.c b/src/owniptc/libip4tc.c
306deleted file mode 100644
307index 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
828diff --git a/src/owniptc/libip6tc.c b/src/owniptc/libip6tc.c
829deleted file mode 100644
830index 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*/
1290diff --git a/src/owniptc/libip6tc.h b/src/owniptc/libip6tc.h
1291deleted file mode 100644
1292index 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 */
1471diff --git a/src/owniptc/libiptc.c b/src/owniptc/libiptc.c
1472deleted file mode 100644
1473index 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 =
3508- list_entry((*handle)->rule_iterator_cur->list.prev,
3509- struct rule_head, list);
3510- }
3511-
3512- c->num_rules--;
3513- iptcc_delete_rule(r);
3514-
3515- set_changed(*handle);
3516-
3517- return 1;
3518-}
3519-
3520-/* Check the packet `fw' on chain `chain'. Returns the verdict, or
3521- NULL and sets errno. */
3522-const char *
3523-TC_CHECK_PACKET(const IPT_CHAINLABEL chain,
3524- STRUCT_ENTRY *entry,
3525- TC_HANDLE_T *handle)
3526-{
3527- iptc_fn = TC_CHECK_PACKET;
3528- errno = ENOSYS;
3529- return NULL;
3530-}
3531-
3532-/* Flushes the entries in the given chain (ie. empties chain). */
3533-int
3534-TC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
3535-{
3536- struct chain_head *c;
3537- struct rule_head *r, *tmp;
3538-
3539- iptc_fn = TC_FLUSH_ENTRIES;
3540- if (!(c = iptcc_find_label(chain, *handle))) {
3541- errno = ENOENT;
3542- return 0;
3543- }
3544-
3545- list_for_each_entry_safe(r, tmp, &c->rules, list) {
3546- iptcc_delete_rule(r);
3547- }
3548-
3549- c->num_rules = 0;
3550-
3551- set_changed(*handle);
3552-
3553- return 1;
3554-}
3555-
3556-/* Zeroes the counters in a chain. */
3557-int
3558-TC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
3559-{
3560- struct chain_head *c;
3561- struct rule_head *r;
3562-
3563- iptc_fn = TC_ZERO_ENTRIES;
3564- if (!(c = iptcc_find_label(chain, *handle))) {
3565- errno = ENOENT;
3566- return 0;
3567- }
3568-
3569- if (c->counter_map.maptype == COUNTER_MAP_NORMAL_MAP)
3570- c->counter_map.maptype = COUNTER_MAP_ZEROED;
3571-
3572- list_for_each_entry(r, &c->rules, list) {
3573- if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP)
3574- r->counter_map.maptype = COUNTER_MAP_ZEROED;
3575- }
3576-
3577- set_changed(*handle);
3578-
3579- return 1;
3580-}
3581-
3582-STRUCT_COUNTERS *
3583-TC_READ_COUNTER(const IPT_CHAINLABEL chain,
3584- unsigned int rulenum,
3585- TC_HANDLE_T *handle)
3586-{
3587- struct chain_head *c;
3588- struct rule_head *r;
3589-
3590- iptc_fn = TC_READ_COUNTER;
3591- CHECK(*handle);
3592-
3593- if (!(c = iptcc_find_label(chain, *handle))) {
3594- errno = ENOENT;
3595- return NULL;
3596- }
3597-
3598- if (!(r = iptcc_get_rule_num(c, rulenum))) {
3599- errno = E2BIG;
3600- return NULL;
3601- }
3602-
3603- return &r->entry[0].counters;
3604-}
3605-
3606-int
3607-TC_ZERO_COUNTER(const IPT_CHAINLABEL chain,
3608- unsigned int rulenum,
3609- TC_HANDLE_T *handle)
3610-{
3611- struct chain_head *c;
3612- struct rule_head *r;
3613-
3614- iptc_fn = TC_ZERO_COUNTER;
3615- CHECK(*handle);
3616-
3617- if (!(c = iptcc_find_label(chain, *handle))) {
3618- errno = ENOENT;
3619- return 0;
3620- }
3621-
3622- if (!(r = iptcc_get_rule_num(c, rulenum))) {
3623- errno = E2BIG;
3624- return 0;
3625- }
3626-
3627- if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP)
3628- r->counter_map.maptype = COUNTER_MAP_ZEROED;
3629-
3630- set_changed(*handle);
3631-
3632- return 1;
3633-}
3634-
3635-int
3636-TC_SET_COUNTER(const IPT_CHAINLABEL chain,
3637- unsigned int rulenum,
3638- STRUCT_COUNTERS *counters,
3639- TC_HANDLE_T *handle)
3640-{
3641- struct chain_head *c;
3642- struct rule_head *r;
3643- STRUCT_ENTRY *e;
3644-
3645- iptc_fn = TC_SET_COUNTER;
3646- CHECK(*handle);
3647-
3648- if (!(c = iptcc_find_label(chain, *handle))) {
3649- errno = ENOENT;
3650- return 0;
3651- }
3652-
3653- if (!(r = iptcc_get_rule_num(c, rulenum))) {
3654- errno = E2BIG;
3655- return 0;
3656- }
3657-
3658- e = r->entry;
3659- r->counter_map.maptype = COUNTER_MAP_SET;
3660-
3661- memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS));
3662-
3663- set_changed(*handle);
3664-
3665- return 1;
3666-}
3667-
3668-/* Creates a new chain. */
3669-/* To create a chain, create two rules: error node and unconditional
3670- * return. */
3671-int
3672-TC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
3673-{
3674- static struct chain_head *c;
3675- int capacity;
3676- int exceeded;
3677-
3678- iptc_fn = TC_CREATE_CHAIN;
3679-
3680- /* find_label doesn't cover built-in targets: DROP, ACCEPT,
3681- QUEUE, RETURN. */
3682- if (iptcc_find_label(chain, *handle)
3683- || strcmp(chain, LABEL_DROP) == 0
3684- || strcmp(chain, LABEL_ACCEPT) == 0
3685- || strcmp(chain, LABEL_QUEUE) == 0
3686- || strcmp(chain, LABEL_RETURN) == 0) {
3687- DEBUGP("Chain `%s' already exists\n", chain);
3688- errno = EEXIST;
3689- return 0;
3690- }
3691-
3692- if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) {
3693- DEBUGP("Chain name `%s' too long\n", chain);
3694- errno = EINVAL;
3695- return 0;
3696- }
3697-
3698- c = iptcc_alloc_chain_head(chain, 0);
3699- if (!c) {
3700- DEBUGP("Cannot allocate memory for chain `%s'\n", chain);
3701- errno = ENOMEM;
3702- return 0;
3703-
3704- }
3705- (*handle)->num_chains++; /* New user defined chain */
3706-
3707- DEBUGP("Creating chain `%s'\n", chain);
3708- iptc_insert_chain(*handle, c); /* Insert sorted */
3709-
3710- /* Inserting chains don't change the correctness of the chain
3711- * index (except if its smaller than index[0], but that
3712- * handled by iptc_insert_chain). It only causes longer lists
3713- * in the buckets. Thus, only rebuild chain index when the
3714- * capacity is exceed with CHAIN_INDEX_INSERT_MAX chains.
3715- */
3716- capacity = (*handle)->chain_index_sz * CHAIN_INDEX_BUCKET_LEN;
3717- exceeded = ((((*handle)->num_chains)-capacity));
3718- if (exceeded > CHAIN_INDEX_INSERT_MAX) {
3719- debug("Capacity(%d) exceeded(%d) rebuild (chains:%d)\n",
3720- capacity, exceeded, (*handle)->num_chains);
3721- iptcc_chain_index_rebuild(*handle);
3722- }
3723-
3724- set_changed(*handle);
3725-
3726- return 1;
3727-}
3728-
3729-/* Get the number of references to this chain. */
3730-int
3731-TC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain,
3732- TC_HANDLE_T *handle)
3733-{
3734- struct chain_head *c;
3735-
3736- iptc_fn = TC_GET_REFERENCES;
3737- if (!(c = iptcc_find_label(chain, *handle))) {
3738- errno = ENOENT;
3739- return 0;
3740- }
3741-
3742- *ref = c->references;
3743-
3744- return 1;
3745-}
3746-
3747-/* Deletes a chain. */
3748-int
3749-TC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
3750-{
3751- unsigned int references;
3752- struct chain_head *c;
3753-
3754- iptc_fn = TC_DELETE_CHAIN;
3755-
3756- if (!(c = iptcc_find_label(chain, *handle))) {
3757- DEBUGP("cannot find chain `%s'\n", chain);
3758- errno = ENOENT;
3759- return 0;
3760- }
3761-
3762- if (TC_BUILTIN(chain, *handle)) {
3763- DEBUGP("cannot remove builtin chain `%s'\n", chain);
3764- errno = EINVAL;
3765- return 0;
3766- }
3767-
3768- if (!TC_GET_REFERENCES(&references, chain, handle)) {
3769- DEBUGP("cannot get references on chain `%s'\n", chain);
3770- return 0;
3771- }
3772-
3773- if (references > 0) {
3774- DEBUGP("chain `%s' still has references\n", chain);
3775- errno = EMLINK;
3776- return 0;
3777- }
3778-
3779- if (c->num_rules) {
3780- DEBUGP("chain `%s' is not empty\n", chain);
3781- errno = ENOTEMPTY;
3782- return 0;
3783- }
3784-
3785- /* If we are about to delete the chain that is the current
3786- * iterator, move chain iterator forward. */
3787- if (c == (*handle)->chain_iterator_cur)
3788- iptcc_chain_iterator_advance(*handle);
3789-
3790- (*handle)->num_chains--; /* One user defined chain deleted */
3791-
3792- //list_del(&c->list); /* Done in iptcc_chain_index_delete_chain() */
3793- iptcc_chain_index_delete_chain(c, *handle);
3794- free(c);
3795-
3796- DEBUGP("chain `%s' deleted\n", chain);
3797-
3798- set_changed(*handle);
3799-
3800- return 1;
3801-}
3802-
3803-/* Renames a chain. */
3804-int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname,
3805- const IPT_CHAINLABEL newname,
3806- TC_HANDLE_T *handle)
3807-{
3808- struct chain_head *c;
3809- iptc_fn = TC_RENAME_CHAIN;
3810-
3811- /* find_label doesn't cover built-in targets: DROP, ACCEPT,
3812- QUEUE, RETURN. */
3813- if (iptcc_find_label(newname, *handle)
3814- || strcmp(newname, LABEL_DROP) == 0
3815- || strcmp(newname, LABEL_ACCEPT) == 0
3816- || strcmp(newname, LABEL_QUEUE) == 0
3817- || strcmp(newname, LABEL_RETURN) == 0) {
3818- errno = EEXIST;
3819- return 0;
3820- }
3821-
3822- if (!(c = iptcc_find_label(oldname, *handle))
3823- || TC_BUILTIN(oldname, *handle)) {
3824- errno = ENOENT;
3825- return 0;
3826- }
3827-
3828- if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) {
3829- errno = EINVAL;
3830- return 0;
3831- }
3832-
3833- strncpy(c->name, newname, sizeof(IPT_CHAINLABEL));
3834-
3835- set_changed(*handle);
3836-
3837- return 1;
3838-}
3839-
3840-/* Sets the policy on a built-in chain. */
3841-int
3842-TC_SET_POLICY(const IPT_CHAINLABEL chain,
3843- const IPT_CHAINLABEL policy,
3844- STRUCT_COUNTERS *counters,
3845- TC_HANDLE_T *handle)
3846-{
3847- struct chain_head *c;
3848-
3849- iptc_fn = TC_SET_POLICY;
3850-
3851- if (!(c = iptcc_find_label(chain, *handle))) {
3852- DEBUGP("cannot find chain `%s'\n", chain);
3853- errno = ENOENT;
3854- return 0;
3855- }
3856-
3857- if (!iptcc_is_builtin(c)) {
3858- DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain);
3859- errno = ENOENT;
3860- return 0;
3861- }
3862-
3863- if (strcmp(policy, LABEL_ACCEPT) == 0)
3864- c->verdict = -NF_ACCEPT - 1;
3865- else if (strcmp(policy, LABEL_DROP) == 0)
3866- c->verdict = -NF_DROP - 1;
3867- else {
3868- errno = EINVAL;
3869- return 0;
3870- }
3871-
3872- if (counters) {
3873- /* set byte and packet counters */
3874- memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS));
3875- c->counter_map.maptype = COUNTER_MAP_SET;
3876- } else {
3877- c->counter_map.maptype = COUNTER_MAP_NOMAP;
3878- }
3879-
3880- set_changed(*handle);
3881-
3882- return 1;
3883-}
3884-
3885-/* Without this, on gcc 2.7.2.3, we get:
3886- libiptc.c: In function `TC_COMMIT':
3887- libiptc.c:833: fixed or forbidden register was spilled.
3888- This may be due to a compiler bug or to impossible asm
3889- statements or clauses.
3890-*/
3891-static void
3892-subtract_counters(STRUCT_COUNTERS *answer,
3893- const STRUCT_COUNTERS *a,
3894- const STRUCT_COUNTERS *b)
3895-{
3896- answer->pcnt = a->pcnt - b->pcnt;
3897- answer->bcnt = a->bcnt - b->bcnt;
3898-}
3899-
3900-
3901-static void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, unsigned int idx)
3902-{
3903- newcounters->counters[idx] = ((STRUCT_COUNTERS) { 0, 0});
3904- DEBUGP_C("NOMAP => zero\n");
3905-}
3906-
3907-static void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters,
3908- STRUCT_REPLACE *repl, unsigned int idx,
3909- unsigned int mappos)
3910-{
3911- /* Original read: X.
3912- * Atomic read on replacement: X + Y.
3913- * Currently in kernel: Z.
3914- * Want in kernel: X + Y + Z.
3915- * => Add in X + Y
3916- * => Add in replacement read.
3917- */
3918- newcounters->counters[idx] = repl->counters[mappos];
3919- DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos);
3920-}
3921-
3922-static void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters,
3923- STRUCT_REPLACE *repl, unsigned int idx,
3924- unsigned int mappos, STRUCT_COUNTERS *counters)
3925-{
3926- /* Original read: X.
3927- * Atomic read on replacement: X + Y.
3928- * Currently in kernel: Z.
3929- * Want in kernel: Y + Z.
3930- * => Add in Y.
3931- * => Add in (replacement read - original read).
3932- */
3933- subtract_counters(&newcounters->counters[idx],
3934- &repl->counters[mappos],
3935- counters);
3936- DEBUGP_C("ZEROED => mappos %u\n", mappos);
3937-}
3938-
3939-static void counters_map_set(STRUCT_COUNTERS_INFO *newcounters,
3940- unsigned int idx, STRUCT_COUNTERS *counters)
3941-{
3942- /* Want to set counter (iptables-restore) */
3943-
3944- memcpy(&newcounters->counters[idx], counters,
3945- sizeof(STRUCT_COUNTERS));
3946-
3947- DEBUGP_C("SET\n");
3948-}
3949-
3950-
3951-int
3952-TC_COMMIT(TC_HANDLE_T *handle)
3953-{
3954- /* Replace, then map back the counters. */
3955- STRUCT_REPLACE *repl;
3956- STRUCT_COUNTERS_INFO *newcounters;
3957- struct chain_head *c;
3958- int ret;
3959- size_t counterlen;
3960- int new_number;
3961- unsigned int new_size;
3962-
3963- iptc_fn = TC_COMMIT;
3964- CHECK(*handle);
3965-
3966- /* Don't commit if nothing changed. */
3967- if (!(*handle)->changed)
3968- goto finished;
3969-
3970- new_number = iptcc_compile_table_prep(*handle, &new_size);
3971- if (new_number < 0) {
3972- errno = ENOMEM;
3973- goto out_zero;
3974- }
3975-
3976- repl = malloc(sizeof(*repl) + new_size);
3977- if (!repl) {
3978- errno = ENOMEM;
3979- goto out_zero;
3980- }
3981- memset(repl, 0, sizeof(*repl) + new_size);
3982-
3983-#if 0
3984- TC_DUMP_ENTRIES(*handle);
3985-#endif
3986-
3987- counterlen = sizeof(STRUCT_COUNTERS_INFO)
3988- + sizeof(STRUCT_COUNTERS) * new_number;
3989-
3990- /* These are the old counters we will get from kernel */
3991- repl->counters = malloc(sizeof(STRUCT_COUNTERS)
3992- * (*handle)->info.num_entries);
3993- if (!repl->counters) {
3994- errno = ENOMEM;
3995- goto out_free_repl;
3996- }
3997- /* These are the counters we're going to put back, later. */
3998- newcounters = malloc(counterlen);
3999- if (!newcounters) {
4000- errno = ENOMEM;
4001- goto out_free_repl_counters;
4002- }
4003- memset(newcounters, 0, counterlen);
4004-
4005- strcpy(repl->name, (*handle)->info.name);
4006- repl->num_entries = new_number;
4007- repl->size = new_size;
4008-
4009- repl->num_counters = (*handle)->info.num_entries;
4010- repl->valid_hooks = (*handle)->info.valid_hooks;
4011-
4012- DEBUGP("num_entries=%u, size=%u, num_counters=%u\n",
4013- repl->num_entries, repl->size, repl->num_counters);
4014-
4015- ret = iptcc_compile_table(*handle, repl);
4016- if (ret < 0) {
4017- errno = ret;
4018- goto out_free_newcounters;
4019- }
4020-
4021-
4022-#ifdef IPTC_DEBUG2
4023- {
4024- int fd = open("/tmp/libiptc-so_set_replace.blob",
4025- O_CREAT|O_WRONLY);
4026- if (fd >= 0) {
4027- write(fd, repl, sizeof(*repl) + repl->size);
4028- close(fd);
4029- }
4030- }
4031-#endif
4032-
4033- ret = setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl,
4034- sizeof(*repl) + repl->size);
4035- if (ret < 0)
4036- goto out_free_newcounters;
4037-
4038- /* Put counters back. */
4039- strcpy(newcounters->name, (*handle)->info.name);
4040- newcounters->num_counters = new_number;
4041-
4042- list_for_each_entry(c, &(*handle)->chains, list) {
4043- struct rule_head *r;
4044-
4045- /* Builtin chains have their own counters */
4046- if (iptcc_is_builtin(c)) {
4047- DEBUGP("counter for chain-index %u: ", c->foot_index);
4048- switch(c->counter_map.maptype) {
4049- case COUNTER_MAP_NOMAP:
4050- counters_nomap(newcounters, c->foot_index);
4051- break;
4052- case COUNTER_MAP_NORMAL_MAP:
4053- counters_normal_map(newcounters, repl,
4054- c->foot_index,
4055- c->counter_map.mappos);
4056- break;
4057- case COUNTER_MAP_ZEROED:
4058- counters_map_zeroed(newcounters, repl,
4059- c->foot_index,
4060- c->counter_map.mappos,
4061- &c->counters);
4062- break;
4063- case COUNTER_MAP_SET:
4064- counters_map_set(newcounters, c->foot_index,
4065- &c->counters);
4066- break;
4067- }
4068- }
4069-
4070- list_for_each_entry(r, &c->rules, list) {
4071- DEBUGP("counter for index %u: ", r->index);
4072- switch (r->counter_map.maptype) {
4073- case COUNTER_MAP_NOMAP:
4074- counters_nomap(newcounters, r->index);
4075- break;
4076-
4077- case COUNTER_MAP_NORMAL_MAP:
4078- counters_normal_map(newcounters, repl,
4079- r->index,
4080- r->counter_map.mappos);
4081- break;
4082-
4083- case COUNTER_MAP_ZEROED:
4084- counters_map_zeroed(newcounters, repl,
4085- r->index,