summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty@linuxcare.com.au>2000-05-02 16:45:16 +0000
committerRusty Russell <rusty@rustcorp.com.au>2000-05-02 16:45:16 +0000
commit79dee0702b18c8ea1d1f7a2b1f6b29349466986b (patch)
treed137896a13b5d5ca59461b78b4e1abe7b231f334
parent52a5149d58d027168b86855106f975a2364e7505 (diff)
IPv6 enhancements.
-rw-r--r--include/ip6tables.h107
-rw-r--r--include/iptables.h28
-rw-r--r--include/iptables_common.h18
-rw-r--r--include/libiptc/libip6tc.h133
-rw-r--r--libiptc/Makefile3
-rw-r--r--libiptc/libip4tc.c444
-rw-r--r--libiptc/libip6tc.c264
-rw-r--r--libiptc/libiptc.c883
8 files changed, 1246 insertions, 634 deletions
diff --git a/include/ip6tables.h b/include/ip6tables.h
new file mode 100644
index 00000000..7acf800b
--- /dev/null
+++ b/include/ip6tables.h
@@ -0,0 +1,107 @@
+#ifndef _IP6TABLES_USER_H
+#define _IP6TABLES_USER_H
+
+#include "iptables_common.h"
+#include "libiptc/libip6tc.h"
+
+/* Include file for additions: new matches and targets. */
+struct ip6tables_match
+{
+ struct ip6tables_match *next;
+
+ ip6t_chainlabel name;
+
+ const char *version;
+
+ /* Size of match data. */
+ size_t size;
+
+ /* Function which prints out usage message. */
+ void (*help)(void);
+
+ /* Initialize the match. */
+ void (*init)(struct ip6t_entry_match *m, unsigned int *nfcache);
+
+ /* Function which parses command options; returns true if it
+ ate an option */
+ int (*parse)(int c, char **argv, int invert, unsigned int *flags,
+ const struct ip6t_entry *entry,
+ unsigned int *nfcache,
+ struct ip6t_entry_match **match);
+
+ /* Final check; exit if not ok. */
+ void (*final_check)(unsigned int flags);
+
+ /* Prints out the match iff non-NULL: put space at end */
+ void (*print)(const struct ip6t_ip6 *ip,
+ const struct ip6t_entry_match *match, int numeric);
+
+ /* Saves the union ipt_matchinfo in parsable form to stdout. */
+ void (*save)(const struct ip6t_ip6 *ip,
+ const struct ip6t_entry_match *match);
+
+ /* Pointer to list of extra command-line options */
+ struct option *extra_opts;
+
+ /* Ignore these men behind the curtain: */
+ unsigned int option_offset;
+ struct ip6t_entry_match *m;
+ unsigned int mflags;
+};
+
+struct ip6tables_target
+{
+ struct ip6tables_target *next;
+
+ ip6t_chainlabel name;
+
+ const char *version;
+
+ /* Size of target data. */
+ size_t size;
+
+ /* Function which prints out usage message. */
+ void (*help)(void);
+
+ /* Initialize the target. */
+ void (*init)(struct ip6t_entry_target *t, unsigned int *nfcache);
+
+ /* Function which parses command options; returns true if it
+ ate an option */
+ int (*parse)(int c, char **argv, int invert, unsigned int *flags,
+ const struct ip6t_entry *entry,
+ struct ip6t_entry_target **target);
+
+ /* Final check; exit if not ok. */
+ void (*final_check)(unsigned int flags);
+
+ /* Prints out the target iff non-NULL: put space at end */
+ void (*print)(const struct ip6t_ip6 *ip,
+ const struct ip6t_entry_target *target, int numeric);
+
+ /* Saves the targinfo in parsable form to stdout. */
+ void (*save)(const struct ip6t_ip6 *ip,
+ const struct ip6t_entry_target *target);
+
+ /* Pointer to list of extra command-line options */
+ struct option *extra_opts;
+
+ /* Ignore these men behind the curtain: */
+ unsigned int option_offset;
+ struct ip6t_entry_target *t;
+ unsigned int tflags;
+};
+
+/* Your shared library should call one of these. */
+extern void register_match6(struct ip6tables_match *me);
+extern void register_target6(struct ip6tables_target *me);
+
+extern int do_command6(int argc, char *argv[], char **table,
+ ip6tc_handle_t *handle);
+/* Keeping track of external matches and targets: linked lists. */
+extern struct ip6tables_match *ip6tables_matches;
+extern struct ip6tables_target *ip6tables_targets;
+
+extern struct ip6tables_target *find_target6(const char *name, int tryload);
+extern struct ip6tables_match *find_match6(const char *name, int tryload);
+#endif /*_IP6TABLES_USER_H*/
diff --git a/include/iptables.h b/include/iptables.h
index 1ddd8712..886d576b 100644
--- a/include/iptables.h
+++ b/include/iptables.h
@@ -1,6 +1,7 @@
#ifndef _IPTABLES_USER_H
#define _IPTABLES_USER_H
+#include "iptables_common.h"
#include "libiptc/libiptc.h"
/* Include file for additions: new matches and targets. */
@@ -38,7 +39,7 @@ struct iptables_match
void (*print)(const struct ipt_ip *ip,
const struct ipt_entry_match *match, int numeric);
- /* Saves the union ipt_matchinfo in parsable form to stdout. */
+ /* Saves the match info in parsable form to stdout. */
void (*save)(const struct ipt_ip *ip,
const struct ipt_entry_match *match);
@@ -101,21 +102,8 @@ struct iptables_target
extern void register_match(struct iptables_match *me);
extern void register_target(struct iptables_target *me);
-/* Functions we share */
-enum exittype {
- OTHER_PROBLEM = 1,
- PARAMETER_PROBLEM,
- VERSION_PROBLEM
-};
-extern void exit_printhelp() __attribute__((noreturn));
-extern void exit_tryhelp(int) __attribute__((noreturn));
-int check_inverse(const char option[], int *invert);
-extern int string_to_number(const char *, int, int);
-void exit_error(enum exittype, char *, ...)__attribute__((noreturn,
- format(printf,2,3)));
+extern struct in_addr *dotted_to_addr(const char *dotted);
extern char *addr_to_dotted(const struct in_addr *addrp);
-struct in_addr *dotted_to_addr(const char *dotted);
-extern const char *program_name, *program_version;
extern int do_command(int argc, char *argv[], char **table,
iptc_handle_t *handle);
@@ -123,6 +111,12 @@ extern int do_command(int argc, char *argv[], char **table,
extern struct iptables_match *iptables_matches;
extern struct iptables_target *iptables_targets;
-extern struct iptables_target *find_target(const char *name, int tryload);
-extern struct iptables_match *find_match(const char *name, int tryload);
+enum ipt_tryload {
+ DONT_LOAD,
+ TRY_LOAD,
+ LOAD_MUST_SUCCEED
+};
+
+extern struct iptables_target *find_target(const char *name, enum ipt_tryload);
+extern struct iptables_match *find_match(const char *name, enum ipt_tryload);
#endif /*_IPTABLES_USER_H*/
diff --git a/include/iptables_common.h b/include/iptables_common.h
new file mode 100644
index 00000000..90ca74d7
--- /dev/null
+++ b/include/iptables_common.h
@@ -0,0 +1,18 @@
+#ifndef _IPTABLES_COMMON_H
+#define _IPTABLES_COMMON_H
+/* Shared definitions between ipv4 and ipv6. */
+
+enum exittype {
+ OTHER_PROBLEM = 1,
+ PARAMETER_PROBLEM,
+ VERSION_PROBLEM
+};
+extern void exit_printhelp() __attribute__((noreturn));
+extern void exit_tryhelp(int) __attribute__((noreturn));
+int check_inverse(const char option[], int *invert);
+extern int string_to_number(const char *, int, int);
+void exit_error(enum exittype, char *, ...)__attribute__((noreturn,
+ format(printf,2,3)));
+extern const char *program_name, *program_version;
+
+#endif /*_IPTABLES_COMMON_H*/
diff --git a/include/libiptc/libip6tc.h b/include/libiptc/libip6tc.h
new file mode 100644
index 00000000..d0b87bdf
--- /dev/null
+++ b/include/libiptc/libip6tc.h
@@ -0,0 +1,133 @@
+#ifndef _LIBIP6TC_H
+#define _LIBIP6TC_H
+/* Library which manipulates firewall rules. Version 0.2. */
+
+#include <libiptc/ipt_kernel_headers.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+#ifndef IP6T_MIN_ALIGN
+#define IP6T_MIN_ALIGN (__alignof__(struct ip6t_entry_match))
+#endif
+#define IP6T_ALIGN(s) (((s) + (IP6T_MIN_ALIGN-1)) & ~(IP6T_MIN_ALIGN-1))
+
+typedef char ip6t_chainlabel[32];
+
+#define IP6TC_LABEL_ACCEPT "ACCEPT"
+#define IP6TC_LABEL_DROP "DROP"
+#define IP6TC_LABEL_RETURN "RETURN"
+
+/* Transparent handle type. */
+typedef struct ip6tc_handle *ip6tc_handle_t;
+
+/* Does this chain exist? */
+int ip6tc_is_chain(const char *chain, const ip6tc_handle_t handle);
+
+/* Take a snapshot of the rules. Returns NULL on error. */
+ip6tc_handle_t ip6tc_init(const char *tablename);
+
+/* Iterator functions to run through the chains; prev = NULL means
+ first chain. Returns NULL at end. */
+const char *ip6tc_next_chain(const char *prev, ip6tc_handle_t *handle);
+
+/* How many rules in this chain? */
+unsigned int ip6tc_num_rules(const char *chain, ip6tc_handle_t *handle);
+
+/* Get n'th rule in this chain. */
+const struct ip6t_entry *ip6tc_get_rule(const char *chain,
+ unsigned int n,
+ ip6tc_handle_t *handle);
+
+/* Returns a pointer to the target name of this position. */
+const char *ip6tc_get_target(const char *chain,
+ unsigned int n,
+ ip6tc_handle_t *handle);
+
+/* Is this a built-in chain? */
+int ip6tc_builtin(const char *chain, const ip6tc_handle_t handle);
+
+/* Get the policy of a given built-in chain */
+const char *ip6tc_get_policy(const char *chain,
+ struct ip6t_counters *counters,
+ ip6tc_handle_t *handle);
+
+/* These functions return TRUE for OK or 0 and set errno. If errno ==
+ 0, it means there was a version error (ie. upgrade libiptc). */
+/* Rule numbers start at 1 for the first rule. */
+
+/* Insert the entry `fw' in chain `chain' into position `rulenum'. */
+int ip6tc_insert_entry(const ip6t_chainlabel chain,
+ const struct ip6t_entry *e,
+ unsigned int rulenum,
+ ip6tc_handle_t *handle);
+
+/* Atomically replace rule `rulenum' in `chain' with `fw'. */
+int ip6tc_replace_entry(const ip6t_chainlabel chain,
+ const struct ip6t_entry *e,
+ unsigned int rulenum,
+ ip6tc_handle_t *handle);
+
+/* Append entry `fw' to chain `chain'. Equivalent to insert with
+ rulenum = length of chain. */
+int ip6tc_append_entry(const ip6t_chainlabel chain,
+ const struct ip6t_entry *e,
+ ip6tc_handle_t *handle);
+
+/* Delete the first rule in `chain' which matches `fw'. */
+int ip6tc_delete_entry(const ip6t_chainlabel chain,
+ const struct ip6t_entry *origfw,
+ ip6tc_handle_t *handle);
+
+/* Delete the rule in position `rulenum' in `chain'. */
+int ip6tc_delete_num_entry(const ip6t_chainlabel chain,
+ unsigned int rulenum,
+ ip6tc_handle_t *handle);
+
+/* Check the packet `fw' on chain `chain'. Returns the verdict, or
+ NULL and sets errno. */
+const char *ip6tc_check_packet(const ip6t_chainlabel chain,
+ struct ip6t_entry *,
+ ip6tc_handle_t *handle);
+
+/* Flushes the entries in the given chain (ie. empties chain). */
+int ip6tc_flush_entries(const ip6t_chainlabel chain,
+ ip6tc_handle_t *handle);
+
+/* Zeroes the counters in a chain. */
+int ip6tc_zero_entries(const ip6t_chainlabel chain,
+ ip6tc_handle_t *handle);
+
+/* Creates a new chain. */
+int ip6tc_create_chain(const ip6t_chainlabel chain,
+ ip6tc_handle_t *handle);
+
+/* Deletes a chain. */
+int ip6tc_delete_chain(const ip6t_chainlabel chain,
+ ip6tc_handle_t *handle);
+
+/* Renames a chain. */
+int ip6tc_rename_chain(const ip6t_chainlabel oldname,
+ const ip6t_chainlabel newname,
+ ip6tc_handle_t *handle);
+
+/* Sets the policy on a built-in chain. */
+int ip6tc_set_policy(const ip6t_chainlabel chain,
+ const ip6t_chainlabel policy,
+ ip6tc_handle_t *handle);
+
+/* Get the number of references to this chain */
+int ip6tc_get_references(unsigned int *ref, const ip6t_chainlabel chain,
+ ip6tc_handle_t *handle);
+
+/* Makes the actual changes. */
+int ip6tc_commit(ip6tc_handle_t *handle);
+
+/* Get raw socket. */
+int ip6tc_get_raw_socket();
+
+/* Translates errno numbers into more human-readable form than strerror. */
+const char *ip6tc_strerror(int err);
+
+/* Return prefix length, or -1 if not contiguous */
+int ipv6_prefix_length(const struct in6_addr *a);
+
+#endif /* _LIBIP6TC_H */
diff --git a/libiptc/Makefile b/libiptc/Makefile
index c47669f5..7c0ff5e5 100644
--- a/libiptc/Makefile
+++ b/libiptc/Makefile
@@ -9,7 +9,8 @@ local:
else
EXTRA_DEPENDS+=libiptc/libiptc.d
-libiptc/libiptc.a: libiptc/libiptc.a(libiptc/libiptc.o)
+#libiptc/libiptc.a: libiptc/libiptc.a(libiptc/libip4tc.o libiptc/libip6tc.o)
+libiptc/libiptc.a: libiptc/libiptc.a(libiptc/libip4tc.o)
libiptc/libiptc.d: %.d: %.c
@-$(CC) -M -MG $(CFLAGS) $< | sed -e 's@^.*\.o:@$*.d $*.a($*.o):@' > $@
diff --git a/libiptc/libip4tc.c b/libiptc/libip4tc.c
new file mode 100644
index 00000000..10ea1be2
--- /dev/null
+++ b/libiptc/libip4tc.c
@@ -0,0 +1,444 @@
+/* Library which manipulates firewall rules. Version 0.1. */
+
+/* Architecture of firewall rules is as follows:
+ *
+ * Chains go INPUT, FORWARD, OUTPUT then user chains.
+ * Each user chain starts with an ERROR node.
+ * Every chain ends with an unconditional jump: a RETURN for user chains,
+ * and a POLICY for built-ins.
+ */
+
+/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
+ COPYING for details). */
+
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef DEBUG_CONNTRACK
+#define inline
+#endif
+
+#if !defined(__GLIBC__) || (__GLIBC__ < 2)
+typedef unsigned int socklen_t;
+#endif
+
+#include "libiptc/libiptc.h"
+
+#define IP_VERSION 4
+#define IP_OFFSET 0x1FFF
+
+#define HOOK_PRE_ROUTING NF_IP_PRE_ROUTING
+#define HOOK_LOCAL_IN NF_IP_LOCAL_IN
+#define HOOK_FORWARD NF_IP_FORWARD
+#define HOOK_LOCAL_OUT NF_IP_LOCAL_OUT
+#define HOOK_POST_ROUTING NF_IP_POST_ROUTING
+
+#define STRUCT_ENTRY_TARGET struct ipt_entry_target
+#define STRUCT_ENTRY struct ipt_entry
+#define STRUCT_ENTRY_MATCH struct ipt_entry_match
+#define STRUCT_GETINFO struct ipt_getinfo
+#define STRUCT_GET_ENTRIES struct ipt_get_entries
+#define STRUCT_COUNTERS struct ipt_counters
+#define STRUCT_COUNTERS_INFO struct ipt_counters_info
+#define STRUCT_STANDARD_TARGET struct ipt_standard_target
+#define STRUCT_REPLACE struct ipt_replace
+
+#define STRUCT_TC_HANDLE struct iptc_handle
+#define TC_HANDLE_T iptc_handle_t
+
+#define ENTRY_ITERATE IPT_ENTRY_ITERATE
+#define TABLE_MAXNAMELEN IPT_TABLE_MAXNAMELEN
+#define FUNCTION_MAXNAMELEN IPT_FUNCTION_MAXNAMELEN
+
+#define GET_TARGET ipt_get_target
+
+#define ERROR_TARGET IPT_ERROR_TARGET
+#define NUMHOOKS NF_IP_NUMHOOKS
+
+#define IPT_CHAINLABEL ipt_chainlabel
+
+#define TC_DUMP_ENTRIES dump_entries
+#define TC_IS_CHAIN iptc_is_chain
+#define TC_NEXT_CHAIN iptc_next_chain
+#define TC_NUM_RULES iptc_num_rules
+#define TC_GET_RULE iptc_get_rule
+#define TC_GET_TARGET iptc_get_target
+#define TC_BUILTIN iptc_builtin
+#define TC_GET_POLICY iptc_get_policy
+#define TC_INSERT_ENTRY iptc_insert_entry
+#define TC_REPLACE_ENTRY iptc_replace_entry
+#define TC_APPEND_ENTRY iptc_append_entry
+#define TC_DELETE_ENTRY iptc_delete_entry
+#define TC_DELETE_NUM_ENTRY iptc_delete_num_entry
+#define TC_CHECK_PACKET iptc_check_packet
+#define TC_FLUSH_ENTRIES iptc_flush_entries
+#define TC_ZERO_ENTRIES iptc_zero_entries
+#define TC_CREATE_CHAIN iptc_create_chain
+#define TC_GET_REFERENCES iptc_get_references
+#define TC_DELETE_CHAIN iptc_delete_chain
+#define TC_RENAME_CHAIN iptc_rename_chain
+#define TC_SET_POLICY iptc_set_policy
+#define TC_GET_RAW_SOCKET iptc_get_raw_socket
+#define TC_INIT iptc_init
+#define TC_COMMIT iptc_commit
+#define TC_STRERROR iptc_strerror
+
+#define TC_AF AF_INET
+#define TC_IPPROTO IPPROTO_IP
+
+#define SO_SET_REPLACE IPT_SO_SET_REPLACE
+#define SO_SET_ADD_COUNTERS IPT_SO_SET_ADD_COUNTERS
+#define SO_GET_INFO IPT_SO_GET_INFO
+#define SO_GET_ENTRIES IPT_SO_GET_ENTRIES
+#define SO_GET_VERSION IPT_SO_GET_VERSION
+
+#define STANDARD_TARGET IPT_STANDARD_TARGET
+#define LABEL_RETURN IPTC_LABEL_RETURN
+#define LABEL_ACCEPT IPTC_LABEL_ACCEPT
+#define LABEL_DROP IPTC_LABEL_DROP
+
+#define ALIGN IPT_ALIGN
+#define RETURN IPT_RETURN
+
+#include "libiptc.c"
+
+#define IP_PARTS_NATIVE(n) \
+(unsigned int)((n)>>24)&0xFF, \
+(unsigned int)((n)>>16)&0xFF, \
+(unsigned int)((n)>>8)&0xFF, \
+(unsigned int)((n)&0xFF)
+
+#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n))
+
+int
+dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle)
+{
+ size_t i;
+ STRUCT_ENTRY_TARGET *t;
+
+ printf("Entry %u (%lu):\n", entry2index(handle, e),
+ entry2offset(handle, e));
+ printf("SRC IP: %u.%u.%u.%u/%u.%u.%u.%u\n",
+ IP_PARTS(e->ip.src.s_addr),IP_PARTS(e->ip.smsk.s_addr));
+ printf("DST IP: %u.%u.%u.%u/%u.%u.%u.%u\n",
+ IP_PARTS(e->ip.dst.s_addr),IP_PARTS(e->ip.dmsk.s_addr));
+ printf("Interface: `%s'/", e->ip.iniface);
+ for (i = 0; i < IFNAMSIZ; i++)
+ printf("%c", e->ip.iniface_mask[i] ? 'X' : '.');
+ printf("to `%s'/", e->ip.outiface);
+ for (i = 0; i < IFNAMSIZ; i++)
+ printf("%c", e->ip.outiface_mask[i] ? 'X' : '.');
+ printf("\nProtocol: %u\n", e->ip.proto);
+ printf("Flags: %02X\n", e->ip.flags);
+ printf("Invflags: %02X\n", e->ip.invflags);
+ printf("Counters: %llu packets, %llu bytes\n",
+ e->counters.pcnt, e->counters.bcnt);
+ printf("Cache: %08X ", e->nfcache);
+ if (e->nfcache & NFC_ALTERED) printf("ALTERED ");
+ if (e->nfcache & NFC_UNKNOWN) printf("UNKNOWN ");
+ if (e->nfcache & NFC_IP_SRC) printf("IP_SRC ");
+ if (e->nfcache & NFC_IP_DST) printf("IP_DST ");
+ if (e->nfcache & NFC_IP_IF_IN) printf("IP_IF_IN ");
+ if (e->nfcache & NFC_IP_IF_OUT) printf("IP_IF_OUT ");
+ if (e->nfcache & NFC_IP_TOS) printf("IP_TOS ");
+ if (e->nfcache & NFC_IP_PROTO) printf("IP_PROTO ");
+ if (e->nfcache & NFC_IP_OPTIONS) printf("IP_OPTIONS ");
+ if (e->nfcache & NFC_IP_TCPFLAGS) printf("IP_TCPFLAGS ");
+ if (e->nfcache & NFC_IP_SRC_PT) printf("IP_SRC_PT ");
+ if (e->nfcache & NFC_IP_DST_PT) printf("IP_DST_PT ");
+ if (e->nfcache & NFC_IP_PROTO_UNKNOWN) printf("IP_PROTO_UNKNOWN ");
+ printf("\n");
+
+ IPT_MATCH_ITERATE(e, print_match);
+
+ t = GET_TARGET(e);
+ printf("Target name: `%s' [%u]\n", t->u.user.name, t->u.target_size);
+ if (strcmp(t->u.user.name, STANDARD_TARGET) == 0) {
+ int pos = *(int *)t->data;
+ if (pos < 0)
+ printf("verdict=%s\n",
+ pos == -NF_ACCEPT-1 ? "NF_ACCEPT"
+ : pos == -NF_DROP-1 ? "NF_DROP"
+ : pos == -NF_QUEUE-1 ? "NF_QUEUE"
+ : pos == RETURN ? "RETURN"
+ : "UNKNOWN");
+ else
+ printf("verdict=%u\n", pos);
+ } else if (strcmp(t->u.user.name, IPT_ERROR_TARGET) == 0)
+ printf("error=`%s'\n", t->data);
+
+ printf("\n");
+ return 0;
+}
+
+static int
+is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b, unsigned char *matchmask)
+{
+ unsigned int i;
+ STRUCT_ENTRY_TARGET *ta, *tb;
+ unsigned char *mptr;
+
+ /* Always compare head structures: ignore mask here. */
+ if (a->ip.src.s_addr != b->ip.src.s_addr
+ || a->ip.dst.s_addr != b->ip.dst.s_addr
+ || a->ip.smsk.s_addr != b->ip.smsk.s_addr
+ || a->ip.smsk.s_addr != b->ip.smsk.s_addr
+ || a->ip.proto != b->ip.proto
+ || a->ip.flags != b->ip.flags
+ || a->ip.invflags != b->ip.invflags)
+ return 0;
+
+ for (i = 0; i < IFNAMSIZ; i++) {
+ if (a->ip.iniface_mask[i] != b->ip.iniface_mask[i])
+ return 0;
+ if ((a->ip.iniface[i] & a->ip.iniface_mask[i])
+ != (b->ip.iniface[i] & b->ip.iniface_mask[i]))
+ return 0;
+ if (a->ip.outiface_mask[i] != b->ip.outiface_mask[i])
+ return 0;
+ if ((a->ip.outiface[i] & a->ip.outiface_mask[i])
+ != (b->ip.outiface[i] & b->ip.outiface_mask[i]))
+ return 0;
+ }
+
+ if (a->nfcache != b->nfcache
+ || a->target_offset != b->target_offset
+ || a->next_offset != b->next_offset)
+ return 0;
+
+ mptr = matchmask + sizeof(STRUCT_ENTRY);
+ if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
+ return 0;
+
+ ta = GET_TARGET((STRUCT_ENTRY *)a);
+ tb = GET_TARGET((STRUCT_ENTRY *)b);
+ if (ta->u.target_size != tb->u.target_size)
+ return 0;
+ if (strcmp(ta->u.user.name, tb->u.user.name) != 0)
+ return 0;
+
+ mptr += sizeof(*ta);
+ if (target_different(ta->data, tb->data,
+ ta->u.target_size - sizeof(*ta), mptr))
+ return 0;
+
+ return 1;
+}
+
+/***************************** DEBUGGING ********************************/
+static inline int
+unconditional(const struct ipt_ip *ip)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(*ip)/sizeof(u_int32_t); i++)
+ if (((u_int32_t *)ip)[i])
+ return 0;
+
+ return 1;
+}
+
+static inline int
+check_match(const STRUCT_ENTRY_MATCH *m, unsigned int *off)
+{
+ assert(m->u.match_size >= sizeof(STRUCT_ENTRY_MATCH));
+ assert(ALIGN(m->u.match_size) == m->u.match_size);
+
+ (*off) += m->u.match_size;
+ return 0;
+}
+
+static inline int
+check_entry(const STRUCT_ENTRY *e, unsigned int *i, unsigned int *off,
+ unsigned int user_offset, int *was_return,
+ TC_HANDLE_T h)
+{
+ unsigned int toff;
+ STRUCT_STANDARD_TARGET *t;
+
+ assert(e->target_offset >= sizeof(STRUCT_ENTRY));
+ assert(e->next_offset >= e->target_offset
+ + sizeof(STRUCT_ENTRY_TARGET));
+ toff = sizeof(STRUCT_ENTRY);
+ IPT_MATCH_ITERATE(e, check_match, &toff);
+
+ assert(toff == e->target_offset);
+
+ t = (STRUCT_STANDARD_TARGET *)
+ GET_TARGET((STRUCT_ENTRY *)e);
+ /* next_offset will have to be multiple of entry alignment. */
+ assert(e->next_offset == ALIGN(e->next_offset));
+ assert(e->target_offset == ALIGN(e->target_offset));
+ assert(t->target.u.target_size == ALIGN(t->target.u.target_size));
+ assert(!TC_IS_CHAIN(t->target.u.user.name, h));
+
+ if (strcmp(t->target.u.user.name, STANDARD_TARGET) == 0) {
+ assert(t->target.u.target_size
+ == ALIGN(sizeof(STRUCT_STANDARD_TARGET)));
+
+ assert(t->verdict == -NF_DROP-1
+ || t->verdict == -NF_ACCEPT-1
+ || t->verdict == RETURN
+ || t->verdict < (int)h->entries.size);
+
+ if (t->verdict >= 0) {
+ STRUCT_ENTRY *te = get_entry(h, t->verdict);
+ int idx;
+
+ idx = entry2index(h, te);
+ assert(strcmp(GET_TARGET(te)->u.user.name,
+ IPT_ERROR_TARGET)
+ != 0);
+ assert(te != e);
+
+ /* Prior node must be error node, or this node. */
+ assert(t->verdict == entry2offset(h, e)+e->next_offset
+ || strcmp(GET_TARGET(index2entry(h, idx-1))
+ ->u.user.name, IPT_ERROR_TARGET)
+ == 0);
+ }
+
+ if (t->verdict == RETURN
+ && unconditional(&e->ip)
+ && e->target_offset == sizeof(*e))
+ *was_return = 1;
+ else
+ *was_return = 0;
+ } else if (strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0) {
+ assert(t->target.u.target_size
+ == ALIGN(sizeof(struct ipt_error_target)));
+
+ /* If this is in user area, previous must have been return */
+ if (*off > user_offset)
+ assert(*was_return);
+
+ *was_return = 0;
+ }
+ else *was_return = 0;
+
+ if (*off == user_offset)
+ assert(strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0);
+
+ (*off) += e->next_offset;
+ (*i)++;
+ return 0;
+}
+
+#ifndef NDEBUG
+/* Do every conceivable sanity check on the handle */
+static void
+do_check(TC_HANDLE_T h, unsigned int line)
+{
+ unsigned int i, n;
+ unsigned int user_offset; /* Offset of first user chain */
+ int was_return;
+
+ assert(h->changed == 0 || h->changed == 1);
+ if (strcmp(h->info.name, "filter") == 0) {
+ assert(h->info.valid_hooks
+ == (1 << NF_IP_LOCAL_IN
+ | 1 << NF_IP_FORWARD
+ | 1 << NF_IP_LOCAL_OUT));
+
+ /* Hooks should be first three */
+ assert(h->info.hook_entry[NF_IP_LOCAL_IN] == 0);
+
+ n = get_chain_end(h, 0);
+ n += get_entry(h, n)->next_offset;
+ assert(h->info.hook_entry[NF_IP_FORWARD] == n);
+
+ n = get_chain_end(h, n);
+ n += get_entry(h, n)->next_offset;
+ assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
+
+ user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
+ } else if (strcmp(h->info.name, "nat") == 0) {
+ assert(h->info.valid_hooks
+ == (1 << NF_IP_PRE_ROUTING
+ | 1 << NF_IP_POST_ROUTING
+ | 1 << NF_IP_LOCAL_OUT));
+
+ assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0);
+
+ n = get_chain_end(h, 0);
+ n += get_entry(h, n)->next_offset;
+ assert(h->info.hook_entry[NF_IP_POST_ROUTING] == n);
+
+ n = get_chain_end(h, n);
+ n += get_entry(h, n)->next_offset;
+ assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
+
+ user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
+ } else if (strcmp(h->info.name, "mangle") == 0) {
+ assert(h->info.valid_hooks
+ == (1 << NF_IP_PRE_ROUTING
+ | 1 << NF_IP_LOCAL_OUT));
+
+ /* Hooks should be first three */
+ assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0);
+
+ n = get_chain_end(h, 0);
+ n += get_entry(h, n)->next_offset;
+ assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
+
+ user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
+ } else
+ abort();
+
+ /* User chain == end of last builtin + policy entry */
+ user_offset = get_chain_end(h, user_offset);
+ user_offset += get_entry(h, user_offset)->next_offset;
+
+ /* Overflows should be end of entry chains, and unconditional
+ policy nodes. */
+ for (i = 0; i < NUMHOOKS; i++) {
+ STRUCT_ENTRY *e;
+ STRUCT_STANDARD_TARGET *t;
+
+ if (!(h->info.valid_hooks & (1 << i)))
+ continue;
+ assert(h->info.underflow[i]
+ == get_chain_end(h, h->info.hook_entry[i]));
+
+ e = get_entry(h, get_chain_end(h, h->info.hook_entry[i]));
+ assert(unconditional(&e->ip));
+ assert(e->target_offset == sizeof(*e));
+ assert(e->next_offset == sizeof(*e) + sizeof(*t));
+ t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
+
+ assert(strcmp(t->target.u.user.name, STANDARD_TARGET)==0);
+ assert(t->verdict == -NF_DROP-1 || t->verdict == -NF_ACCEPT-1);
+
+ /* Hooks and underflows must be valid entries */
+ entry2index(h, get_entry(h, h->info.hook_entry[i]));
+ entry2index(h, get_entry(h, h->info.underflow[i]));
+ }
+
+ assert(h->info.size
+ >= h->info.num_entries * (sizeof(STRUCT_ENTRY)
+ +sizeof(STRUCT_STANDARD_TARGET)));
+
+ assert(h->entries.size
+ >= (h->new_number
+ * (sizeof(STRUCT_ENTRY)
+ + sizeof(STRUCT_STANDARD_TARGET))));
+ assert(strcmp(h->info.name, h->entries.name) == 0);
+
+ i = 0; n = 0;
+ was_return = 0;
+ /* Check all the entries. */
+ ENTRY_ITERATE(h->entries.entries, h->entries.size,
+ check_entry, &i, &n, user_offset, &was_return, h);
+
+ assert(i == h->new_number);
+ assert(n == h->entries.size);
+
+ /* Final entry must be error node */
+ assert(strcmp(GET_TARGET(index2entry(h, h->new_number-1))
+ ->u.user.name,
+ IPT_ERROR_TARGET) == 0);
+}
+#endif /*NDEBUG*/
diff --git a/libiptc/libip6tc.c b/libiptc/libip6tc.c
new file mode 100644
index 00000000..033693ff
--- /dev/null
+++ b/libiptc/libip6tc.c
@@ -0,0 +1,264 @@
+/* Library which manipulates firewall rules. Version 0.1. */
+
+/* Architecture of firewall rules is as follows:
+ *
+ * Chains go INPUT, FORWARD, OUTPUT then user chains.
+ * Each user chain starts with an ERROR node.
+ * Every chain ends with an unconditional jump: a RETURN for user chains,
+ * and a POLICY for built-ins.
+ */
+
+/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
+ COPYING for details). */
+
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <arpa/inet.h>
+
+#ifdef DEBUG_CONNTRACK
+#define inline
+#endif
+
+#if !defined(__GLIBC__) || (__GLIBC__ < 2)
+typedef unsigned int socklen_t;
+#endif
+
+#include "libiptc/libip6tc.h"
+
+#define HOOK_PRE_ROUTING NF_IP6_PRE_ROUTING
+#define HOOK_LOCAL_IN NF_IP6_LOCAL_IN
+#define HOOK_FORWARD NF_IP6_FORWARD
+#define HOOK_LOCAL_OUT NF_IP6_LOCAL_OUT
+#define HOOK_POST_ROUTING NF_IP6_POST_ROUTING
+
+#define STRUCT_ENTRY_TARGET struct ip6t_entry_target
+#define STRUCT_ENTRY struct ip6t_entry
+#define STRUCT_ENTRY_MATCH struct ip6t_entry_match
+#define STRUCT_GETINFO struct ip6t_getinfo
+#define STRUCT_GET_ENTRIES struct ip6t_get_entries
+#define STRUCT_COUNTERS struct ip6t_counters
+#define STRUCT_COUNTERS_INFO struct ip6t_counters_info
+#define STRUCT_STANDARD_TARGET struct ip6t_standard_target
+#define STRUCT_REPLACE struct ip6t_replace
+
+#define STRUCT_TC_HANDLE struct ip6tc_handle
+#define TC_HANDLE_T ip6tc_handle_t
+
+#define ENTRY_ITERATE IP6T_ENTRY_ITERATE
+#define TABLE_MAXNAMELEN IP6T_TABLE_MAXNAMELEN
+#define FUNCTION_MAXNAMELEN IP6T_FUNCTION_MAXNAMELEN
+
+#define GET_TARGET ip6t_get_target
+
+#define ERROR_TARGET IP6T_ERROR_TARGET
+#define NUMHOOKS NF_IP6_NUMHOOKS
+
+#define IPT_CHAINLABEL ip6t_chainlabel
+
+#define TC_DUMP_ENTRIES dump_entries6
+#define TC_IS_CHAIN ip6tc_is_chain
+#define TC_NEXT_CHAIN ip6tc_next_chain
+#define TC_NUM_RULES ip6tc_num_rules
+#define TC_GET_RULE ip6tc_get_rule
+#define TC_GET_TARGET ip6tc_get_target
+#define TC_BUILTIN ip6tc_builtin
+#define TC_GET_POLICY ip6tc_get_policy
+#define TC_INSERT_ENTRY ip6tc_insert_entry
+#define TC_REPLACE_ENTRY ip6tc_replace_entry
+#define TC_APPEND_ENTRY ip6tc_append_entry
+#define TC_DELETE_ENTRY ip6tc_delete_entry
+#define TC_DELETE_NUM_ENTRY ip6tc_delete_num_entry
+#define TC_CHECK_PACKET ip6tc_check_packet
+#define TC_FLUSH_ENTRIES ip6tc_flush_entries
+#define TC_ZERO_ENTRIES ip6tc_zero_entries
+#define TC_CREATE_CHAIN ip6tc_create_chain
+#define TC_GET_REFERENCES ip6tc_get_references
+#define TC_DELETE_CHAIN ip6tc_delete_chain
+#define TC_RENAME_CHAIN ip6tc_rename_chain
+#define TC_SET_POLICY ip6tc_set_policy
+#define TC_GET_RAW_SOCKET ip6tc_get_raw_socket
+#define TC_INIT ip6tc_init
+#define TC_COMMIT ip6tc_commit
+#define TC_STRERROR ip6tc_strerror
+
+#define TC_AF AF_INET6
+#define TC_IPPROTO IPPROTO_IPV6
+
+#define SO_SET_REPLACE IP6T_SO_SET_REPLACE
+#define SO_SET_ADD_COUNTERS IP6T_SO_SET_ADD_COUNTERS
+#define SO_GET_INFO IP6T_SO_GET_INFO
+#define SO_GET_ENTRIES IP6T_SO_GET_ENTRIES
+#define SO_GET_VERSION IP6T_SO_GET_VERSION
+
+#define STANDARD_TARGET IP6T_STANDARD_TARGET
+#define LABEL_RETURN IP6TC_LABEL_RETURN
+#define LABEL_ACCEPT IP6TC_LABEL_ACCEPT
+#define LABEL_DROP IP6TC_LABEL_DROP
+
+#define ALIGN IP6T_ALIGN
+#define RETURN IP6T_RETURN
+
+#include "libiptc.c"
+
+#define BIT6(a, l) \
+ (((a->in6_u.u6_addr32[(l) / 32]) >> ((l) & 31)) & 1)
+
+int
+ipv6_prefix_length(const struct in6_addr *a)
+{
+ int l, i;
+ for (l = 0; l < 128; l++) {
+ if (BIT6(a, l) == 0)
+ break;
+ }
+ for (i = l + 1; i < 128; i++) {
+ if (BIT6(a, i) == 1)
+ return -1;
+ }
+ return l;
+}
+
+static int
+dump_entry(struct ip6t_entry *e, const ip6tc_handle_t handle)
+{
+ size_t i;
+ char buf[40];
+ int len;
+ struct ip6t_entry_target *t;
+
+ printf("Entry %u (%lu):\n", entry2index(handle, e),
+ entry2offset(handle, e));
+ puts("SRC IP: ");
+ inet_ntop(AF_INET6, &e->ipv6.src, buf, sizeof buf);
+ puts(buf);
+ putchar('/');
+ len = ipv6_prefix_length(&e->ipv6.smsk);
+ if (len != -1)
+ printf("%d", len);
+ else {
+ inet_ntop(AF_INET6, &e->ipv6.smsk, buf, sizeof buf);
+ puts(buf);
+ }
+ putchar('\n');
+
+ puts("DST IP: ");
+ inet_ntop(AF_INET6, &e->ipv6.dst, buf, sizeof buf);
+ puts(buf);
+ putchar('/');
+ len = ipv6_prefix_length(&e->ipv6.dmsk);
+ if (len != -1)
+ printf("%d", len);
+ else {
+ inet_ntop(AF_INET6, &e->ipv6.dmsk, buf, sizeof buf);
+ puts(buf);
+ }
+ putchar('\n');
+
+ printf("Interface: `%s'/", e->ipv6.iniface);
+ for (i = 0; i < IFNAMSIZ; i++)
+ printf("%c", e->ipv6.iniface_mask[i] ? 'X' : '.');
+ printf("to `%s'/", e->ipv6.outiface);
+ for (i = 0; i < IFNAMSIZ; i++)
+ printf("%c", e->ipv6.outiface_mask[i] ? 'X' : '.');
+ printf("\nProtocol: %u\n", e->ipv6.proto);
+ if (e->ipv6.flags & IP6T_F_TOS)
+ printf("TOS: %u\n", e->ipv6.tos);
+ printf("Flags: %02X\n", e->ipv6.flags);
+ printf("Invflags: %02X\n", e->ipv6.invflags);
+ printf("Counters: %llu packets, %llu bytes\n",
+ e->counters.pcnt, e->counters.bcnt);
+ printf("Cache: %08X ", e->nfcache);
+ if (e->nfcache & NFC_ALTERED) printf("ALTERED ");
+ if (e->nfcache & NFC_UNKNOWN) printf("UNKNOWN ");
+ if (e->nfcache & NFC_IP6_SRC) printf("IP6_SRC ");
+ if (e->nfcache & NFC_IP6_DST) printf("IP6_DST ");
+ if (e->nfcache & NFC_IP6_IF_IN) printf("IP6_IF_IN ");
+ if (e->nfcache & NFC_IP6_IF_OUT) printf("IP6_IF_OUT ");
+ if (e->nfcache & NFC_IP6_TOS) printf("IP6_TOS ");
+ if (e->nfcache & NFC_IP6_PROTO) printf("IP6_PROTO ");
+ if (e->nfcache & NFC_IP6_OPTIONS) printf("IP6_OPTIONS ");
+ if (e->nfcache & NFC_IP6_TCPFLAGS) printf("IP6_TCPFLAGS ");
+ if (e->nfcache & NFC_IP6_SRC_PT) printf("IP6_SRC_PT ");
+ if (e->nfcache & NFC_IP6_DST_PT) printf("IP6_DST_PT ");
+ if (e->nfcache & NFC_IP6_PROTO_UNKNOWN) printf("IP6_PROTO_UNKNOWN ");
+ printf("\n");
+
+ IP6T_MATCH_ITERATE(e, print_match);
+
+ t = ip6t_get_target(e);
+ printf("Target name: `%s' [%u]\n", t->u.name, t->target_size);
+ if (strcmp(t->u.name, IP6T_STANDARD_TARGET) == 0) {
+ int pos = *(int *)t->data;
+ if (pos < 0)
+ printf("verdict=%s\n",
+ pos == -NF_ACCEPT-1 ? "NF_ACCEPT"
+ : pos == -NF_DROP-1 ? "NF_DROP"
+ : pos == IP6T_RETURN ? "RETURN"
+ : "UNKNOWN");
+ else
+ printf("verdict=%u\n", pos);
+ } else if (strcmp(t->u.name, IP6T_ERROR_TARGET) == 0)
+ printf("error=`%s'\n", t->data);
+
+ printf("\n");
+ return 0;
+}
+
+static inline int
+is_same(const struct STRUCT_ENTRY *a, const struct STRUCT_ENTRY *b,
+ unsigned char *matchmask)
+{
+ unsigned int i;
+ struct STRUCT_ENTRY_TARGET *ta, *tb;
+ unsigned char *mptr;
+
+ /* Always compare head structures: ignore mask here. */
+ if (memcmp(&a->ipv6.src, &b->ipv6.src, sizeof(struct in6_addr))
+ || memcmp(&a->ipv6.dst, &b->ipv6.dst, sizeof(struct in6_addr))
+ || memcmp(&a->ipv6.smsk, &b->ipv6.smsk, sizeof(struct in6_addr))
+ || memcmp(&a->ipv6.dmsk, &b->ipv6.dmsk, sizeof(struct in6_addr))
+ || a->ipv6.proto != b->ipv6.proto
+ || a->ipv6.tos != b->ipv6.tos
+ || a->ipv6.flags != b->ipv6.flags
+ || a->ipv6.invflags != b->ipv6.invflags)
+ return 0;
+
+ for (i = 0; i < IFNAMSIZ; i++) {
+ if (a->ipv6.iniface_mask[i] != b->ipv6.iniface_mask[i])
+ return 0;
+ if ((a->ipv6.iniface[i] & a->ipv6.iniface_mask[i])
+ != (b->ipv6.iniface[i] & b->ipv6.iniface_mask[i]))
+ return 0;
+ if (a->ipv6.outiface_mask[i] != b->ipv6.outiface_mask[i])
+ return 0;
+ if ((a->ipv6.outiface[i] & a->ipv6.outiface_mask[i])
+ != (b->ipv6.outiface[i] & b->ipv6.outiface_mask[i]))
+ return 0;
+ }
+
+ if (a->nfcache != b->nfcache
+ || a->target_offset != b->target_offset
+ || a->next_offset != b->next_offset)
+ return 0;
+
+ mptr = matchmask + sizeof(struct STRUCT_ENTRY);
+ if (IP6T_MATCH_ITERATE(a, match_different, a->elems, b->elems))
+ return 0;
+
+ ta = GET_TARGET((struct STRUCT_ENTRY *)a);
+ tb = GET_TARGET((struct STRUCT_ENTRY *)b);
+ if (ta->target_size != tb->target_size)
+ return 0;
+ if (strcmp(ta->u.name, tb->u.name) != 0)
+ return 0;
+ mptr += sizeof(*ta);
+
+ if (target_different(ta->data, tb->data,
+ ta->u.target_size - sizeof(*ta), mptr))
+ return 0;
+
+ return 1;
+}
diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c
index 019de66f..56c33049 100644
--- a/libiptc/libiptc.c
+++ b/libiptc/libiptc.c
@@ -11,30 +11,13 @@
/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
COPYING for details). */
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <limits.h>
-
-#if !defined(__GLIBC__) || (__GLIBC__ < 2)
-typedef unsigned int socklen_t;
-#endif
-
-#include <libiptc/libiptc.h>
-#include <linux/netfilter_ipv4/ipt_limit.h>
-
-#define IP_VERSION 4
-#define IP_OFFSET 0x1FFF
-
#ifndef IPT_LIB_DIR
#define IPT_LIB_DIR "/usr/local/lib/iptables"
#endif
#if 0
-static struct ipt_entry_target *
-ipt_get_target(struct ipt_entry *e)
+static STRUCT_ENTRY_TARGET *
+GET_TARGET(STRUCT_ENTRY *e)
{
return (void *)e + e->target_offset;
}
@@ -44,11 +27,11 @@ static int sockfd = -1;
static void *iptc_fn = NULL;
static const char *hooknames[]
-= { [NF_IP_PRE_ROUTING] "PREROUTING",
- [NF_IP_LOCAL_IN] "INPUT",
- [NF_IP_FORWARD] "FORWARD",
- [NF_IP_LOCAL_OUT] "OUTPUT",
- [NF_IP_POST_ROUTING] "POSTROUTING"
+= { [HOOK_PRE_ROUTING] "PREROUTING",
+ [HOOK_LOCAL_IN] "INPUT",
+ [HOOK_FORWARD] "FORWARD",
+ [HOOK_LOCAL_OUT] "OUTPUT",
+ [HOOK_POST_ROUTING] "POSTROUTING"
};
struct counter_map
@@ -64,25 +47,25 @@ struct counter_map
/* Convenience structures */
struct ipt_error_target
{
- struct ipt_entry_target t;
- char error[IPT_TABLE_MAXNAMELEN];
+ STRUCT_ENTRY_TARGET t;
+ char error[TABLE_MAXNAMELEN];
};
struct chain_cache
{
- char name[IPT_TABLE_MAXNAMELEN];
+ char name[TABLE_MAXNAMELEN];
/* This is the first rule in chain. */
- struct ipt_entry *start;
+ STRUCT_ENTRY *start;
/* Last rule in chain */
- struct ipt_entry *end;
+ STRUCT_ENTRY *end;
};
-struct iptc_handle
+STRUCT_TC_HANDLE
{
/* Have changes been made? */
int changed;
/* Size in here reflects original state. */
- struct ipt_getinfo info;
+ STRUCT_GETINFO info;
struct counter_map *counter_map;
/* Array of hook names */
@@ -97,15 +80,15 @@ struct iptc_handle
struct chain_cache *cache_chain_iteration;
/* Rule iterator: terminal rule */
- struct ipt_entry *cache_rule_end;
+ STRUCT_ENTRY *cache_rule_end;
/* Number in here reflects current state. */
unsigned int new_number;
- struct ipt_get_entries entries;
+ STRUCT_GET_ENTRIES entries;
};
static void
-set_changed(iptc_handle_t h)
+set_changed(TC_HANDLE_T h)
{
if (h->cache_chain_heads) {
free(h->cache_chain_heads);
@@ -118,15 +101,15 @@ set_changed(iptc_handle_t h)
}
#ifndef NDEBUG
-static void do_check(iptc_handle_t h, unsigned int line);
+static void do_check(TC_HANDLE_T h, unsigned int line);
#define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0)
#else
#define CHECK(h)
#endif
static inline int
-get_number(const struct ipt_entry *i,
- const struct ipt_entry *seek,
+get_number(const STRUCT_ENTRY *i,
+ const STRUCT_ENTRY *seek,
unsigned int *pos)
{
if (i == seek)
@@ -136,12 +119,12 @@ get_number(const struct ipt_entry *i,
}
static unsigned int
-entry2index(const iptc_handle_t h, const struct ipt_entry *seek)
+entry2index(const TC_HANDLE_T h, const STRUCT_ENTRY *seek)
{
unsigned int pos = 0;
- if (IPT_ENTRY_ITERATE(h->entries.entries, h->entries.size,
- get_number, seek, &pos) == 0) {
+ if (ENTRY_ITERATE(h->entries.entries, h->entries.size,
+ get_number, seek, &pos) == 0) {
fprintf(stderr, "ERROR: offset %i not an entry!\n",
(unsigned char *)seek - h->entries.entries);
abort();
@@ -150,10 +133,10 @@ entry2index(const iptc_handle_t h, const struct ipt_entry *seek)
}
static inline int
-get_entry_n(struct ipt_entry *i,
+get_entry_n(STRUCT_ENTRY *i,
unsigned int number,
unsigned int *pos,
- struct ipt_entry **pe)
+ STRUCT_ENTRY **pe)
{
if (*pos == number) {
*pe = i;
@@ -163,59 +146,59 @@ get_entry_n(struct ipt_entry *i,
return 0;
}
-static struct ipt_entry *
-index2entry(iptc_handle_t h, unsigned int index)
+static STRUCT_ENTRY *
+index2entry(TC_HANDLE_T h, unsigned int index)
{
unsigned int pos = 0;
- struct ipt_entry *ret = NULL;
+ STRUCT_ENTRY *ret = NULL;
- IPT_ENTRY_ITERATE(h->entries.entries, h->entries.size,
- get_entry_n, index, &pos, &ret);
+ ENTRY_ITERATE(h->entries.entries, h->entries.size,
+ get_entry_n, index, &pos, &ret);
return ret;
}
-static inline struct ipt_entry *
-get_entry(iptc_handle_t h, unsigned int offset)
+static inline STRUCT_ENTRY *
+get_entry(TC_HANDLE_T h, unsigned int offset)
{
- return (struct ipt_entry *)(h->entries.entries + offset);
+ return (STRUCT_ENTRY *)(h->entries.entries + offset);
}
static inline unsigned long
-entry2offset(const iptc_handle_t h, const struct ipt_entry *e)
+entry2offset(const TC_HANDLE_T h, const STRUCT_ENTRY *e)
{
return (unsigned char *)e - h->entries.entries;
}
static unsigned long
-index2offset(iptc_handle_t h, unsigned int index)
+index2offset(TC_HANDLE_T h, unsigned int index)
{
return entry2offset(h, index2entry(h, index));
}
static const char *
-get_errorlabel(iptc_handle_t h, unsigned int offset)
+get_errorlabel(TC_HANDLE_T h, unsigned int offset)
{
- struct ipt_entry *e;
+ STRUCT_ENTRY *e;
e = get_entry(h, offset);
- if (strcmp(ipt_get_target(e)->u.user.name, IPT_ERROR_TARGET) != 0) {
+ if (strcmp(GET_TARGET(e)->u.user.name, IPT_ERROR_TARGET) != 0) {
fprintf(stderr, "ERROR: offset %u not an error node!\n",
offset);
abort();
}
- return (const char *)ipt_get_target(e)->data;
+ return (const char *)GET_TARGET(e)->data;
}
/* Allocate handle of given size */
-static iptc_handle_t
+static TC_HANDLE_T
alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
{
size_t len;
- iptc_handle_t h;
+ TC_HANDLE_T h;
- len = sizeof(struct iptc_handle)
+ len = sizeof(STRUCT_TC_HANDLE)
+ size
+ num_rules * sizeof(struct counter_map);
@@ -228,7 +211,7 @@ alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
h->cache_num_chains = 0;
h->cache_chain_heads = NULL;
h->counter_map = (void *)h
- + sizeof(struct iptc_handle)
+ + sizeof(STRUCT_TC_HANDLE)
+ size;
strcpy(h->info.name, tablename);
strcpy(h->entries.name, tablename);
@@ -236,28 +219,28 @@ alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
return h;
}
-iptc_handle_t
-iptc_init(const char *tablename)
+TC_HANDLE_T
+TC_INIT(const char *tablename)
{
- iptc_handle_t h;
- struct ipt_getinfo info;
+ TC_HANDLE_T h;
+ STRUCT_GETINFO info;
unsigned int i;
int tmp;
socklen_t s;
- iptc_fn = iptc_init;
+ iptc_fn = TC_INIT;
- sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);
if (sockfd < 0)
return NULL;
s = sizeof(info);
- if (strlen(tablename) >= IPT_TABLE_MAXNAMELEN) {
+ if (strlen(tablename) >= TABLE_MAXNAMELEN) {
errno = EINVAL;
return NULL;
}
strcpy(info.name, tablename);
- if (getsockopt(sockfd, IPPROTO_IP, IPT_SO_GET_INFO, &info, &s) < 0)
+ if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0)
return NULL;
if ((h = alloc_handle(info.name, info.size, info.num_entries))
@@ -290,9 +273,9 @@ iptc_init(const char *tablename)
h->entries.size = h->info.size;
- tmp = sizeof(struct ipt_get_entries) + h->info.size;
+ tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size;
- if (getsockopt(sockfd, IPPROTO_IP, IPT_SO_GET_ENTRIES, &h->entries,
+ if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, &h->entries,
&tmp) < 0) {
free(h);
return NULL;
@@ -302,84 +285,17 @@ iptc_init(const char *tablename)
return h;
}
-#define IP_PARTS_NATIVE(n) \
-(unsigned int)((n)>>24)&0xFF, \
-(unsigned int)((n)>>16)&0xFF, \
-(unsigned int)((n)>>8)&0xFF, \
-(unsigned int)((n)&0xFF)
-
-#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n))
-
static inline int
-print_match(const struct ipt_entry_match *m)
+print_match(const STRUCT_ENTRY_MATCH *m)
{
printf("Match name: `%s'\n", m->u.user.name);
return 0;
}
-int
-dump_entry(struct ipt_entry *e, const iptc_handle_t handle)
-{
- size_t i;
- struct ipt_entry_target *t;
-
- printf("Entry %u (%lu):\n", entry2index(handle, e),
- entry2offset(handle, e));
- printf("SRC IP: %u.%u.%u.%u/%u.%u.%u.%u\n",
- IP_PARTS(e->ip.src.s_addr),IP_PARTS(e->ip.smsk.s_addr));
- printf("DST IP: %u.%u.%u.%u/%u.%u.%u.%u\n",
- IP_PARTS(e->ip.dst.s_addr),IP_PARTS(e->ip.dmsk.s_addr));
- printf("Interface: `%s'/", e->ip.iniface);
- for (i = 0; i < IFNAMSIZ; i++)
- printf("%c", e->ip.iniface_mask[i] ? 'X' : '.');
- printf("to `%s'/", e->ip.outiface);
- for (i = 0; i < IFNAMSIZ; i++)
- printf("%c", e->ip.outiface_mask[i] ? 'X' : '.');
- printf("\nProtocol: %u\n", e->ip.proto);
- printf("Flags: %02X\n", e->ip.flags);
- printf("Invflags: %02X\n", e->ip.invflags);
- printf("Counters: %llu packets, %llu bytes\n",
- e->counters.pcnt, e->counters.bcnt);
- printf("Cache: %08X ", e->nfcache);
- if (e->nfcache & NFC_ALTERED) printf("ALTERED ");
- if (e->nfcache & NFC_UNKNOWN) printf("UNKNOWN ");
- if (e->nfcache & NFC_IP_SRC) printf("IP_SRC ");
- if (e->nfcache & NFC_IP_DST) printf("IP_DST ");
- if (e->nfcache & NFC_IP_IF_IN) printf("IP_IF_IN ");
- if (e->nfcache & NFC_IP_IF_OUT) printf("IP_IF_OUT ");
- if (e->nfcache & NFC_IP_TOS) printf("IP_TOS ");
- if (e->nfcache & NFC_IP_PROTO) printf("IP_PROTO ");
- if (e->nfcache & NFC_IP_OPTIONS) printf("IP_OPTIONS ");
- if (e->nfcache & NFC_IP_TCPFLAGS) printf("IP_TCPFLAGS ");
- if (e->nfcache & NFC_IP_SRC_PT) printf("IP_SRC_PT ");
- if (e->nfcache & NFC_IP_DST_PT) printf("IP_DST_PT ");
- if (e->nfcache & NFC_IP_PROTO_UNKNOWN) printf("IP_PROTO_UNKNOWN ");
- printf("\n");
-
- IPT_MATCH_ITERATE(e, print_match);
-
- t = ipt_get_target(e);
- printf("Target name: `%s' [%u]\n", t->u.user.name, t->u.target_size);
- if (strcmp(t->u.user.name, IPT_STANDARD_TARGET) == 0) {
- int pos = *(int *)t->data;
- if (pos < 0)
- printf("verdict=%s\n",
- pos == -NF_ACCEPT-1 ? "NF_ACCEPT"
- : pos == -NF_DROP-1 ? "NF_DROP"
- : pos == -NF_QUEUE-1 ? "NF_QUEUE"
- : pos == IPT_RETURN ? "RETURN"
- : "UNKNOWN");
- else
- printf("verdict=%u\n", pos);
- } else if (strcmp(t->u.user.name, IPT_ERROR_TARGET) == 0)
- printf("error=`%s'\n", t->data);
-
- printf("\n");
- return 0;
-}
-
+static int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle);
+
void
-dump_entries(const iptc_handle_t handle)
+TC_DUMP_ENTRIES(const TC_HANDLE_T handle)
{
CHECK(handle);
@@ -400,17 +316,17 @@ dump_entries(const iptc_handle_t handle)
handle->info.underflow[NF_IP_LOCAL_OUT],
handle->info.underflow[NF_IP_POST_ROUTING]);
- IPT_ENTRY_ITERATE(handle->entries.entries, handle->entries.size,
- dump_entry, handle);
+ ENTRY_ITERATE(handle->entries.entries, handle->entries.size,
+ dump_entry, handle);
}
/* Returns 0 if not hook entry, else hooknumber + 1 */
static inline unsigned int
-is_hook_entry(struct ipt_entry *e, iptc_handle_t h)
+is_hook_entry(STRUCT_ENTRY *e, TC_HANDLE_T h)
{
unsigned int i;
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NUMHOOKS; i++) {
if ((h->info.valid_hooks & (1 << i))
&& get_entry(h, h->info.hook_entry[i]) == e)
return i+1;
@@ -419,7 +335,7 @@ is_hook_entry(struct ipt_entry *e, iptc_handle_t h)
}
static inline int
-add_chain(struct ipt_entry *e, iptc_handle_t h, struct ipt_entry **prev)
+add_chain(STRUCT_ENTRY *e, TC_HANDLE_T h, STRUCT_ENTRY **prev)
{
unsigned int builtin;
@@ -432,13 +348,13 @@ add_chain(struct ipt_entry *e, iptc_handle_t h, struct ipt_entry **prev)
/* We know this is the start of a new chain if it's an ERROR
target, or a hook entry point */
- if (strcmp(ipt_get_target(e)->u.user.name, IPT_ERROR_TARGET) == 0) {
+ if (strcmp(GET_TARGET(e)->u.user.name, IPT_ERROR_TARGET) == 0) {
/* prev was last entry in previous chain */
h->cache_chain_heads[h->cache_num_chains-1].end
= *prev;
strcpy(h->cache_chain_heads[h->cache_num_chains].name,
- (const char *)ipt_get_target(e)->data);
+ (const char *)GET_TARGET(e)->data);
h->cache_chain_heads[h->cache_num_chains].start
= (void *)e + e->next_offset;
h->cache_num_chains++;
@@ -465,10 +381,10 @@ static int alphasort(const void *a, const void *b)
((struct chain_cache *)b)->name);
}
-static int populate_cache(iptc_handle_t h)
+static int populate_cache(TC_HANDLE_T h)
{
unsigned int i;
- struct ipt_entry *prev;
+ STRUCT_ENTRY *prev;
/* # chains < # rules / 2 + num builtins - 1 */
h->cache_chain_heads = malloc((h->new_number / 2 + 4)
@@ -482,14 +398,14 @@ static int populate_cache(iptc_handle_t h)
h->cache_num_builtins = 0;
/* Count builtins */
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NUMHOOKS; i++) {
if (h->info.valid_hooks & (1 << i))
h->cache_num_builtins++;
}
prev = NULL;
- IPT_ENTRY_ITERATE(h->entries.entries, h->entries.size,
- add_chain, h, &prev);
+ ENTRY_ITERATE(h->entries.entries, h->entries.size,
+ add_chain, h, &prev);
qsort(h->cache_chain_heads + h->cache_num_builtins,
h->cache_num_chains - h->cache_num_builtins,
@@ -500,7 +416,7 @@ static int populate_cache(iptc_handle_t h)
/* Returns cache ptr if found, otherwise NULL. */
static struct chain_cache *
-find_label(const char *name, iptc_handle_t handle)
+find_label(const char *name, TC_HANDLE_T handle)
{
unsigned int i;
@@ -518,17 +434,17 @@ find_label(const char *name, iptc_handle_t handle)
}
/* Does this chain exist? */
-int iptc_is_chain(const char *chain, const iptc_handle_t handle)
+int TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle)
{
return find_label(chain, handle) != NULL;
}
/* Returns the position of the final (ie. unconditional) element. */
static unsigned int
-get_chain_end(const iptc_handle_t handle, unsigned int start)
+get_chain_end(const TC_HANDLE_T handle, unsigned int start)
{
unsigned int last_off, off;
- struct ipt_entry *e;
+ STRUCT_ENTRY *e;
last_off = start;
e = get_entry(handle, start);
@@ -537,20 +453,20 @@ get_chain_end(const iptc_handle_t handle, unsigned int start)
for (off = start + e->next_offset;
off < handle->entries.size;
last_off = off, off += e->next_offset) {
- struct ipt_entry_target *t;
+ STRUCT_ENTRY_TARGET *t;
unsigned int i;
e = get_entry(handle, off);
/* We hit an entry point. */
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NUMHOOKS; i++) {
if ((handle->info.valid_hooks & (1 << i))
&& off == handle->info.hook_entry[i])
return last_off;
}
/* We hit a user chain label */
- t = ipt_get_target(e);
+ t = GET_TARGET(e);
if (strcmp(t->u.user.name, IPT_ERROR_TARGET) == 0)
return last_off;
}
@@ -562,7 +478,7 @@ get_chain_end(const iptc_handle_t handle, unsigned int start)
/* Iterator functions to run through the chains. */
const char *
-iptc_first_chain(iptc_handle_t *handle)
+iptc_first_chain(TC_HANDLE_T *handle)
{
if ((*handle)->cache_chain_heads == NULL
&& !populate_cache(*handle))
@@ -576,7 +492,7 @@ iptc_first_chain(iptc_handle_t *handle)
/* Iterator functions to run through the chains. Returns NULL at end. */
const char *
-iptc_next_chain(iptc_handle_t *handle)
+TC_NEXT_CHAIN(TC_HANDLE_T *handle)
{
(*handle)->cache_chain_iteration++;
@@ -588,8 +504,8 @@ iptc_next_chain(iptc_handle_t *handle)
}
/* Get first rule in the given chain: NULL for empty chain. */
-const struct ipt_entry *
-iptc_first_rule(const char *chain, iptc_handle_t *handle)
+const STRUCT_ENTRY *
+iptc_first_rule(const char *chain, TC_HANDLE_T *handle)
{
struct chain_cache *c;
@@ -608,8 +524,8 @@ iptc_first_rule(const char *chain, iptc_handle_t *handle)
}
/* Returns NULL when rules run out. */
-const struct ipt_entry *
-iptc_next_rule(const struct ipt_entry *prev, iptc_handle_t *handle)
+const STRUCT_ENTRY *
+iptc_next_rule(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle)
{
if ((void *)prev + prev->next_offset
== (void *)(*handle)->cache_rule_end)
@@ -621,10 +537,10 @@ iptc_next_rule(const struct ipt_entry *prev, iptc_handle_t *handle)
#if 0
/* How many rules in this chain? */
unsigned int
-iptc_num_rules(const char *chain, iptc_handle_t *handle)
+TC_NUM_RULES(const char *chain, TC_HANDLE_T *handle)
{
unsigned int off = 0;
- struct ipt_entry *start, *end;
+ STRUCT_ENTRY *start, *end;
CHECK(*handle);
if (!find_label(&off, chain, *handle)) {
@@ -639,9 +555,9 @@ iptc_num_rules(const char *chain, iptc_handle_t *handle)
}
/* Get n'th rule in this chain. */
-const struct ipt_entry *iptc_get_rule(const char *chain,
- unsigned int n,
- iptc_handle_t *handle)
+const STRUCT_ENTRY *TC_GET_RULE(const char *chain,
+ unsigned int n,
+ TC_HANDLE_T *handle)
{
unsigned int pos = 0, chainindex;
@@ -658,27 +574,27 @@ const struct ipt_entry *iptc_get_rule(const char *chain,
#endif
static const char *
-target_name(iptc_handle_t handle, const struct ipt_entry *ce)
+target_name(TC_HANDLE_T handle, const STRUCT_ENTRY *ce)
{
int spos;
unsigned int labelidx;
- struct ipt_entry *jumpto;
+ STRUCT_ENTRY *jumpto;
/* To avoid const warnings */
- struct ipt_entry *e = (struct ipt_entry *)ce;
+ STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce;
- if (strcmp(ipt_get_target(e)->u.user.name, IPT_STANDARD_TARGET) != 0)
- return ipt_get_target(e)->u.user.name;
+ if (strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET) != 0)
+ return GET_TARGET(e)->u.user.name;
/* Standard target: evaluate */
- spos = *(int *)ipt_get_target(e)->data;
+ spos = *(int *)GET_TARGET(e)->data;
if (spos < 0) {
- if (spos == IPT_RETURN)
- return IPTC_LABEL_RETURN;
+ if (spos == RETURN)
+ return LABEL_RETURN;
else if (spos == -NF_ACCEPT-1)
- return IPTC_LABEL_ACCEPT;
+ return LABEL_ACCEPT;
else if (spos == -NF_DROP-1)
- return IPTC_LABEL_DROP;
+ return LABEL_DROP;
else if (spos == -NF_QUEUE-1)
return IPTC_LABEL_QUEUE;
@@ -700,19 +616,19 @@ target_name(iptc_handle_t handle, const struct ipt_entry *ce)
}
/* Returns a pointer to the target name of this position. */
-const char *iptc_get_target(const struct ipt_entry *e,
- iptc_handle_t *handle)
+const char *TC_GET_TARGET(const STRUCT_ENTRY *e,
+ TC_HANDLE_T *handle)
{
return target_name(*handle, e);
}
/* Is this a built-in chain? Actually returns hook + 1. */
int
-iptc_builtin(const char *chain, const iptc_handle_t handle)
+TC_BUILTIN(const char *chain, const TC_HANDLE_T handle)
{
unsigned int i;
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NUMHOOKS; i++) {
if ((handle->info.valid_hooks & (1 << i))
&& handle->hooknames[i]
&& strcmp(handle->hooknames[i], chain) == 0)
@@ -723,15 +639,15 @@ iptc_builtin(const char *chain, const iptc_handle_t handle)
/* Get the policy of a given built-in chain */
const char *
-iptc_get_policy(const char *chain,
- struct ipt_counters *counters,
- iptc_handle_t *handle)
+TC_GET_POLICY(const char *chain,
+ STRUCT_COUNTERS *counters,
+ TC_HANDLE_T *handle)
{
unsigned int start;
- struct ipt_entry *e;
+ STRUCT_ENTRY *e;
int hook;
- hook = iptc_builtin(chain, *handle);
+ hook = TC_BUILTIN(chain, *handle);
if (hook != 0)
start = (*handle)->info.hook_entry[hook-1];
else
@@ -744,16 +660,16 @@ iptc_get_policy(const char *chain,
}
static int
-correct_verdict(struct ipt_entry *e,
+correct_verdict(STRUCT_ENTRY *e,
unsigned char *base,
unsigned int offset, int delta_offset)
{
- struct ipt_standard_target *t = (void *)ipt_get_target(e);
+ STRUCT_STANDARD_TARGET *t = (void *)GET_TARGET(e);
unsigned int curr = (unsigned char *)e - base;
/* Trap: insert of fall-through rule. Don't change fall-through
verdict to jump-over-next-rule. */
- if (strcmp(t->target.u.user.name, IPT_STANDARD_TARGET) == 0
+ if (strcmp(t->target.u.user.name, STANDARD_TARGET) == 0
&& t->verdict > (int)offset
&& !(curr == offset &&
t->verdict == curr + e->next_offset)) {
@@ -765,12 +681,12 @@ correct_verdict(struct ipt_entry *e,
/* Adjusts standard verdict jump positions after an insertion/deletion. */
static int
-set_verdict(unsigned int offset, int delta_offset, iptc_handle_t *handle)
+set_verdict(unsigned int offset, int delta_offset, TC_HANDLE_T *handle)
{
- IPT_ENTRY_ITERATE((*handle)->entries.entries,
- (*handle)->entries.size,
- correct_verdict, (*handle)->entries.entries,
- offset, delta_offset);
+ ENTRY_ITERATE((*handle)->entries.entries,
+ (*handle)->entries.size,
+ correct_verdict, (*handle)->entries.entries,
+ offset, delta_offset);
set_changed(*handle);
return 1;
@@ -780,13 +696,13 @@ set_verdict(unsigned int offset, int delta_offset, iptc_handle_t *handle)
* insertion position is an entry point, keep the entry point. */
static int
insert_rules(unsigned int num_rules, unsigned int rules_size,
- const struct ipt_entry *insert,
+ const STRUCT_ENTRY *insert,
unsigned int offset, unsigned int num_rules_offset,
int prepend,
- iptc_handle_t *handle)
+ TC_HANDLE_T *handle)
{
- iptc_handle_t newh;
- struct ipt_getinfo newinfo;
+ TC_HANDLE_T newh;
+ STRUCT_GETINFO newinfo;
unsigned int i;
if (offset >= (*handle)->entries.size) {
@@ -797,7 +713,7 @@ insert_rules(unsigned int num_rules, unsigned int rules_size,
newinfo = (*handle)->info;
/* Fix up entry points. */
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NUMHOOKS; i++) {
/* Entry points to START of chain, so keep same if
inserting on at that point. */
if ((*handle)->info.hook_entry[i] > offset)
@@ -855,7 +771,7 @@ insert_rules(unsigned int num_rules, unsigned int rules_size,
static int
delete_rules(unsigned int num_rules, unsigned int rules_size,
unsigned int offset, unsigned int num_rules_offset,
- iptc_handle_t *handle)
+ TC_HANDLE_T *handle)
{
unsigned int i;
@@ -865,7 +781,7 @@ delete_rules(unsigned int num_rules, unsigned int rules_size,
}
/* Fix up entry points. */
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+ for (i = 0; i < NUMHOOKS; i++) {
/* In practice, we never delete up to a hook entry,
since the built-in chains are always first,
so these two are never equal */
@@ -908,31 +824,31 @@ delete_rules(unsigned int num_rules, unsigned int rules_size,
}
static int
-standard_map(struct ipt_entry *e, int verdict)
+standard_map(STRUCT_ENTRY *e, int verdict)
{
- struct ipt_standard_target *t;
+ STRUCT_STANDARD_TARGET *t;
- t = (struct ipt_standard_target *)ipt_get_target(e);
+ t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
- if (t->target.u.target_size != sizeof(struct ipt_standard_target)) {
+ if (t->target.u.target_size != sizeof(STRUCT_STANDARD_TARGET)) {
errno = EINVAL;
return 0;
}
/* memset for memcmp convenience on delete/replace */
- memset(t->target.u.user.name, 0, IPT_FUNCTION_MAXNAMELEN);
- strcpy(t->target.u.user.name, IPT_STANDARD_TARGET);
+ memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
+ strcpy(t->target.u.user.name, STANDARD_TARGET);
t->verdict = verdict;
return 1;
}
static int
-map_target(const iptc_handle_t handle,
- struct ipt_entry *e,
+map_target(const TC_HANDLE_T handle,
+ STRUCT_ENTRY *e,
unsigned int offset,
- struct ipt_entry_target *old)
+ STRUCT_ENTRY_TARGET *old)
{
- struct ipt_entry_target *t = ipt_get_target(e);
+ STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
/* Save old target (except data, which we don't change, except for
standard case, where we don't care). */
@@ -942,15 +858,15 @@ map_target(const iptc_handle_t handle,
if (strcmp(t->u.user.name, "") == 0)
return standard_map(e, offset + e->next_offset);
/* Maybe it's a standard target name... */
- else if (strcmp(t->u.user.name, IPTC_LABEL_ACCEPT) == 0)
+ else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0)
return standard_map(e, -NF_ACCEPT - 1);
- else if (strcmp(t->u.user.name, IPTC_LABEL_DROP) == 0)
+ else if (strcmp(t->u.user.name, LABEL_DROP) == 0)
return standard_map(e, -NF_DROP - 1);
else if (strcmp(t->u.user.name, IPTC_LABEL_QUEUE) == 0)
return standard_map(e, -NF_QUEUE - 1);
- else if (strcmp(t->u.user.name, IPTC_LABEL_RETURN) == 0)
- return standard_map(e, IPT_RETURN);
- else if (iptc_builtin(t->u.user.name, handle)) {
+ else if (strcmp(t->u.user.name, LABEL_RETURN) == 0)
+ return standard_map(e, RETURN);
+ else if (TC_BUILTIN(t->u.user.name, handle)) {
/* Can't jump to builtins. */
errno = EINVAL;
return 0;
@@ -967,14 +883,14 @@ map_target(const iptc_handle_t handle,
/* memset to all 0 for your memcmp convenience. */
memset(t->u.user.name + strlen(t->u.user.name),
0,
- IPT_FUNCTION_MAXNAMELEN - strlen(t->u.user.name));
+ FUNCTION_MAXNAMELEN - strlen(t->u.user.name));
return 1;
}
static void
-unmap_target(struct ipt_entry *e, struct ipt_entry_target *old)
+unmap_target(STRUCT_ENTRY *e, STRUCT_ENTRY_TARGET *old)
{
- struct ipt_entry_target *t = ipt_get_target(e);
+ STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
/* Save old target (except data, which we don't change, except for
standard case, where we don't care). */
@@ -983,17 +899,17 @@ unmap_target(struct ipt_entry *e, struct ipt_entry_target *old)
/* Insert the entry `fw' in chain `chain' into position `rulenum'. */
int
-iptc_insert_entry(const ipt_chainlabel chain,
- const struct ipt_entry *e,
- unsigned int rulenum,
- iptc_handle_t *handle)
+TC_INSERT_ENTRY(const IPT_CHAINLABEL chain,
+ const STRUCT_ENTRY *e,
+ unsigned int rulenum,
+ TC_HANDLE_T *handle)
{
unsigned int chainindex, offset;
- struct ipt_entry_target old;
+ STRUCT_ENTRY_TARGET old;
struct chain_cache *c;
int ret;
- iptc_fn = iptc_insert_entry;
+ iptc_fn = TC_INSERT_ENTRY;
if (!(c = find_label(chain, *handle))) {
errno = ENOENT;
return 0;
@@ -1009,28 +925,28 @@ iptc_insert_entry(const ipt_chainlabel chain,
/* Mapping target actually alters entry, but that's
transparent to the caller. */
- if (!map_target(*handle, (struct ipt_entry *)e, offset, &old))
+ if (!map_target(*handle, (STRUCT_ENTRY *)e, offset, &old))
return 0;
ret = insert_rules(1, e->next_offset, e, offset,
chainindex + rulenum, rulenum == 0, handle);
- unmap_target((struct ipt_entry *)e, &old);
+ unmap_target((STRUCT_ENTRY *)e, &old);
return ret;
}
/* Atomically replace rule `rulenum' in `chain' with `fw'. */
int
-iptc_replace_entry(const ipt_chainlabel chain,
- const struct ipt_entry *e,
- unsigned int rulenum,
- iptc_handle_t *handle)
+TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain,
+ const STRUCT_ENTRY *e,
+ unsigned int rulenum,
+ TC_HANDLE_T *handle)
{
unsigned int chainindex, offset;
- struct ipt_entry_target old;
+ STRUCT_ENTRY_TARGET old;
struct chain_cache *c;
int ret;
- iptc_fn = iptc_replace_entry;
+ iptc_fn = TC_REPLACE_ENTRY;
if (!(c = find_label(chain, *handle))) {
errno = ENOENT;
@@ -1050,33 +966,33 @@ iptc_replace_entry(const ipt_chainlabel chain,
offset, chainindex + rulenum, handle))
return 0;
- if (!map_target(*handle, (struct ipt_entry *)e, offset, &old))
+ if (!map_target(*handle, (STRUCT_ENTRY *)e, offset, &old))
return 0;
ret = insert_rules(1, e->next_offset, e, offset,
chainindex + rulenum, 1, handle);
- unmap_target((struct ipt_entry *)e, &old);
+ unmap_target((STRUCT_ENTRY *)e, &old);
return ret;
}
/* Append entry `fw' to chain `chain'. Equivalent to insert with
rulenum = length of chain. */
int
-iptc_append_entry(const ipt_chainlabel chain,
- const struct ipt_entry *e,
- iptc_handle_t *handle)
+TC_APPEND_ENTRY(const IPT_CHAINLABEL chain,
+ const STRUCT_ENTRY *e,
+ TC_HANDLE_T *handle)
{
struct chain_cache *c;
- struct ipt_entry_target old;
+ STRUCT_ENTRY_TARGET old;
int ret;
- iptc_fn = iptc_append_entry;
+ iptc_fn = TC_APPEND_ENTRY;
if (!(c = find_label(chain, *handle))) {
errno = ENOENT;
return 0;
}
- if (!map_target(*handle, (struct ipt_entry *)e,
+ if (!map_target(*handle, (STRUCT_ENTRY *)e,
entry2offset(*handle, c->end), &old))
return 0;
@@ -1084,17 +1000,17 @@ iptc_append_entry(const ipt_chainlabel chain,
entry2offset(*handle, c->end),
entry2index(*handle, c->end),
0, handle);
- unmap_target((struct ipt_entry *)e, &old);
+ unmap_target((STRUCT_ENTRY *)e, &old);
return ret;
}
static inline int
-match_different(const struct ipt_entry_match *a,
+match_different(const STRUCT_ENTRY_MATCH *a,
const unsigned char *a_elems,
const unsigned char *b_elems,
unsigned char **maskptr)
{
- const struct ipt_entry_match *b;
+ const STRUCT_ENTRY_MATCH *b;
unsigned int i;
/* Offset of b is the same as a. */
@@ -1129,73 +1045,23 @@ target_different(const unsigned char *a_targdata,
return 0;
}
-static inline int
-is_same(const struct ipt_entry *a, const struct ipt_entry *b,
- unsigned char *matchmask)
-{
- unsigned int i;
- struct ipt_entry_target *ta, *tb;
- unsigned char *mptr;
-
- /* Always compare head structures: ignore mask here. */
- if (a->ip.src.s_addr != b->ip.src.s_addr
- || a->ip.dst.s_addr != b->ip.dst.s_addr
- || a->ip.smsk.s_addr != b->ip.smsk.s_addr
- || a->ip.smsk.s_addr != b->ip.smsk.s_addr
- || a->ip.proto != b->ip.proto
- || a->ip.flags != b->ip.flags
- || a->ip.invflags != b->ip.invflags)
- return 0;
-
- for (i = 0; i < IFNAMSIZ; i++) {
- if (a->ip.iniface_mask[i] != b->ip.iniface_mask[i])
- return 0;
- if ((a->ip.iniface[i] & a->ip.iniface_mask[i])
- != (b->ip.iniface[i] & b->ip.iniface_mask[i]))
- return 0;
- if (a->ip.outiface_mask[i] != b->ip.outiface_mask[i])
- return 0;
- if ((a->ip.outiface[i] & a->ip.outiface_mask[i])
- != (b->ip.outiface[i] & b->ip.outiface_mask[i]))
- return 0;
- }
-
- if (a->nfcache != b->nfcache
- || a->target_offset != b->target_offset
- || a->next_offset != b->next_offset)
- return 0;
-
- mptr = matchmask + sizeof(struct ipt_entry);
- if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
- return 0;
-
- ta = ipt_get_target((struct ipt_entry *)a);
- tb = ipt_get_target((struct ipt_entry *)b);
- if (ta->u.target_size != tb->u.target_size)
- return 0;
- if (strcmp(ta->u.user.name, tb->u.user.name) != 0)
- return 0;
-
- mptr += sizeof(*ta);
- if (target_different(ta->data, tb->data,
- ta->u.target_size - sizeof(*ta), mptr))
- return 0;
-
- return 1;
-}
+static int
+is_same(const STRUCT_ENTRY *a,
+ const STRUCT_ENTRY *b,
+ unsigned char *matchmask);
/* Delete the first rule in `chain' which matches `fw'. */
int
-iptc_delete_entry(const ipt_chainlabel chain,
- const struct ipt_entry *origfw,
- unsigned char *matchmask,
- iptc_handle_t *handle)
+TC_DELETE_ENTRY(const IPT_CHAINLABEL chain,
+ const STRUCT_ENTRY *origfw,
+ unsigned char *matchmask,
+ TC_HANDLE_T *handle)
{
unsigned int offset;
struct chain_cache *c;
- struct ipt_entry *e, *fw;
+ STRUCT_ENTRY *e, *fw;
- iptc_fn = iptc_delete_entry;
+ iptc_fn = TC_DELETE_ENTRY;
if (!(c = find_label(chain, *handle))) {
errno = ENOENT;
return 0;
@@ -1210,7 +1076,7 @@ iptc_delete_entry(const ipt_chainlabel chain,
for (offset = entry2offset(*handle, c->start);
offset < entry2offset(*handle, c->end);
offset += e->next_offset) {
- struct ipt_entry_target discard;
+ STRUCT_ENTRY_TARGET discard;
memcpy(fw, origfw, origfw->next_offset);
@@ -1242,16 +1108,16 @@ iptc_delete_entry(const ipt_chainlabel chain,
/* Delete the rule in position `rulenum' in `chain'. */
int
-iptc_delete_num_entry(const ipt_chainlabel chain,
- unsigned int rulenum,
- iptc_handle_t *handle)
+TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain,
+ unsigned int rulenum,
+ TC_HANDLE_T *handle)
{
unsigned int index;
int ret;
- struct ipt_entry *e;
+ STRUCT_ENTRY *e;
struct chain_cache *c;
- iptc_fn = iptc_delete_num_entry;
+ iptc_fn = TC_DELETE_NUM_ENTRY;
if (!(c = find_label(chain, *handle))) {
errno = ENOENT;
return 0;
@@ -1278,9 +1144,9 @@ iptc_delete_num_entry(const ipt_chainlabel chain,
/* Check the packet `fw' on chain `chain'. Returns the verdict, or
NULL and sets errno. */
const char *
-iptc_check_packet(const ipt_chainlabel chain,
- struct ipt_entry *entry,
- iptc_handle_t *handle)
+TC_CHECK_PACKET(const IPT_CHAINLABEL chain,
+ STRUCT_ENTRY *entry,
+ TC_HANDLE_T *handle)
{
errno = ENOSYS;
return NULL;
@@ -1288,13 +1154,13 @@ iptc_check_packet(const ipt_chainlabel chain,
/* Flushes the entries in the given chain (ie. empties chain). */
int
-iptc_flush_entries(const ipt_chainlabel chain, iptc_handle_t *handle)
+TC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
{
unsigned int startindex, endindex;
struct chain_cache *c;
int ret;
- iptc_fn = iptc_flush_entries;
+ iptc_fn = TC_FLUSH_ENTRIES;
if (!(c = find_label(chain, *handle))) {
errno = ENOENT;
return 0;
@@ -1311,7 +1177,7 @@ iptc_flush_entries(const ipt_chainlabel chain, iptc_handle_t *handle)
/* Zeroes the counters in a chain. */
int
-iptc_zero_entries(const ipt_chainlabel chain, iptc_handle_t *handle)
+TC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
{
unsigned int i, end;
struct chain_cache *c;
@@ -1337,48 +1203,48 @@ iptc_zero_entries(const ipt_chainlabel chain, iptc_handle_t *handle)
/* To create a chain, create two rules: error node and unconditional
* return. */
int
-iptc_create_chain(const ipt_chainlabel chain, iptc_handle_t *handle)
+TC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
{
int ret;
struct {
- struct ipt_entry head;
+ STRUCT_ENTRY head;
struct ipt_error_target name;
- struct ipt_entry ret;
- struct ipt_standard_target target;
+ STRUCT_ENTRY ret;
+ STRUCT_STANDARD_TARGET target;
} newc;
- iptc_fn = iptc_create_chain;
+ iptc_fn = TC_CREATE_CHAIN;
/* find_label doesn't cover built-in targets: DROP, ACCEPT,
QUEUE, RETURN. */
if (find_label(chain, *handle)
- || strcmp(chain, IPTC_LABEL_DROP) == 0
- || strcmp(chain, IPTC_LABEL_ACCEPT) == 0
+ || strcmp(chain, LABEL_DROP) == 0
+ || strcmp(chain, LABEL_ACCEPT) == 0
|| strcmp(chain, IPTC_LABEL_QUEUE) == 0
- || strcmp(chain, IPTC_LABEL_RETURN) == 0) {
+ || strcmp(chain, LABEL_RETURN) == 0) {
errno = EEXIST;
return 0;
}
- if (strlen(chain)+1 > sizeof(ipt_chainlabel)) {
+ if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) {
errno = EINVAL;
return 0;
}
memset(&newc, 0, sizeof(newc));
- newc.head.target_offset = sizeof(struct ipt_entry);
+ newc.head.target_offset = sizeof(STRUCT_ENTRY);
newc.head.next_offset
- = sizeof(struct ipt_entry) + sizeof(struct ipt_error_target);
+ = sizeof(STRUCT_ENTRY) + sizeof(struct ipt_error_target);
strcpy(newc.name.t.u.user.name, IPT_ERROR_TARGET);
newc.name.t.u.target_size = sizeof(struct ipt_error_target);
strcpy(newc.name.error, chain);
- newc.ret.target_offset = sizeof(struct ipt_entry);
+ newc.ret.target_offset = sizeof(STRUCT_ENTRY);
newc.ret.next_offset
- = sizeof(struct ipt_entry)+sizeof(struct ipt_standard_target);
- strcpy(newc.target.target.u.user.name, IPT_STANDARD_TARGET);
- newc.target.target.u.target_size = sizeof(struct ipt_standard_target);
- newc.target.verdict = IPT_RETURN;
+ = sizeof(STRUCT_ENTRY)+sizeof(STRUCT_STANDARD_TARGET);
+ strcpy(newc.target.target.u.user.name, STANDARD_TARGET);
+ newc.target.target.u.target_size = sizeof(STRUCT_STANDARD_TARGET);
+ newc.target.verdict = RETURN;
/* Add just before terminal entry */
ret = insert_rules(2, sizeof(newc), &newc.head,
@@ -1389,12 +1255,12 @@ iptc_create_chain(const ipt_chainlabel chain, iptc_handle_t *handle)
}
static int
-count_ref(struct ipt_entry *e, unsigned int offset, unsigned int *ref)
+count_ref(STRUCT_ENTRY *e, unsigned int offset, unsigned int *ref)
{
- struct ipt_standard_target *t;
+ STRUCT_STANDARD_TARGET *t;
- if (strcmp(ipt_get_target(e)->u.user.name, IPT_STANDARD_TARGET) == 0) {
- t = (struct ipt_standard_target *)ipt_get_target(e);
+ if (strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET) == 0) {
+ t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
if (t->verdict == offset)
(*ref)++;
@@ -1405,8 +1271,8 @@ count_ref(struct ipt_entry *e, unsigned int offset, unsigned int *ref)
/* Get the number of references to this chain. */
int
-iptc_get_references(unsigned int *ref, const ipt_chainlabel chain,
- iptc_handle_t *handle)
+TC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain,
+ TC_HANDLE_T *handle)
{
struct chain_cache *c;
@@ -1416,27 +1282,27 @@ iptc_get_references(unsigned int *ref, const ipt_chainlabel chain,
}
*ref = 0;
- IPT_ENTRY_ITERATE((*handle)->entries.entries,
- (*handle)->entries.size,
- count_ref, entry2offset(*handle, c->start), ref);
+ ENTRY_ITERATE((*handle)->entries.entries,
+ (*handle)->entries.size,
+ count_ref, entry2offset(*handle, c->start), ref);
return 1;
}
/* Deletes a chain. */
int
-iptc_delete_chain(const ipt_chainlabel chain, iptc_handle_t *handle)
+TC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
{
unsigned int labelidx, labeloff;
unsigned int references;
struct chain_cache *c;
int ret;
- if (!iptc_get_references(&references, chain, handle))
+ if (!TC_GET_REFERENCES(&references, chain, handle))
return 0;
- iptc_fn = iptc_delete_chain;
+ iptc_fn = TC_DELETE_CHAIN;
- if (iptc_builtin(chain, *handle)) {
+ if (TC_BUILTIN(chain, *handle)) {
errno = EINVAL;
return 0;
}
@@ -1468,33 +1334,33 @@ iptc_delete_chain(const ipt_chainlabel chain, iptc_handle_t *handle)
}
/* Renames a chain. */
-int iptc_rename_chain(const ipt_chainlabel oldname,
- const ipt_chainlabel newname,
- iptc_handle_t *handle)
+int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname,
+ const IPT_CHAINLABEL newname,
+ TC_HANDLE_T *handle)
{
unsigned int labeloff, labelidx;
struct chain_cache *c;
struct ipt_error_target *t;
- iptc_fn = iptc_rename_chain;
+ iptc_fn = TC_RENAME_CHAIN;
/* find_label doesn't cover built-in targets: DROP, ACCEPT
RETURN. */
if (find_label(newname, *handle)
- || strcmp(newname, IPTC_LABEL_DROP) == 0
- || strcmp(newname, IPTC_LABEL_ACCEPT) == 0
- || strcmp(newname, IPTC_LABEL_RETURN) == 0) {
+ || strcmp(newname, LABEL_DROP) == 0
+ || strcmp(newname, LABEL_ACCEPT) == 0
+ || strcmp(newname, LABEL_RETURN) == 0) {
errno = EEXIST;
return 0;
}
if (!(c = find_label(oldname, *handle))
- || iptc_builtin(oldname, *handle)) {
+ || TC_BUILTIN(oldname, *handle)) {
errno = ENOENT;
return 0;
}
- if (strlen(newname)+1 > sizeof(ipt_chainlabel)) {
+ if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) {
errno = EINVAL;
return 0;
}
@@ -1504,7 +1370,7 @@ int iptc_rename_chain(const ipt_chainlabel oldname,
labeloff = index2offset(*handle, labelidx);
t = (struct ipt_error_target *)
- ipt_get_target(get_entry(*handle, labeloff));
+ GET_TARGET(get_entry(*handle, labeloff));
memset(t->error, 0, sizeof(t->error));
strcpy(t->error, newname);
@@ -1515,18 +1381,18 @@ int iptc_rename_chain(const ipt_chainlabel oldname,
/* Sets the policy on a built-in chain. */
int
-iptc_set_policy(const ipt_chainlabel chain,
- const ipt_chainlabel policy,
- iptc_handle_t *handle)
+TC_SET_POLICY(const IPT_CHAINLABEL chain,
+ const IPT_CHAINLABEL policy,
+ TC_HANDLE_T *handle)
{
unsigned int hook;
unsigned int policyoff;
- struct ipt_entry *e;
- struct ipt_standard_target *t;
+ STRUCT_ENTRY *e;
+ STRUCT_STANDARD_TARGET *t;
- iptc_fn = iptc_set_policy;
+ iptc_fn = TC_SET_POLICY;
/* Figure out which chain. */
- hook = iptc_builtin(chain, *handle);
+ hook = TC_BUILTIN(chain, *handle);
if (hook == 0) {
errno = ENOENT;
return 0;
@@ -1541,11 +1407,11 @@ iptc_set_policy(const ipt_chainlabel chain,
}
e = get_entry(*handle, policyoff);
- t = (struct ipt_standard_target *)ipt_get_target(e);
+ t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
- if (strcmp(policy, IPTC_LABEL_ACCEPT) == 0)
+ if (strcmp(policy, LABEL_ACCEPT) == 0)
t->verdict = -NF_ACCEPT - 1;
- else if (strcmp(policy, IPTC_LABEL_DROP) == 0)
+ else if (strcmp(policy, LABEL_DROP) == 0)
t->verdict = -NF_DROP - 1;
else {
errno = EINVAL;
@@ -1559,34 +1425,34 @@ iptc_set_policy(const ipt_chainlabel chain,
}
/* Without this, on gcc 2.7.2.3, we get:
- libiptc.c: In function `iptc_commit':
+ libiptc.c: In function `TC_COMMIT':
libiptc.c:833: fixed or forbidden register was spilled.
This may be due to a compiler bug or to impossible asm
statements or clauses.
*/
static void
-subtract_counters(struct ipt_counters *answer,
- const struct ipt_counters *a,
- const struct ipt_counters *b)
+subtract_counters(STRUCT_COUNTERS *answer,
+ const STRUCT_COUNTERS *a,
+ const STRUCT_COUNTERS *b)
{
answer->pcnt = a->pcnt - b->pcnt;
answer->bcnt = a->bcnt - b->bcnt;
}
int
-iptc_commit(iptc_handle_t *handle)
+TC_COMMIT(TC_HANDLE_T *handle)
{
/* Replace, then map back the counters. */
- struct ipt_replace *repl;
- struct ipt_counters_info *newcounters;
+ STRUCT_REPLACE *repl;
+ STRUCT_COUNTERS_INFO *newcounters;
unsigned int i;
size_t counterlen
- = sizeof(struct ipt_counters_info)
- + sizeof(struct ipt_counters) * (*handle)->new_number;
+ = sizeof(STRUCT_COUNTERS_INFO)
+ + sizeof(STRUCT_COUNTERS) * (*handle)->new_number;
CHECK(*handle);
#if 0
- dump_entries(*handle);
+ TC_TC_DUMP_ENTRIES(*handle);
#endif
/* Don't commit if nothing changed. */
@@ -1600,7 +1466,7 @@ iptc_commit(iptc_handle_t *handle)
}
/* These are the old counters we will get from kernel */
- repl->counters = malloc(sizeof(struct ipt_counters)
+ repl->counters = malloc(sizeof(STRUCT_COUNTERS)
* (*handle)->info.num_entries);
if (!repl->counters) {
free(repl);
@@ -1629,7 +1495,7 @@ iptc_commit(iptc_handle_t *handle)
memcpy(repl->entries, (*handle)->entries.entries,
(*handle)->entries.size);
- if (setsockopt(sockfd, IPPROTO_IP, IPT_SO_SET_REPLACE, repl,
+ if (setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl,
sizeof(*repl) + (*handle)->entries.size) < 0) {
free(repl->counters);
free(repl);
@@ -1645,7 +1511,7 @@ iptc_commit(iptc_handle_t *handle)
switch ((*handle)->counter_map[i].maptype) {
case COUNTER_MAP_NOMAP:
newcounters->counters[i]
- = ((struct ipt_counters){ 0, 0 });
+ = ((STRUCT_COUNTERS){ 0, 0 });
break;
case COUNTER_MAP_NORMAL_MAP:
@@ -1674,8 +1540,8 @@ iptc_commit(iptc_handle_t *handle)
}
}
- if (setsockopt(sockfd, IPPROTO_IP, IPT_SO_SET_ADD_COUNTERS,
- newcounters, counterlen) < 0) {
+ if (setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS,
+ newcounters, counterlen) < 0) {
free(repl->counters);
free(repl);
free(newcounters);
@@ -1696,14 +1562,14 @@ iptc_commit(iptc_handle_t *handle)
/* Get raw socket. */
int
-iptc_get_raw_socket()
+TC_GET_RAW_SOCKET()
{
return sockfd;
}
/* Translates errno numbers into more human-readable form than strerror. */
const char *
-iptc_strerror(int err)
+TC_STRERROR(int err)
{
unsigned int i;
struct table_struct {
@@ -1715,27 +1581,27 @@ iptc_strerror(int err)
{ NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
{ NULL, ENOSYS, "Will be implemented real soon. I promise." },
{ NULL, ENOMEM, "Memory allocation problem" },
- { iptc_init, EPERM, "Permission denied (you must be root)" },
- { iptc_init, EINVAL, "Module is wrong version" },
- { iptc_delete_chain, ENOTEMPTY, "Chain is not empty" },
- { iptc_delete_chain, EINVAL, "Can't delete built-in chain" },
- { iptc_delete_chain, EMLINK,
+ { TC_INIT, EPERM, "Permission denied (you must be root)" },
+ { TC_INIT, EINVAL, "Module is wrong version" },
+ { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" },
+ { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" },
+ { TC_DELETE_CHAIN, EMLINK,
"Can't delete chain with references left" },
- { iptc_create_chain, EEXIST, "Chain already exists" },
- { iptc_insert_entry, E2BIG, "Index of insertion too big" },
- { iptc_replace_entry, E2BIG, "Index of replacement too big" },
- { iptc_delete_num_entry, E2BIG, "Index of deletion too big" },
- { iptc_insert_entry, ELOOP, "Loop found in table" },
- { iptc_insert_entry, EINVAL, "Target problem" },
+ { TC_CREATE_CHAIN, EEXIST, "Chain already exists" },
+ { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" },
+ { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" },
+ { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" },
+ { TC_INSERT_ENTRY, ELOOP, "Loop found in table" },
+ { TC_INSERT_ENTRY, EINVAL, "Target problem" },
/* EINVAL for CHECK probably means bad interface. */
- { iptc_check_packet, EINVAL,
+ { TC_CHECK_PACKET, EINVAL,
"Bad arguments (does that interface exist?)" },
/* ENOENT for DELETE probably means no matching rule */
- { iptc_delete_entry, ENOENT,
+ { TC_DELETE_ENTRY, ENOENT,
"Bad rule (does a matching rule exist in that chain?)" },
- { iptc_set_policy, ENOENT,
+ { TC_SET_POLICY, ENOENT,
"Bad built-in chain name" },
- { iptc_set_policy, EINVAL,
+ { TC_SET_POLICY, EINVAL,
"Bad policy name" },
{ NULL, ENOENT, "No extended target/match by that name" }
};
@@ -1748,218 +1614,3 @@ iptc_strerror(int err)
return strerror(err);
}
-
-/***************************** DEBUGGING ********************************/
-static inline int
-unconditional(const struct ipt_ip *ip)
-{
- unsigned int i;
-
- for (i = 0; i < sizeof(*ip)/sizeof(u_int32_t); i++)
- if (((u_int32_t *)ip)[i])
- return 0;
-
- return 1;
-}
-
-static inline int
-check_match(const struct ipt_entry_match *m, unsigned int *off)
-{
- assert(m->u.match_size >= sizeof(struct ipt_entry_match));
- assert(IPT_ALIGN(m->u.match_size) == m->u.match_size);
-
- (*off) += m->u.match_size;
- return 0;
-}
-
-static inline int
-check_entry(const struct ipt_entry *e, unsigned int *i, unsigned int *off,
- unsigned int user_offset, int *was_return,
- iptc_handle_t h)
-{
- unsigned int toff;
- struct ipt_standard_target *t;
-
- assert(e->target_offset >= sizeof(struct ipt_entry));
- assert(e->next_offset >= e->target_offset
- + sizeof(struct ipt_entry_target));
- toff = sizeof(struct ipt_entry);
- IPT_MATCH_ITERATE(e, check_match, &toff);
-
- assert(toff == e->target_offset);
-
- t = (struct ipt_standard_target *)
- ipt_get_target((struct ipt_entry *)e);
- /* next_offset will have to be multiple of entry alignment. */
- assert(e->next_offset == IPT_ALIGN(e->next_offset));
- assert(e->target_offset == IPT_ALIGN(e->target_offset));
- assert(t->target.u.target_size == IPT_ALIGN(t->target.u.target_size));
- assert(!iptc_is_chain(t->target.u.user.name, h));
-
- if (strcmp(t->target.u.user.name, IPT_STANDARD_TARGET) == 0) {
- assert(t->target.u.target_size
- == IPT_ALIGN(sizeof(struct ipt_standard_target)));
-
- assert(t->verdict == -NF_DROP-1
- || t->verdict == -NF_ACCEPT-1
- || t->verdict == IPT_RETURN
- || t->verdict < (int)h->entries.size);
-
- if (t->verdict >= 0) {
- struct ipt_entry *te = get_entry(h, t->verdict);
- int idx;
-
- idx = entry2index(h, te);
- assert(strcmp(ipt_get_target(te)->u.user.name,
- IPT_ERROR_TARGET)
- != 0);
- assert(te != e);
-
- /* Prior node must be error node, or this node. */
- assert(t->verdict == entry2offset(h, e)+e->next_offset
- || strcmp(ipt_get_target(index2entry(h, idx-1))
- ->u.user.name, IPT_ERROR_TARGET)
- == 0);
- }
-
- if (t->verdict == IPT_RETURN
- && unconditional(&e->ip)
- && e->target_offset == sizeof(*e))
- *was_return = 1;
- else
- *was_return = 0;
- } else if (strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0) {
- assert(t->target.u.target_size
- == IPT_ALIGN(sizeof(struct ipt_error_target)));
-
- /* If this is in user area, previous must have been return */
- if (*off > user_offset)
- assert(*was_return);
-
- *was_return = 0;
- }
- else *was_return = 0;
-
- if (*off == user_offset)
- assert(strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0);
-
- (*off) += e->next_offset;
- (*i)++;
- return 0;
-}
-
-#ifndef NDEBUG
-/* Do every conceivable sanity check on the handle */
-static void
-do_check(iptc_handle_t h, unsigned int line)
-{
- unsigned int i, n;
- unsigned int user_offset; /* Offset of first user chain */
- int was_return;
-
- assert(h->changed == 0 || h->changed == 1);
- if (strcmp(h->info.name, "filter") == 0) {
- assert(h->info.valid_hooks
- == (1 << NF_IP_LOCAL_IN
- | 1 << NF_IP_FORWARD
- | 1 << NF_IP_LOCAL_OUT));
-
- /* Hooks should be first three */
- assert(h->info.hook_entry[NF_IP_LOCAL_IN] == 0);
-
- n = get_chain_end(h, 0);
- n += get_entry(h, n)->next_offset;
- assert(h->info.hook_entry[NF_IP_FORWARD] == n);
-
- n = get_chain_end(h, n);
- n += get_entry(h, n)->next_offset;
- assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
-
- user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
- } else if (strcmp(h->info.name, "nat") == 0) {
- assert(h->info.valid_hooks
- == (1 << NF_IP_PRE_ROUTING
- | 1 << NF_IP_POST_ROUTING
- | 1 << NF_IP_LOCAL_OUT));
-
- assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0);
-
- n = get_chain_end(h, 0);
- n += get_entry(h, n)->next_offset;
- assert(h->info.hook_entry[NF_IP_POST_ROUTING] == n);
-
- n = get_chain_end(h, n);
- n += get_entry(h, n)->next_offset;
- assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
-
- user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
- } else if (strcmp(h->info.name, "mangle") == 0) {
- assert(h->info.valid_hooks
- == (1 << NF_IP_PRE_ROUTING
- | 1 << NF_IP_LOCAL_OUT));
-
- /* Hooks should be first three */
- assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0);
-
- n = get_chain_end(h, 0);
- n += get_entry(h, n)->next_offset;
- assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
-
- user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
- } else
- abort();
-
- /* User chain == end of last builtin + policy entry */
- user_offset = get_chain_end(h, user_offset);
- user_offset += get_entry(h, user_offset)->next_offset;
-
- /* Overflows should be end of entry chains, and unconditional
- policy nodes. */
- for (i = 0; i < NF_IP_NUMHOOKS; i++) {
- struct ipt_entry *e;
- struct ipt_standard_target *t;
-
- if (!(h->info.valid_hooks & (1 << i)))
- continue;
- assert(h->info.underflow[i]
- == get_chain_end(h, h->info.hook_entry[i]));
-
- e = get_entry(h, get_chain_end(h, h->info.hook_entry[i]));
- assert(unconditional(&e->ip));
- assert(e->target_offset == sizeof(*e));
- assert(e->next_offset == sizeof(*e) + sizeof(*t));
- t = (struct ipt_standard_target *)ipt_get_target(e);
-
- assert(strcmp(t->target.u.user.name, IPT_STANDARD_TARGET)==0);
- assert(t->verdict == -NF_DROP-1 || t->verdict == -NF_ACCEPT-1);
-
- /* Hooks and underflows must be valid entries */
- entry2index(h, get_entry(h, h->info.hook_entry[i]));
- entry2index(h, get_entry(h, h->info.underflow[i]));
- }
-
- assert(h->info.size
- >= h->info.num_entries * (sizeof(struct ipt_entry)
- +sizeof(struct ipt_standard_target)));
-
- assert(h->entries.size
- >= (h->new_number
- * (sizeof(struct ipt_entry)
- + sizeof(struct ipt_standard_target))));
- assert(strcmp(h->info.name, h->entries.name) == 0);
-
- i = 0; n = 0;
- was_return = 0;
- /* Check all the entries. */
- IPT_ENTRY_ITERATE(h->entries.entries, h->entries.size,
- check_entry, &i, &n, user_offset, &was_return, h);
-
- assert(i == h->new_number);
- assert(n == h->entries.size);
-
- /* Final entry must be error node */
- assert(strcmp(ipt_get_target(index2entry(h, h->new_number-1))
- ->u.user.name,
- IPT_ERROR_TARGET) == 0);
-}
-#endif /*NDEBUG*/