libip4tc.c revision e37d45ce390c2f5a7f1e64742b9100ecef0def54
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Library which manipulates firewall rules.  Version 0.1. */
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Architecture of firewall rules is as follows:
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Chains go INPUT, FORWARD, OUTPUT then user chains.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Each user chain starts with an ERROR node.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Every chain ends with an unconditional jump: a RETURN for user chains,
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * and a POLICY for built-ins.
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)   COPYING for details). */
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <assert.h>
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <string.h>
16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include <errno.h>
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_CONNTRACK
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#define inline
23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(__ANDROID__) && (!defined(__GLIBC__) || (__GLIBC__ < 2))
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef unsigned int socklen_t;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "libiptc/libiptc.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IP_VERSION	4
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IP_OFFSET	0x1FFF
3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define HOOK_PRE_ROUTING	NF_IP_PRE_ROUTING
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define HOOK_LOCAL_IN		NF_IP_LOCAL_IN
3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define HOOK_FORWARD		NF_IP_FORWARD
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define HOOK_LOCAL_OUT		NF_IP_LOCAL_OUT
3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define HOOK_POST_ROUTING	NF_IP_POST_ROUTING
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#ifdef NF_IP_DROPPING
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define HOOK_DROPPING		NF_IP_DROPPING
4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define STRUCT_ENTRY_TARGET	struct ipt_entry_target
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define STRUCT_ENTRY		struct ipt_entry
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STRUCT_ENTRY_MATCH	struct ipt_entry_match
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STRUCT_GETINFO		struct ipt_getinfo
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STRUCT_GET_ENTRIES	struct ipt_get_entries
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define STRUCT_COUNTERS		struct ipt_counters
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#define STRUCT_COUNTERS_INFO	struct ipt_counters_info
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define STRUCT_STANDARD_TARGET	struct ipt_standard_target
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STRUCT_REPLACE		struct ipt_replace
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STRUCT_TC_HANDLE	struct iptc_handle
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define xtc_handle		iptc_handle
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define ENTRY_ITERATE		IPT_ENTRY_ITERATE
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TABLE_MAXNAMELEN	IPT_TABLE_MAXNAMELEN
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FUNCTION_MAXNAMELEN	IPT_FUNCTION_MAXNAMELEN
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GET_TARGET		ipt_get_target
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ERROR_TARGET		IPT_ERROR_TARGET
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NUMHOOKS		NF_IP_NUMHOOKS
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define IPT_CHAINLABEL		ipt_chainlabel
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define TC_DUMP_ENTRIES		dump_entries
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TC_IS_CHAIN		iptc_is_chain
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_FIRST_CHAIN		iptc_first_chain
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_NEXT_CHAIN		iptc_next_chain
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_FIRST_RULE		iptc_first_rule
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_NEXT_RULE		iptc_next_rule
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_GET_TARGET		iptc_get_target
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_BUILTIN		iptc_builtin
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_GET_POLICY		iptc_get_policy
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_INSERT_ENTRY		iptc_insert_entry
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_REPLACE_ENTRY	iptc_replace_entry
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_APPEND_ENTRY		iptc_append_entry
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_CHECK_ENTRY		iptc_check_entry
80a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define TC_DELETE_ENTRY		iptc_delete_entry
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_DELETE_NUM_ENTRY	iptc_delete_num_entry
82a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define TC_FLUSH_ENTRIES	iptc_flush_entries
83a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define TC_ZERO_ENTRIES		iptc_zero_entries
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_READ_COUNTER		iptc_read_counter
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_ZERO_COUNTER		iptc_zero_counter
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_SET_COUNTER		iptc_set_counter
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_CREATE_CHAIN		iptc_create_chain
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_GET_REFERENCES	iptc_get_references
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_DELETE_CHAIN		iptc_delete_chain
90a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define TC_RENAME_CHAIN		iptc_rename_chain
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_SET_POLICY		iptc_set_policy
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_GET_RAW_SOCKET	iptc_get_raw_socket
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_INIT			iptc_init
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_FREE			iptc_free
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_COMMIT		iptc_commit
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_STRERROR		iptc_strerror
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_NUM_RULES		iptc_num_rules
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_GET_RULE		iptc_get_rule
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_AF			AF_INET
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TC_IPPROTO		IPPROTO_IP
102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SO_SET_REPLACE		IPT_SO_SET_REPLACE
104a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define SO_SET_ADD_COUNTERS	IPT_SO_SET_ADD_COUNTERS
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SO_GET_INFO		IPT_SO_GET_INFO
106a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define SO_GET_ENTRIES		IPT_SO_GET_ENTRIES
107a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define SO_GET_VERSION		IPT_SO_GET_VERSION
108a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
109a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define STANDARD_TARGET		IPT_STANDARD_TARGET
110a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define LABEL_RETURN		IPTC_LABEL_RETURN
111a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define LABEL_ACCEPT		IPTC_LABEL_ACCEPT
112a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define LABEL_DROP		IPTC_LABEL_DROP
113a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define LABEL_QUEUE		IPTC_LABEL_QUEUE
114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
115a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define ALIGN			XT_ALIGN
116a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define RETURN			IPT_RETURN
117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "libiptc.c"
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define IP_PARTS_NATIVE(n)			\
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)(unsigned int)((n)>>24)&0xFF,			\
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)(unsigned int)((n)>>16)&0xFF,			\
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)(unsigned int)((n)>>8)&0xFF,			\
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(unsigned int)((n)&0xFF)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n))
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
129a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)dump_entry(struct ipt_entry *e, struct iptc_handle *const handle)
130a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles){
131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	size_t i;
132a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	STRUCT_ENTRY_TARGET *t;
133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	printf("Entry %u (%lu):\n", iptcb_entry2index(handle, e),
135a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	       iptcb_entry2offset(handle, e));
136a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	printf("SRC IP: %u.%u.%u.%u/%u.%u.%u.%u\n",
137a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	       IP_PARTS(e->ip.src.s_addr),IP_PARTS(e->ip.smsk.s_addr));
138a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	printf("DST IP: %u.%u.%u.%u/%u.%u.%u.%u\n",
139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	       IP_PARTS(e->ip.dst.s_addr),IP_PARTS(e->ip.dmsk.s_addr));
140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	printf("Interface: `%s'/", e->ip.iniface);
141a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	for (i = 0; i < IFNAMSIZ; i++)
142a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		printf("%c", e->ip.iniface_mask[i] ? 'X' : '.');
143a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	printf("to `%s'/", e->ip.outiface);
144a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	for (i = 0; i < IFNAMSIZ; i++)
145a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		printf("%c", e->ip.outiface_mask[i] ? 'X' : '.');
146a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	printf("\nProtocol: %u\n", e->ip.proto);
147a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	printf("Flags: %02X\n", e->ip.flags);
148a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	printf("Invflags: %02X\n", e->ip.invflags);
149a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	printf("Counters: %llu packets, %llu bytes\n",
150a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	       (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
151a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	printf("Cache: %08X\n", e->nfcache);
152a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
153a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	IPT_MATCH_ITERATE(e, print_match);
154a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
155a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	t = GET_TARGET(e);
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	printf("Target name: `%s' [%u]\n", t->u.user.name, t->u.target_size);
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if (strcmp(t->u.user.name, STANDARD_TARGET) == 0) {
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		const unsigned char *data = t->data;
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		int pos = *(const int *)data;
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		if (pos < 0)
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			printf("verdict=%s\n",
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			       pos == -NF_ACCEPT-1 ? "NF_ACCEPT"
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			       : pos == -NF_DROP-1 ? "NF_DROP"
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			       : pos == -NF_QUEUE-1 ? "NF_QUEUE"
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			       : pos == RETURN ? "RETURN"
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			       : "UNKNOWN");
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		else
168a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			printf("verdict=%u\n", pos);
169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	} else if (strcmp(t->u.user.name, IPT_ERROR_TARGET) == 0)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		printf("error=`%s'\n", t->data);
171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	printf("\n");
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned char *
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b, unsigned char *matchmask)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	unsigned int i;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned char *mptr;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Always compare head structures: ignore mask here. */
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (a->ip.src.s_addr != b->ip.src.s_addr
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    || a->ip.dst.s_addr != b->ip.dst.s_addr
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    || a->ip.smsk.s_addr != b->ip.smsk.s_addr
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    || a->ip.dmsk.s_addr != b->ip.dmsk.s_addr
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	    || a->ip.proto != b->ip.proto
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    || a->ip.flags != b->ip.flags
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    || a->ip.invflags != b->ip.invflags)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < IFNAMSIZ; i++) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (a->ip.iniface_mask[i] != b->ip.iniface_mask[i])
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return NULL;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if ((a->ip.iniface[i] & a->ip.iniface_mask[i])
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    != (b->ip.iniface[i] & b->ip.iniface_mask[i]))
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return NULL;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (a->ip.outiface_mask[i] != b->ip.outiface_mask[i])
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return NULL;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if ((a->ip.outiface[i] & a->ip.outiface_mask[i])
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		    != (b->ip.outiface[i] & b->ip.outiface_mask[i]))
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return NULL;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (a->target_offset != b->target_offset
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    || a->next_offset != b->next_offset)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	mptr = matchmask + sizeof(STRUCT_ENTRY);
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		return NULL;
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	mptr += XT_ALIGN(sizeof(struct ipt_entry_target));
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	return mptr;
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if 0
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/***************************** DEBUGGING ********************************/
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static inline int
22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)unconditional(const struct ipt_ip *ip)
22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles){
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned int i;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < sizeof(*ip)/sizeof(uint32_t); i++)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (((uint32_t *)ip)[i])
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return 0;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 1;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
230a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int
232a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)check_match(const STRUCT_ENTRY_MATCH *m, unsigned int *off)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	assert(m->u.match_size >= sizeof(STRUCT_ENTRY_MATCH));
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	assert(ALIGN(m->u.match_size) == m->u.match_size);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(*off) += m->u.match_size;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)check_entry(const STRUCT_ENTRY *e, unsigned int *i, unsigned int *off,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    unsigned int user_offset, int *was_return,
244a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	    struct iptc_handle *h)
245a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles){
246a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	unsigned int toff;
247a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	STRUCT_STANDARD_TARGET *t;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	assert(e->target_offset >= sizeof(STRUCT_ENTRY));
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	assert(e->next_offset >= e->target_offset
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       + sizeof(STRUCT_ENTRY_TARGET));
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	toff = sizeof(STRUCT_ENTRY);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	IPT_MATCH_ITERATE(e, check_match, &toff);
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	assert(toff == e->target_offset);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	t = (STRUCT_STANDARD_TARGET *)
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		GET_TARGET((STRUCT_ENTRY *)e);
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	/* next_offset will have to be multiple of entry alignment. */
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	assert(e->next_offset == ALIGN(e->next_offset));
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	assert(e->target_offset == ALIGN(e->target_offset));
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	assert(t->target.u.target_size == ALIGN(t->target.u.target_size));
263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	assert(!TC_IS_CHAIN(t->target.u.user.name, h));
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if (strcmp(t->target.u.user.name, STANDARD_TARGET) == 0) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(t->target.u.target_size
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       == ALIGN(sizeof(STRUCT_STANDARD_TARGET)));
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(t->verdict == -NF_DROP-1
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       || t->verdict == -NF_ACCEPT-1
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       || t->verdict == RETURN
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       || t->verdict < (int)h->entries->size);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (t->verdict >= 0) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			STRUCT_ENTRY *te = get_entry(h, t->verdict);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			int idx;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			idx = iptcb_entry2index(h, te);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			assert(strcmp(GET_TARGET(te)->u.user.name,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      IPT_ERROR_TARGET)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       != 0);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			assert(te != e);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			/* Prior node must be error node, or this node. */
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			assert(t->verdict == iptcb_entry2offset(h, e)+e->next_offset
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			       || strcmp(GET_TARGET(index2entry(h, idx-1))
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)					 ->u.user.name, IPT_ERROR_TARGET)
288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			       == 0);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		if (t->verdict == RETURN
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    && unconditional(&e->ip)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    && e->target_offset == sizeof(*e))
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			*was_return = 1;
295a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		else
296a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			*was_return = 0;
297a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	} else if (strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0) {
298a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		assert(t->target.u.target_size
299a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		       == ALIGN(sizeof(struct ipt_error_target)));
300a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
301a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		/* If this is in user area, previous must have been return */
302a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		if (*off > user_offset)
303a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			assert(*was_return);
304a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
305a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		*was_return = 0;
306a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	}
307a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	else *was_return = 0;
308a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
309a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	if (*off == user_offset)
310a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		assert(strcmp(t->target.u.user.name, IPT_ERROR_TARGET) == 0);
311a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
312a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	(*off) += e->next_offset;
313a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	(*i)++;
314a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	return 0;
315a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
316a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
317a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifdef IPTC_DEBUG
318a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)/* Do every conceivable sanity check on the handle */
319a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static void
320a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)do_check(struct iptc_handle *h, unsigned int line)
321a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles){
322a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	unsigned int i, n;
323a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	unsigned int user_offset; /* Offset of first user chain */
324a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	int was_return;
325a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
326a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	assert(h->changed == 0 || h->changed == 1);
327a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	if (strcmp(h->info.name, "filter") == 0) {
328a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		assert(h->info.valid_hooks
329a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		       == (1 << NF_IP_LOCAL_IN
330a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			   | 1 << NF_IP_FORWARD
331a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			   | 1 << NF_IP_LOCAL_OUT));
332a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
333a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		/* Hooks should be first three */
334a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		assert(h->info.hook_entry[NF_IP_LOCAL_IN] == 0);
335a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
336a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		n = get_chain_end(h, 0);
337a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		n += get_entry(h, n)->next_offset;
338a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		assert(h->info.hook_entry[NF_IP_FORWARD] == n);
339a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
340a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		n = get_chain_end(h, n);
341a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		n += get_entry(h, n)->next_offset;
342a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
343a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
344a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
345a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)	} else if (strcmp(h->info.name, "nat") == 0) {
346a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		assert((h->info.valid_hooks
347a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		        == (1 << NF_IP_PRE_ROUTING
348a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			    | 1 << NF_IP_POST_ROUTING
349a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			    | 1 << NF_IP_LOCAL_OUT)) ||
350a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		       (h->info.valid_hooks
351a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			== (1 << NF_IP_PRE_ROUTING
352a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			    | 1 << NF_IP_LOCAL_IN
353a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			    | 1 << NF_IP_POST_ROUTING
354a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			    | 1 << NF_IP_LOCAL_OUT)));
355a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
356a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0);
357a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
358a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		n = get_chain_end(h, 0);
359a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
360a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		n += get_entry(h, n)->next_offset;
361a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		assert(h->info.hook_entry[NF_IP_POST_ROUTING] == n);
362a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		n = get_chain_end(h, n);
363a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
36458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		n += get_entry(h, n)->next_offset;
36558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
36658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
36758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
36858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		if (h->info.valid_hooks & (1 << NF_IP_LOCAL_IN)) {
36958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			n = get_chain_end(h, n);
37058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			n += get_entry(h, n)->next_offset;
37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			assert(h->info.hook_entry[NF_IP_LOCAL_IN] == n);
37258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			user_offset = h->info.hook_entry[NF_IP_LOCAL_IN];
37358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		}
37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
37558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	} else if (strcmp(h->info.name, "mangle") == 0) {
376a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		/* This code is getting ugly because linux < 2.4.18-pre6 had
377a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		 * two mangle hooks, linux >= 2.4.18-pre6 has five mangle hooks
378a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		 * */
379a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		assert((h->info.valid_hooks
380a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			== (1 << NF_IP_PRE_ROUTING
381a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)			    | 1 << NF_IP_LOCAL_OUT)) ||
382a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		       (h->info.valid_hooks
3837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)			== (1 << NF_IP_PRE_ROUTING
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    | 1 << NF_IP_LOCAL_IN
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    | 1 << NF_IP_FORWARD
386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			    | 1 << NF_IP_LOCAL_OUT
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    | 1 << NF_IP_POST_ROUTING)));
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		/* Hooks should be first five */
39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0);
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		n = get_chain_end(h, 0);
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		if (h->info.valid_hooks & (1 << NF_IP_LOCAL_IN)) {
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			n += get_entry(h, n)->next_offset;
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			assert(h->info.hook_entry[NF_IP_LOCAL_IN] == n);
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			n = get_chain_end(h, n);
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		}
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (h->info.valid_hooks & (1 << NF_IP_FORWARD)) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			n += get_entry(h, n)->next_offset;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			assert(h->info.hook_entry[NF_IP_FORWARD] == n);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			n = get_chain_end(h, n);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
4057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		n += get_entry(h, n)->next_offset;
4077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)		assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
4087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)		user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (h->info.valid_hooks & (1 << NF_IP_POST_ROUTING)) {
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			n = get_chain_end(h, n);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			n += get_entry(h, n)->next_offset;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			assert(h->info.hook_entry[NF_IP_POST_ROUTING] == n);
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			user_offset = h->info.hook_entry[NF_IP_POST_ROUTING];
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	} else if (strcmp(h->info.name, "raw") == 0) {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(h->info.valid_hooks
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       == (1 << NF_IP_PRE_ROUTING
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   | 1 << NF_IP_LOCAL_OUT));
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* Hooks should be first three */
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		n = get_chain_end(h, n);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		n += get_entry(h, n)->next_offset;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT];
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NF_IP_DROPPING
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else if (strcmp(h->info.name, "drop") == 0) {
432a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		assert(h->info.valid_hooks == (1 << NF_IP_DROPPING));
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
434a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		/* Hook should be first */
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(h->info.hook_entry[NF_IP_DROPPING] == 0);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		user_offset = 0;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	} else {
4394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		fprintf(stderr, "Unknown table `%s'\n", h->info.name);
440f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		abort();
441f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	}
442f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	/* User chain == end of last builtin + policy entry */
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	user_offset = get_chain_end(h, user_offset);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	user_offset += get_entry(h, user_offset)->next_offset;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Overflows should be end of entry chains, and unconditional
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           policy nodes. */
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < NUMHOOKS; i++) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		STRUCT_ENTRY *e;
451a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)		STRUCT_STANDARD_TARGET *t;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (!(h->info.valid_hooks & (1 << i)))
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			continue;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(h->info.underflow[i]
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       == get_chain_end(h, h->info.hook_entry[i]));
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		e = get_entry(h, get_chain_end(h, h->info.hook_entry[i]));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(unconditional(&e->ip));
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(e->target_offset == sizeof(*e));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(t->target.u.target_size == ALIGN(sizeof(*t)));
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(e->next_offset == sizeof(*e) + ALIGN(sizeof(*t)));
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(strcmp(t->target.u.user.name, STANDARD_TARGET)==0);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		assert(t->verdict == -NF_DROP-1 || t->verdict == -NF_ACCEPT-1);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* Hooks and underflows must be valid entries */
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		entry2index(h, get_entry(h, h->info.hook_entry[i]));
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		entry2index(h, get_entry(h, h->info.underflow[i]));
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	assert(h->info.size
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       >= h->info.num_entries * (sizeof(STRUCT_ENTRY)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 +sizeof(STRUCT_STANDARD_TARGET)));
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	assert(h->entries.size
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	       >= (h->new_number
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   * (sizeof(STRUCT_ENTRY)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      + sizeof(STRUCT_STANDARD_TARGET))));
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	assert(strcmp(h->info.name, h->entries.name) == 0);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	i = 0; n = 0;
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	was_return = 0;
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	/* Check all the entries. */
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	ENTRY_ITERATE(h->entries.entrytable, h->entries.size,
48758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		      check_entry, &i, &n, user_offset, &was_return, h);
48858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	assert(i == h->new_number);
49058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	assert(n == h->entries.size);
49158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
49258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	/* Final entry must be error node */
49358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	assert(strcmp(GET_TARGET(index2entry(h, h->new_number-1))
49458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		      ->u.user.name,
49558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		      ERROR_TARGET) == 0);
49658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /*IPTC_DEBUG*/
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)