1ecfcd5655758955d8958dc2a7a7b2c8eff2395b7Sebastian Redl/* Library which manipulates firewall rules.  Version 0.1. */
220093b4bf698f292c664676987541d5103b65b15Douglas Gregor
320093b4bf698f292c664676987541d5103b65b15Douglas Gregor/* Architecture of firewall rules is as follows:
420093b4bf698f292c664676987541d5103b65b15Douglas Gregor *
520093b4bf698f292c664676987541d5103b65b15Douglas Gregor * Chains go INPUT, FORWARD, OUTPUT then user chains.
620093b4bf698f292c664676987541d5103b65b15Douglas Gregor * Each user chain starts with an ERROR node.
720093b4bf698f292c664676987541d5103b65b15Douglas Gregor * Every chain ends with an unconditional jump: a RETURN for user chains,
820093b4bf698f292c664676987541d5103b65b15Douglas Gregor * and a POLICY for built-ins.
920093b4bf698f292c664676987541d5103b65b15Douglas Gregor */
1020093b4bf698f292c664676987541d5103b65b15Douglas Gregor
1120093b4bf698f292c664676987541d5103b65b15Douglas Gregor/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
1220093b4bf698f292c664676987541d5103b65b15Douglas Gregor   COPYING for details). */
13e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor
14e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include <assert.h>
1520093b4bf698f292c664676987541d5103b65b15Douglas Gregor#include <string.h>
16120d63cd4465230c2cd56508c7cd8e0ad00848e7John McCall#include <errno.h>
17e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include <stdlib.h>
18d6542d8efcf8389c3aab764f9e29ac284e16eda6Douglas Gregor#include <stdio.h>
19b13b737a2450167c82e148590e8019b839ce6b98John McCall#include <unistd.h>
2020093b4bf698f292c664676987541d5103b65b15Douglas Gregor#include <arpa/inet.h>
2120093b4bf698f292c664676987541d5103b65b15Douglas Gregor
2220093b4bf698f292c664676987541d5103b65b15Douglas Gregor#ifdef DEBUG_CONNTRACK
2320093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define inline
2420093b4bf698f292c664676987541d5103b65b15Douglas Gregor#endif
2520093b4bf698f292c664676987541d5103b65b15Douglas Gregor
2620093b4bf698f292c664676987541d5103b65b15Douglas Gregor#if !defined(__ANDROID__) && (!defined(__GLIBC__) || (__GLIBC__ < 2))
2720093b4bf698f292c664676987541d5103b65b15Douglas Gregortypedef unsigned int socklen_t;
2820093b4bf698f292c664676987541d5103b65b15Douglas Gregor#endif
2920093b4bf698f292c664676987541d5103b65b15Douglas Gregor
3020093b4bf698f292c664676987541d5103b65b15Douglas Gregor#include "libiptc/libip6tc.h"
3120093b4bf698f292c664676987541d5103b65b15Douglas Gregor
3220093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define HOOK_PRE_ROUTING	NF_IP6_PRE_ROUTING
3320093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define HOOK_LOCAL_IN		NF_IP6_LOCAL_IN
3420093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define HOOK_FORWARD		NF_IP6_FORWARD
3520093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define HOOK_LOCAL_OUT		NF_IP6_LOCAL_OUT
3620093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define HOOK_POST_ROUTING	NF_IP6_POST_ROUTING
3720093b4bf698f292c664676987541d5103b65b15Douglas Gregor
3820093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define STRUCT_ENTRY_TARGET	struct ip6t_entry_target
3920093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define STRUCT_ENTRY		struct ip6t_entry
4020093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define STRUCT_ENTRY_MATCH	struct ip6t_entry_match
4120093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define STRUCT_GETINFO		struct ip6t_getinfo
4220093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define STRUCT_GET_ENTRIES	struct ip6t_get_entries
4320093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define STRUCT_COUNTERS		struct ip6t_counters
4420093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define STRUCT_COUNTERS_INFO	struct ip6t_counters_info
4520093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define STRUCT_STANDARD_TARGET	struct ip6t_standard_target
4620093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define STRUCT_REPLACE		struct ip6t_replace
4720093b4bf698f292c664676987541d5103b65b15Douglas Gregor
4820093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define STRUCT_TC_HANDLE	struct ip6tc_handle
4920093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define xtc_handle		ip6tc_handle
5020093b4bf698f292c664676987541d5103b65b15Douglas Gregor
51a729bbb739ca97a8dc52b6b0495725590a0367dcAnders Carlsson#define ENTRY_ITERATE		IP6T_ENTRY_ITERATE
52a729bbb739ca97a8dc52b6b0495725590a0367dcAnders Carlsson#define TABLE_MAXNAMELEN	IP6T_TABLE_MAXNAMELEN
53a729bbb739ca97a8dc52b6b0495725590a0367dcAnders Carlsson#define FUNCTION_MAXNAMELEN	IP6T_FUNCTION_MAXNAMELEN
54a729bbb739ca97a8dc52b6b0495725590a0367dcAnders Carlsson
55a729bbb739ca97a8dc52b6b0495725590a0367dcAnders Carlsson#define GET_TARGET		ip6t_get_target
5618ef5e28a9a2677f8b1dce1fb2638d66e0a1621fDouglas Gregor
5718ef5e28a9a2677f8b1dce1fb2638d66e0a1621fDouglas Gregor#define ERROR_TARGET		IP6T_ERROR_TARGET
5818ef5e28a9a2677f8b1dce1fb2638d66e0a1621fDouglas Gregor#define NUMHOOKS		NF_IP6_NUMHOOKS
5920093b4bf698f292c664676987541d5103b65b15Douglas Gregor
6020093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define IPT_CHAINLABEL		ip6t_chainlabel
6120093b4bf698f292c664676987541d5103b65b15Douglas Gregor
6220093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define TC_DUMP_ENTRIES		dump_entries6
634171766318a2564fbc9a739be0a2851f441c0d29Sean Hunt#define TC_IS_CHAIN		ip6tc_is_chain
64059ce0d92eb5a7da900ae735dc0a2ea3d64f4b0bSean Hunt#define TC_FIRST_CHAIN		ip6tc_first_chain
65d3d824d45c32d457493e7cb79cc34a4761afb760Anders Carlsson#define TC_NEXT_CHAIN		ip6tc_next_chain
66cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor#define TC_FIRST_RULE		ip6tc_first_rule
67310b1c421665241d9b135c517d5031716d4a3221Fariborz Jahanian#define TC_NEXT_RULE		ip6tc_next_rule
68310b1c421665241d9b135c517d5031716d4a3221Fariborz Jahanian#define TC_GET_TARGET		ip6tc_get_target
69310b1c421665241d9b135c517d5031716d4a3221Fariborz Jahanian#define TC_BUILTIN		ip6tc_builtin
700c706c29f20b6fa36759fa41333b9c3ec0bd2969Eli Friedman#define TC_GET_POLICY		ip6tc_get_policy
710c706c29f20b6fa36759fa41333b9c3ec0bd2969Eli Friedman#define TC_INSERT_ENTRY		ip6tc_insert_entry
720c706c29f20b6fa36759fa41333b9c3ec0bd2969Eli Friedman#define TC_REPLACE_ENTRY	ip6tc_replace_entry
734773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor#define TC_APPEND_ENTRY		ip6tc_append_entry
744773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor#define TC_CHECK_ENTRY		ip6tc_check_entry
754773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor#define TC_DELETE_ENTRY		ip6tc_delete_entry
764773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor#define TC_DELETE_NUM_ENTRY	ip6tc_delete_num_entry
7720093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define TC_FLUSH_ENTRIES	ip6tc_flush_entries
7820093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define TC_ZERO_ENTRIES		ip6tc_zero_entries
7920093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define TC_ZERO_COUNTER		ip6tc_zero_counter
8020093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define TC_READ_COUNTER		ip6tc_read_counter
8120093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define TC_SET_COUNTER		ip6tc_set_counter
8220093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define TC_CREATE_CHAIN		ip6tc_create_chain
83cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor#define TC_GET_REFERENCES	ip6tc_get_references
84cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor#define TC_DELETE_CHAIN		ip6tc_delete_chain
85cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor#define TC_RENAME_CHAIN		ip6tc_rename_chain
86cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor#define TC_SET_POLICY		ip6tc_set_policy
87d6542d8efcf8389c3aab764f9e29ac284e16eda6Douglas Gregor#define TC_GET_RAW_SOCKET	ip6tc_get_raw_socket
88d6542d8efcf8389c3aab764f9e29ac284e16eda6Douglas Gregor#define TC_INIT			ip6tc_init
8920093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define TC_FREE			ip6tc_free
9020093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define TC_COMMIT		ip6tc_commit
914773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor#define TC_STRERROR		ip6tc_strerror
92f85e193739c953358c865005855253af4f68a497John McCall#define TC_NUM_RULES		ip6tc_num_rules
9320093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define TC_GET_RULE		ip6tc_get_rule
94f85e193739c953358c865005855253af4f68a497John McCall
95f85e193739c953358c865005855253af4f68a497John McCall#define TC_AF			AF_INET6
96f85e193739c953358c865005855253af4f68a497John McCall#define TC_IPPROTO		IPPROTO_IPV6
97f85e193739c953358c865005855253af4f68a497John McCall
9820093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define SO_SET_REPLACE		IP6T_SO_SET_REPLACE
99ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor#define SO_SET_ADD_COUNTERS	IP6T_SO_SET_ADD_COUNTERS
100ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor#define SO_GET_INFO		IP6T_SO_GET_INFO
101ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor#define SO_GET_ENTRIES		IP6T_SO_GET_ENTRIES
102ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor#define SO_GET_VERSION		IP6T_SO_GET_VERSION
1033c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor
1044773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor#define STANDARD_TARGET		IP6T_STANDARD_TARGET
1053c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor#define LABEL_RETURN		IP6TC_LABEL_RETURN
1063c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor#define LABEL_ACCEPT		IP6TC_LABEL_ACCEPT
1073c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor#define LABEL_DROP		IP6TC_LABEL_DROP
1083c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor#define LABEL_QUEUE		IP6TC_LABEL_QUEUE
1093c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor
1104926d832aa2f0af9d7c00633727d49e7967eb978Douglas Gregor#define ALIGN			XT_ALIGN
1114926d832aa2f0af9d7c00633727d49e7967eb978Douglas Gregor#define RETURN			IP6T_RETURN
1123c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor
1133c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor#include "libiptc.c"
11420093b4bf698f292c664676987541d5103b65b15Douglas Gregor
11520093b4bf698f292c664676987541d5103b65b15Douglas Gregor#define BIT6(a, l) \
116711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson ((ntohl(a->s6_addr32[(l) / 32]) >> (31 - ((l) & 31))) & 1)
117711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson
118711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlssonint
119cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregoripv6_prefix_length(const struct in6_addr *a)
1200c706c29f20b6fa36759fa41333b9c3ec0bd2969Eli Friedman{
1210c706c29f20b6fa36759fa41333b9c3ec0bd2969Eli Friedman	int l, i;
1220c706c29f20b6fa36759fa41333b9c3ec0bd2969Eli Friedman	for (l = 0; l < 128; l++) {
123cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor		if (BIT6(a, l) == 0)
1244773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor			break;
1254773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor	}
1264773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor	for (i = l + 1; i < 128; i++) {
1274773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		if (BIT6(a, i) == 1)
1284773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor			return -1;
1294773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor	}
1304773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor	return l;
1314773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor}
13220093b4bf698f292c664676987541d5103b65b15Douglas Gregor
13320093b4bf698f292c664676987541d5103b65b15Douglas Gregorstatic int
13420093b4bf698f292c664676987541d5103b65b15Douglas Gregordump_entry(struct ip6t_entry *e, struct ip6tc_handle *const handle)
13520093b4bf698f292c664676987541d5103b65b15Douglas Gregor{
13620093b4bf698f292c664676987541d5103b65b15Douglas Gregor	size_t i;
13720093b4bf698f292c664676987541d5103b65b15Douglas Gregor	char buf[40];
138d6542d8efcf8389c3aab764f9e29ac284e16eda6Douglas Gregor	int len;
139606f65665421d594458e1409b4413005fb521c25Francois Pichet	struct ip6t_entry_target *t;
14020093b4bf698f292c664676987541d5103b65b15Douglas Gregor
141a188ff2d8a18140541fcd5884deda4552dac71a7Douglas Gregor	printf("Entry %u (%lu):\n", iptcb_entry2index(handle, e),
142a188ff2d8a18140541fcd5884deda4552dac71a7Douglas Gregor	       iptcb_entry2offset(handle, e));
143a188ff2d8a18140541fcd5884deda4552dac71a7Douglas Gregor	puts("SRC IP: ");
1443c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor	inet_ntop(AF_INET6, &e->ipv6.src, buf, sizeof buf);
1453c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor	puts(buf);
1463c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor	putchar('/');
1473c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor	len = ipv6_prefix_length(&e->ipv6.smsk);
1483c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor	if (len != -1)
1493c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor		printf("%d", len);
1503c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor	else {
15120093b4bf698f292c664676987541d5103b65b15Douglas Gregor		inet_ntop(AF_INET6, &e->ipv6.smsk, buf, sizeof buf);
15220093b4bf698f292c664676987541d5103b65b15Douglas Gregor		puts(buf);
153cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor	}
154d6542d8efcf8389c3aab764f9e29ac284e16eda6Douglas Gregor	putchar('\n');
155606f65665421d594458e1409b4413005fb521c25Francois Pichet
15620093b4bf698f292c664676987541d5103b65b15Douglas Gregor	puts("DST IP: ");
157cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor	inet_ntop(AF_INET6, &e->ipv6.dst, buf, sizeof buf);
158cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor	puts(buf);
159cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor	putchar('/');
160cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor	len = ipv6_prefix_length(&e->ipv6.dmsk);
1614773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor	if (len != -1)
1624773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		printf("%d", len);
1634773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor	else {
1644773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		inet_ntop(AF_INET6, &e->ipv6.dmsk, buf, sizeof buf);
1654773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		puts(buf);
1664773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor	}
1674773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor	putchar('\n');
1684773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor
16920093b4bf698f292c664676987541d5103b65b15Douglas Gregor	printf("Interface: `%s'/", e->ipv6.iniface);
17020093b4bf698f292c664676987541d5103b65b15Douglas Gregor	for (i = 0; i < IFNAMSIZ; i++)
17120093b4bf698f292c664676987541d5103b65b15Douglas Gregor		printf("%c", e->ipv6.iniface_mask[i] ? 'X' : '.');
17220093b4bf698f292c664676987541d5103b65b15Douglas Gregor	printf("to `%s'/", e->ipv6.outiface);
17320093b4bf698f292c664676987541d5103b65b15Douglas Gregor	for (i = 0; i < IFNAMSIZ; i++)
17420093b4bf698f292c664676987541d5103b65b15Douglas Gregor		printf("%c", e->ipv6.outiface_mask[i] ? 'X' : '.');
17520093b4bf698f292c664676987541d5103b65b15Douglas Gregor	printf("\nProtocol: %u\n", e->ipv6.proto);
176745da3a5bb4ea35f93f50301e7fbbb7d78d3b6bbFariborz Jahanian	if (e->ipv6.flags & IP6T_F_TOS)
177745da3a5bb4ea35f93f50301e7fbbb7d78d3b6bbFariborz Jahanian		printf("TOS: %u\n", e->ipv6.tos);
1784e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie	printf("Flags: %02X\n", e->ipv6.flags);
179f85e193739c953358c865005855253af4f68a497John McCall	printf("Invflags: %02X\n", e->ipv6.invflags);
180f85e193739c953358c865005855253af4f68a497John McCall	printf("Counters: %llu packets, %llu bytes\n",
181f85e193739c953358c865005855253af4f68a497John McCall	       (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
182f85e193739c953358c865005855253af4f68a497John McCall	printf("Cache: %08X\n", e->nfcache);
183f85e193739c953358c865005855253af4f68a497John McCall
184f85e193739c953358c865005855253af4f68a497John McCall	IP6T_MATCH_ITERATE(e, print_match);
185f85e193739c953358c865005855253af4f68a497John McCall
18682d1cc06ea533267e24ffe8b5885062ca062b479John McCall	t = ip6t_get_target(e);
18782d1cc06ea533267e24ffe8b5885062ca062b479John McCall	printf("Target name: `%s' [%u]\n", t->u.user.name, t->u.target_size);
188f85e193739c953358c865005855253af4f68a497John McCall	if (strcmp(t->u.user.name, IP6T_STANDARD_TARGET) == 0) {
18920093b4bf698f292c664676987541d5103b65b15Douglas Gregor		const unsigned char *data = t->data;
19020093b4bf698f292c664676987541d5103b65b15Douglas Gregor		int pos = *(const int *)data;
191a188ff2d8a18140541fcd5884deda4552dac71a7Douglas Gregor		if (pos < 0)
192a188ff2d8a18140541fcd5884deda4552dac71a7Douglas Gregor			printf("verdict=%s\n",
193745da3a5bb4ea35f93f50301e7fbbb7d78d3b6bbFariborz Jahanian			       pos == -NF_ACCEPT-1 ? "NF_ACCEPT"
194f85e193739c953358c865005855253af4f68a497John McCall			       : pos == -NF_DROP-1 ? "NF_DROP"
195f85e193739c953358c865005855253af4f68a497John McCall			       : pos == IP6T_RETURN ? "RETURN"
196688fc9b9b4323a294f5bf4f8a83f7c365edec573Douglas Gregor			       : "UNKNOWN");
197688fc9b9b4323a294f5bf4f8a83f7c365edec573Douglas Gregor		else
198745da3a5bb4ea35f93f50301e7fbbb7d78d3b6bbFariborz Jahanian			printf("verdict=%u\n", pos);
199688fc9b9b4323a294f5bf4f8a83f7c365edec573Douglas Gregor	} else if (strcmp(t->u.user.name, IP6T_ERROR_TARGET) == 0)
200f85e193739c953358c865005855253af4f68a497John McCall		printf("error=`%s'\n", t->data);
201688fc9b9b4323a294f5bf4f8a83f7c365edec573Douglas Gregor
202a188ff2d8a18140541fcd5884deda4552dac71a7Douglas Gregor	printf("\n");
203a188ff2d8a18140541fcd5884deda4552dac71a7Douglas Gregor	return 0;
20420093b4bf698f292c664676987541d5103b65b15Douglas Gregor}
20520093b4bf698f292c664676987541d5103b65b15Douglas Gregor
2063c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregorstatic unsigned char *
2073c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregoris_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b,
20820093b4bf698f292c664676987541d5103b65b15Douglas Gregor	unsigned char *matchmask)
20920093b4bf698f292c664676987541d5103b65b15Douglas Gregor{
210310b1c421665241d9b135c517d5031716d4a3221Fariborz Jahanian	unsigned int i;
211310b1c421665241d9b135c517d5031716d4a3221Fariborz Jahanian	unsigned char *mptr;
212310b1c421665241d9b135c517d5031716d4a3221Fariborz Jahanian
213310b1c421665241d9b135c517d5031716d4a3221Fariborz Jahanian	/* Always compare head structures: ignore mask here. */
214310b1c421665241d9b135c517d5031716d4a3221Fariborz Jahanian	if (memcmp(&a->ipv6.src, &b->ipv6.src, sizeof(struct in6_addr))
21520093b4bf698f292c664676987541d5103b65b15Douglas Gregor	    || memcmp(&a->ipv6.dst, &b->ipv6.dst, sizeof(struct in6_addr))
21620093b4bf698f292c664676987541d5103b65b15Douglas Gregor	    || memcmp(&a->ipv6.smsk, &b->ipv6.smsk, sizeof(struct in6_addr))
2173c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor	    || memcmp(&a->ipv6.dmsk, &b->ipv6.dmsk, sizeof(struct in6_addr))
2183c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor	    || a->ipv6.proto != b->ipv6.proto
21920093b4bf698f292c664676987541d5103b65b15Douglas Gregor	    || a->ipv6.tos != b->ipv6.tos
22018ef5e28a9a2677f8b1dce1fb2638d66e0a1621fDouglas Gregor	    || a->ipv6.flags != b->ipv6.flags
22118ef5e28a9a2677f8b1dce1fb2638d66e0a1621fDouglas Gregor	    || a->ipv6.invflags != b->ipv6.invflags)
222d6542d8efcf8389c3aab764f9e29ac284e16eda6Douglas Gregor		return NULL;
223d6542d8efcf8389c3aab764f9e29ac284e16eda6Douglas Gregor
22418ef5e28a9a2677f8b1dce1fb2638d66e0a1621fDouglas Gregor	for (i = 0; i < IFNAMSIZ; i++) {
22520093b4bf698f292c664676987541d5103b65b15Douglas Gregor		if (a->ipv6.iniface_mask[i] != b->ipv6.iniface_mask[i])
22620093b4bf698f292c664676987541d5103b65b15Douglas Gregor			return NULL;
227d6542d8efcf8389c3aab764f9e29ac284e16eda6Douglas Gregor		if ((a->ipv6.iniface[i] & a->ipv6.iniface_mask[i])
2286e4a0af697eec5b0c47ccf96dff170af56df826dRichard Smith		    != (b->ipv6.iniface[i] & b->ipv6.iniface_mask[i]))
2296e4a0af697eec5b0c47ccf96dff170af56df826dRichard Smith			return NULL;
2306e4a0af697eec5b0c47ccf96dff170af56df826dRichard Smith		if (a->ipv6.outiface_mask[i] != b->ipv6.outiface_mask[i])
23120093b4bf698f292c664676987541d5103b65b15Douglas Gregor			return NULL;
232ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor		if ((a->ipv6.outiface[i] & a->ipv6.outiface_mask[i])
233ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor		    != (b->ipv6.outiface[i] & b->ipv6.outiface_mask[i]))
234ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor			return NULL;
235ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor	}
236ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor
237ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor	if (a->target_offset != b->target_offset
238ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor	    || a->next_offset != b->next_offset)
239ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor		return NULL;
240ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor
24120093b4bf698f292c664676987541d5103b65b15Douglas Gregor	mptr = matchmask + sizeof(STRUCT_ENTRY);
24220093b4bf698f292c664676987541d5103b65b15Douglas Gregor	if (IP6T_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
243711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson		return NULL;
244711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson	mptr += XT_ALIGN(sizeof(struct ip6t_entry_target));
2454171766318a2564fbc9a739be0a2851f441c0d29Sean Hunt
2464171766318a2564fbc9a739be0a2851f441c0d29Sean Hunt	return mptr;
2474171766318a2564fbc9a739be0a2851f441c0d29Sean Hunt}
248059ce0d92eb5a7da900ae735dc0a2ea3d64f4b0bSean Hunt
2494171766318a2564fbc9a739be0a2851f441c0d29Sean Hunt/* All zeroes == unconditional rule. */
25020093b4bf698f292c664676987541d5103b65b15Douglas Gregorstatic inline int
251cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregorunconditional(const struct ip6t_ip6 *ipv6)
252cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor{
253cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor	unsigned int i;
254cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor
25520093b4bf698f292c664676987541d5103b65b15Douglas Gregor	for (i = 0; i < sizeof(*ipv6); i++)
25620093b4bf698f292c664676987541d5103b65b15Douglas Gregor		if (((char *)ipv6)[i])
25700eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet			break;
25800eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet
25900eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet	return (i == sizeof(*ipv6));
26000eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet}
26100eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet
26200eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet#ifdef IPTC_DEBUG
263cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor/* Do every conceivable sanity check on the handle */
264cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregorstatic void
265cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregordo_check(struct xtc_handle *h, unsigned int line)
266cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor{
267cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor	unsigned int i, n;
268cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor	unsigned int user_offset; /* Offset of first user chain */
269cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor	int was_return;
2704773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor
2714773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor	assert(h->changed == 0 || h->changed == 1);
2724773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor	if (strcmp(h->info.name, "filter") == 0) {
2734773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		assert(h->info.valid_hooks
2744773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		       == (1 << NF_IP6_LOCAL_IN
2754773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor			   | 1 << NF_IP6_FORWARD
2764773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor			   | 1 << NF_IP6_LOCAL_OUT));
27720093b4bf698f292c664676987541d5103b65b15Douglas Gregor
27820093b4bf698f292c664676987541d5103b65b15Douglas Gregor		/* Hooks should be first three */
27920093b4bf698f292c664676987541d5103b65b15Douglas Gregor		assert(h->info.hook_entry[NF_IP6_LOCAL_IN] == 0);
280cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor
281fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner		n = get_chain_end(h, 0);
282cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor		n += get_entry(h, n)->next_offset;
283cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor		assert(h->info.hook_entry[NF_IP6_FORWARD] == n);
284cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor
28520093b4bf698f292c664676987541d5103b65b15Douglas Gregor		n = get_chain_end(h, n);
286d6542d8efcf8389c3aab764f9e29ac284e16eda6Douglas Gregor		n += get_entry(h, n)->next_offset;
28720093b4bf698f292c664676987541d5103b65b15Douglas Gregor		assert(h->info.hook_entry[NF_IP6_LOCAL_OUT] == n);
288ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor
289ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor		user_offset = h->info.hook_entry[NF_IP6_LOCAL_OUT];
290ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor	} else if (strcmp(h->info.name, "nat") == 0) {
291ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor		assert((h->info.valid_hooks
292ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor			== (1 << NF_IP6_PRE_ROUTING
293ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor			    | 1 << NF_IP6_LOCAL_OUT
294ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor			    | 1 << NF_IP6_POST_ROUTING)) ||
295ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor		       (h->info.valid_hooks
296ab6677ec401cfd2c82b34e4cdfebd55a9dc25778Douglas Gregor			== (1 << NF_IP6_PRE_ROUTING
29799a2e600f9e2e51d3ce10fb6f27191677ac65b2aDouglas Gregor			    | 1 << NF_IP6_LOCAL_IN
29899a2e600f9e2e51d3ce10fb6f27191677ac65b2aDouglas Gregor			    | 1 << NF_IP6_LOCAL_OUT
2997abfbdbc97ad8e7f340789f751df1e32b10118b4Douglas Gregor			    | 1 << NF_IP6_POST_ROUTING)));
3007abfbdbc97ad8e7f340789f751df1e32b10118b4Douglas Gregor
3017abfbdbc97ad8e7f340789f751df1e32b10118b4Douglas Gregor		assert(h->info.hook_entry[NF_IP6_PRE_ROUTING] == 0);
3027abfbdbc97ad8e7f340789f751df1e32b10118b4Douglas Gregor
3037abfbdbc97ad8e7f340789f751df1e32b10118b4Douglas Gregor		n = get_chain_end(h, 0);
3043c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor
3053c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor		n += get_entry(h, n)->next_offset;
3063c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor		assert(h->info.hook_entry[NF_IP6_POST_ROUTING] == n);
307f85e193739c953358c865005855253af4f68a497John McCall		n = get_chain_end(h, n);
308f85e193739c953358c865005855253af4f68a497John McCall
309f85e193739c953358c865005855253af4f68a497John McCall		n += get_entry(h, n)->next_offset;
310f85e193739c953358c865005855253af4f68a497John McCall		assert(h->info.hook_entry[NF_IP6_LOCAL_OUT] == n);
311f85e193739c953358c865005855253af4f68a497John McCall		user_offset = h->info.hook_entry[NF_IP6_LOCAL_OUT];
312f85e193739c953358c865005855253af4f68a497John McCall
313f85e193739c953358c865005855253af4f68a497John McCall		if (h->info.valid_hooks & (1 << NF_IP6_LOCAL_IN)) {
3143c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor			n = get_chain_end(h, n);
3159db7dbb918ca49f4ee6c181e4917e7b6ec547353Douglas Gregor			n += get_entry(h, n)->next_offset;
3169db7dbb918ca49f4ee6c181e4917e7b6ec547353Douglas Gregor			assert(h->info.hook_entry[NF_IP6_LOCAL_IN] == n);
3179db7dbb918ca49f4ee6c181e4917e7b6ec547353Douglas Gregor			user_offset = h->info.hook_entry[NF_IP6_LOCAL_IN];
318711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson		}
319711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson
320711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson	} else if (strcmp(h->info.name, "mangle") == 0) {
321711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson		/* This code is getting ugly because linux < 2.4.18-pre6 had
322711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson		 * two mangle hooks, linux >= 2.4.18-pre6 has five mangle hooks
323711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson		 * */
324711f34adb886cce8ba86c7b1b6513a1eaaf63bb5Anders Carlsson		assert((h->info.valid_hooks
3259db7dbb918ca49f4ee6c181e4917e7b6ec547353Douglas Gregor			== (1 << NF_IP6_PRE_ROUTING
3269db7dbb918ca49f4ee6c181e4917e7b6ec547353Douglas Gregor			    | 1 << NF_IP6_LOCAL_OUT)) ||
32720093b4bf698f292c664676987541d5103b65b15Douglas Gregor		       (h->info.valid_hooks
32820093b4bf698f292c664676987541d5103b65b15Douglas Gregor			== (1 << NF_IP6_PRE_ROUTING
32920093b4bf698f292c664676987541d5103b65b15Douglas Gregor			    | 1 << NF_IP6_LOCAL_IN
33020093b4bf698f292c664676987541d5103b65b15Douglas Gregor			    | 1 << NF_IP6_FORWARD
3313c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor			    | 1 << NF_IP6_LOCAL_OUT
33220093b4bf698f292c664676987541d5103b65b15Douglas Gregor			    | 1 << NF_IP6_POST_ROUTING)));
333f85e193739c953358c865005855253af4f68a497John McCall
33420093b4bf698f292c664676987541d5103b65b15Douglas Gregor		/* Hooks should be first five */
33520093b4bf698f292c664676987541d5103b65b15Douglas Gregor		assert(h->info.hook_entry[NF_IP6_PRE_ROUTING] == 0);
33620093b4bf698f292c664676987541d5103b65b15Douglas Gregor
33720093b4bf698f292c664676987541d5103b65b15Douglas Gregor		n = get_chain_end(h, 0);
3383c9034cb7ff1d6c1e4ecd1b44c98f553df013c7cDouglas Gregor
33920093b4bf698f292c664676987541d5103b65b15Douglas Gregor		if (h->info.valid_hooks & (1 << NF_IP6_LOCAL_IN)) {
340cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor			n += get_entry(h, n)->next_offset;
341cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor			assert(h->info.hook_entry[NF_IP6_LOCAL_IN] == n);
342cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor			n = get_chain_end(h, n);
343cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor		}
3440c706c29f20b6fa36759fa41333b9c3ec0bd2969Eli Friedman
345eb52f86a62db523e3c993686b3ed92c55d59d53cDavid Blaikie		if (h->info.valid_hooks & (1 << NF_IP6_FORWARD)) {
346cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor			n += get_entry(h, n)->next_offset;
347cb57fb9f91e0976f4a3382b89a2734ffa50eb6fbDouglas Gregor			assert(h->info.hook_entry[NF_IP6_FORWARD] == n);
3484773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor			n = get_chain_end(h, n);
3494773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		}
3504773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor
3514773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		n += get_entry(h, n)->next_offset;
3524773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		assert(h->info.hook_entry[NF_IP6_LOCAL_OUT] == n);
3534773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		user_offset = h->info.hook_entry[NF_IP6_LOCAL_OUT];
3544773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor
3554773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		if (h->info.valid_hooks & (1 << NF_IP6_POST_ROUTING)) {
3564773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor			n = get_chain_end(h, n);
3574773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor			n += get_entry(h, n)->next_offset;
3584773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor			assert(h->info.hook_entry[NF_IP6_POST_ROUTING] == n);
3594773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor			user_offset = h->info.hook_entry[NF_IP6_POST_ROUTING];
3604773654f2700d6fbb20612fbb6763b35860fa74dDouglas Gregor		}
36120093b4bf698f292c664676987541d5103b65b15Douglas Gregor	} else if (strcmp(h->info.name, "raw") == 0) {
36220093b4bf698f292c664676987541d5103b65b15Douglas Gregor		assert(h->info.valid_hooks
36320093b4bf698f292c664676987541d5103b65b15Douglas Gregor		       == (1 << NF_IP6_PRE_ROUTING
36420093b4bf698f292c664676987541d5103b65b15Douglas Gregor			   | 1 << NF_IP6_LOCAL_OUT));
36520093b4bf698f292c664676987541d5103b65b15Douglas Gregor
36620093b4bf698f292c664676987541d5103b65b15Douglas Gregor		/* Hooks should be first three */
36720093b4bf698f292c664676987541d5103b65b15Douglas Gregor		assert(h->info.hook_entry[NF_IP6_PRE_ROUTING] == 0);
36820093b4bf698f292c664676987541d5103b65b15Douglas Gregor
36920093b4bf698f292c664676987541d5103b65b15Douglas Gregor		n = get_chain_end(h, n);
370ed878af7914df535b32d64f555fa118413186672Douglas Gregor		n += get_entry(h, n)->next_offset;
371ed878af7914df535b32d64f555fa118413186672Douglas Gregor		assert(h->info.hook_entry[NF_IP6_LOCAL_OUT] == n);
372ed878af7914df535b32d64f555fa118413186672Douglas Gregor
373ed878af7914df535b32d64f555fa118413186672Douglas Gregor		user_offset = h->info.hook_entry[NF_IP6_LOCAL_OUT];
374ed878af7914df535b32d64f555fa118413186672Douglas Gregor	} else {
37520093b4bf698f292c664676987541d5103b65b15Douglas Gregor                fprintf(stderr, "Unknown table `%s'\n", h->info.name);
37620093b4bf698f292c664676987541d5103b65b15Douglas Gregor		abort();
37720093b4bf698f292c664676987541d5103b65b15Douglas Gregor	}
3783a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl
3793a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl	/* User chain == end of last builtin + policy entry */
3803a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl	user_offset = get_chain_end(h, user_offset);
381ed878af7914df535b32d64f555fa118413186672Douglas Gregor	user_offset += get_entry(h, user_offset)->next_offset;
3823a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl
3833a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl	/* Overflows should be end of entry chains, and unconditional
3843a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl           policy nodes. */
3853a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl	for (i = 0; i < NUMHOOKS; i++) {
38620093b4bf698f292c664676987541d5103b65b15Douglas Gregor		STRUCT_ENTRY *e;
38720093b4bf698f292c664676987541d5103b65b15Douglas Gregor		STRUCT_STANDARD_TARGET *t;
38820093b4bf698f292c664676987541d5103b65b15Douglas Gregor
3893a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl		if (!(h->info.valid_hooks & (1 << i)))
3903a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl			continue;
3913a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl		assert(h->info.underflow[i]
3923a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl		       == get_chain_end(h, h->info.hook_entry[i]));
39320093b4bf698f292c664676987541d5103b65b15Douglas Gregor
39420093b4bf698f292c664676987541d5103b65b15Douglas Gregor		e = get_entry(h, get_chain_end(h, h->info.hook_entry[i]));
39520093b4bf698f292c664676987541d5103b65b15Douglas Gregor		assert(unconditional(&e->ipv6));
39620093b4bf698f292c664676987541d5103b65b15Douglas Gregor		assert(e->target_offset == sizeof(*e));
3973a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl		t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
39820093b4bf698f292c664676987541d5103b65b15Douglas Gregor		printf("target_size=%u, align=%u\n",
3993a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl			t->target.u.target_size, ALIGN(sizeof(*t)));
40020093b4bf698f292c664676987541d5103b65b15Douglas Gregor		assert(t->target.u.target_size == ALIGN(sizeof(*t)));
40120093b4bf698f292c664676987541d5103b65b15Douglas Gregor		assert(e->next_offset == sizeof(*e) + ALIGN(sizeof(*t)));
40220093b4bf698f292c664676987541d5103b65b15Douglas Gregor
40320093b4bf698f292c664676987541d5103b65b15Douglas Gregor		assert(strcmp(t->target.u.user.name, STANDARD_TARGET)==0);
40420093b4bf698f292c664676987541d5103b65b15Douglas Gregor		assert(t->verdict == -NF_DROP-1 || t->verdict == -NF_ACCEPT-1);
40520093b4bf698f292c664676987541d5103b65b15Douglas Gregor
40620093b4bf698f292c664676987541d5103b65b15Douglas Gregor		/* Hooks and underflows must be valid entries */
40720093b4bf698f292c664676987541d5103b65b15Douglas Gregor		iptcb_entry2index(h, get_entry(h, h->info.hook_entry[i]));
40820093b4bf698f292c664676987541d5103b65b15Douglas Gregor		iptcb_entry2index(h, get_entry(h, h->info.underflow[i]));
40920093b4bf698f292c664676987541d5103b65b15Douglas Gregor	}
41020093b4bf698f292c664676987541d5103b65b15Douglas Gregor
4113a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl	assert(h->info.size
4123a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl	       >= h->info.num_entries * (sizeof(STRUCT_ENTRY)
41320093b4bf698f292c664676987541d5103b65b15Douglas Gregor					 +sizeof(STRUCT_STANDARD_TARGET)));
41420093b4bf698f292c664676987541d5103b65b15Douglas Gregor
4155b9cc5df25c2198f270dd1d5c438fdce70d4051dSebastian Redl	assert(h->entries.size
4163a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl	       >= (h->new_number
4173a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl		   * (sizeof(STRUCT_ENTRY)
4185b9cc5df25c2198f270dd1d5c438fdce70d4051dSebastian Redl		      + sizeof(STRUCT_STANDARD_TARGET))));
4195b9cc5df25c2198f270dd1d5c438fdce70d4051dSebastian Redl	assert(strcmp(h->info.name, h->entries.name) == 0);
420f85e193739c953358c865005855253af4f68a497John McCall
421f85e193739c953358c865005855253af4f68a497John McCall	i = 0; n = 0;
422c8d7f586180995ba33d03c0f6115b6a7bdefe326Richard Smith	was_return = 0;
4233a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl
4243a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl#if 0
42520093b4bf698f292c664676987541d5103b65b15Douglas Gregor	/* Check all the entries. */
42620093b4bf698f292c664676987541d5103b65b15Douglas Gregor	ENTRY_ITERATE(h->entries.entrytable, h->entries.size,
427f85e193739c953358c865005855253af4f68a497John McCall		      check_entry, &i, &n, user_offset, &was_return, h);
428f85e193739c953358c865005855253af4f68a497John McCall
4293a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl	assert(i == h->new_number);
4303a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl	assert(n == h->entries.size);
4313a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl
4323a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl	/* Final entry must be error node */
4333a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl	assert(strcmp(GET_TARGET(index2entry(h, h->new_number-1))
4343a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl		      ->u.user.name,
435f85e193739c953358c865005855253af4f68a497John McCall		      ERROR_TARGET) == 0);
436f85e193739c953358c865005855253af4f68a497John McCall#endif
437f85e193739c953358c865005855253af4f68a497John McCall}
438f85e193739c953358c865005855253af4f68a497John McCall#endif /*IPTC_DEBUG*/
4393a45c0e61dfc19f27b8ebcb15dd70159a36f1f9aSebastian Redl