11b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt#include <stdint.h>
2b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell#include <stdio.h>
3b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell#include <string.h>
45d9678ad3eabc34ac40dfe055d7f6a8e44445a5aJan Engelhardt#include <xtables.h>
54e41854423b529d3107c23b85434d50a75d08057Jan Engelhardt#include <limits.h> /* INT_MAX in ip6_tables.h */
6b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell#include <linux/netfilter_ipv6/ip6_tables.h>
7b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
81b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardtenum {
91b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt	O_ICMPV6_TYPE = 0,
101b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt};
111b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt
12e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabóstruct icmpv6_names {
13b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	const char *name;
147ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardt	uint8_t type;
157ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardt	uint8_t code_min, code_max;
16b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell};
17b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
18e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabóstatic const struct icmpv6_names icmpv6_codes[] = {
19b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{ "destination-unreachable", 1, 0, 0xFF },
20b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{   "no-route", 1, 0, 0 },
21b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{   "communication-prohibited", 1, 1, 1 },
22b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{   "address-unreachable", 1, 3, 3 },
23b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{   "port-unreachable", 1, 4, 4 },
24b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
25b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{ "packet-too-big", 2, 0, 0xFF },
26b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
27b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{ "time-exceeded", 3, 0, 0xFF },
28b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	/* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
29b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{   "ttl-zero-during-transit", 3, 0, 0 },
30b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{   "ttl-zero-during-reassembly", 3, 1, 1 },
31b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
32b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{ "parameter-problem", 4, 0, 0xFF },
33b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{   "bad-header", 4, 0, 0 },
34b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{   "unknown-header-type", 4, 1, 1 },
35b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{   "unknown-option", 4, 2, 2 },
36b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
37b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{ "echo-request", 128, 0, 0xFF },
38b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	/* Alias */ { "ping", 128, 0, 0xFF },
39b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
40b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{ "echo-reply", 129, 0, 0xFF },
41b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	/* Alias */ { "pong", 129, 0, 0xFF },
42b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
43b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{ "router-solicitation", 133, 0, 0xFF },
44b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
45b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{ "router-advertisement", 134, 0, 0xFF },
46b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
47b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{ "neighbour-solicitation", 135, 0, 0xFF },
48b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	/* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
49b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
50b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{ "neighbour-advertisement", 136, 0, 0xFF },
51b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	/* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
52b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
53b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	{ "redirect", 137, 0, 0xFF },
54b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
55b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell};
56b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
57b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundellstatic void
58500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardyprint_icmpv6types(void)
59b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell{
60b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	unsigned int i;
61b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	printf("Valid ICMPv6 Types:");
62b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
632c69b55e55f2efc5a334b87ccdceaa9de0ecb658Jan Engelhardt	for (i = 0; i < ARRAY_SIZE(icmpv6_codes); ++i) {
64e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó		if (i && icmpv6_codes[i].type == icmpv6_codes[i-1].type) {
65e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó			if (icmpv6_codes[i].code_min == icmpv6_codes[i-1].code_min
66e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó			    && (icmpv6_codes[i].code_max
67e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó				== icmpv6_codes[i-1].code_max))
68e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó				printf(" (%s)", icmpv6_codes[i].name);
69b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell			else
70e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó				printf("\n   %s", icmpv6_codes[i].name);
71b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		}
72b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		else
73e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó			printf("\n%s", icmpv6_codes[i].name);
74b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	}
75b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	printf("\n");
76b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell}
77b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
78997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void icmp6_help(void)
79b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell{
80b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	printf(
818b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"icmpv6 match options:\n"
82967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt"[!] --icmpv6-type typename	match icmpv6 type\n"
838b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"				(or numeric type or type/code)\n");
84e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó	print_icmpv6types();
85b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell}
86b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
871b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardtstatic const struct xt_option_entry icmp6_opts[] = {
881b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt	{.name = "icmpv6-type", .id = O_ICMPV6_TYPE, .type = XTTYPE_STRING,
891b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt	 .flags = XTOPT_MAND | XTOPT_INVERT},
901b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt	XTOPT_TABLEEND,
91b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell};
92b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
938115e5425721cd610b6390c3d4c24540773b0520Pablo Neirastatic void
947ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtparse_icmpv6(const char *icmpv6type, uint8_t *type, uint8_t code[])
95b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell{
962c69b55e55f2efc5a334b87ccdceaa9de0ecb658Jan Engelhardt	static const unsigned int limit = ARRAY_SIZE(icmpv6_codes);
97b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	unsigned int match = limit;
98b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	unsigned int i;
99b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
100b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	for (i = 0; i < limit; i++) {
101e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó		if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type))
102b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		    == 0) {
103b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell			if (match != limit)
1041829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt				xtables_error(PARAMETER_PROBLEM,
105b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell					   "Ambiguous ICMPv6 type `%s':"
106b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell					   " `%s' or `%s'?",
107e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó					   icmpv6type,
108e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó					   icmpv6_codes[match].name,
109e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó					   icmpv6_codes[i].name);
110b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell			match = i;
111b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		}
112b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	}
113b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
114b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	if (match != limit) {
115e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó		*type = icmpv6_codes[match].type;
116e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó		code[0] = icmpv6_codes[match].code_min;
117e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó		code[1] = icmpv6_codes[match].code_max;
118b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	} else {
119b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		char *slash;
120e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó		char buffer[strlen(icmpv6type) + 1];
121b47197629735fa1cb93112dfd7d1c4fbcdb24a95Harald Welte		unsigned int number;
122b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
123e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó		strcpy(buffer, icmpv6type);
124b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		slash = strchr(buffer, '/');
125b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
126b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		if (slash)
127b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell			*slash = '\0';
128b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
1295f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt		if (!xtables_strtoui(buffer, NULL, &number, 0, UINT8_MAX))
1301829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt			xtables_error(PARAMETER_PROBLEM,
131b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell				   "Invalid ICMPv6 type `%s'\n", buffer);
132b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		*type = number;
133b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		if (slash) {
1345f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt			if (!xtables_strtoui(slash+1, NULL, &number, 0, UINT8_MAX))
1351829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt				xtables_error(PARAMETER_PROBLEM,
136b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell					   "Invalid ICMPv6 code `%s'\n",
137b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell					   slash+1);
138b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell			code[0] = code[1] = number;
139b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		} else {
140b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell			code[0] = 0;
141b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell			code[1] = 0xFF;
142b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		}
143b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	}
144b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell}
145b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
146997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void icmp6_init(struct xt_entry_match *m)
147b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell{
148e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó	struct ip6t_icmp *icmpv6info = (struct ip6t_icmp *)m->data;
149b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
150e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó	icmpv6info->code[1] = 0xFF;
151b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell}
152b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
1531b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardtstatic void icmp6_parse(struct xt_option_call *cb)
154b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell{
1551b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt	struct ip6t_icmp *icmpv6info = cb->data;
156b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
1571b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt	xtables_option_parse(cb);
1581b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt	parse_icmpv6(cb->arg, &icmpv6info->type, icmpv6info->code);
1591b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt	if (cb->invert)
1601b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt		icmpv6info->invflags |= IP6T_ICMP_INV;
161b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell}
162b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
1637ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic void print_icmpv6type(uint8_t type,
1647ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardt			   uint8_t code_min, uint8_t code_max,
165b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell			   int invert,
166b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell			   int numeric)
167b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell{
168b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	if (!numeric) {
169b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		unsigned int i;
170b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
1712c69b55e55f2efc5a334b87ccdceaa9de0ecb658Jan Engelhardt		for (i = 0; i < ARRAY_SIZE(icmpv6_codes); ++i)
172e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó			if (icmpv6_codes[i].type == type
173e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó			    && icmpv6_codes[i].code_min == code_min
174e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó			    && icmpv6_codes[i].code_max == code_max)
175b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell				break;
176b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
1772c69b55e55f2efc5a334b87ccdceaa9de0ecb658Jan Engelhardt		if (i != ARRAY_SIZE(icmpv6_codes)) {
17873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt			printf(" %s%s",
179b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell			       invert ? "!" : "",
180e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó			       icmpv6_codes[i].name);
181b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell			return;
182b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		}
183b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	}
184b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
185b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	if (invert)
18673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" !");
187b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
188b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell	printf("type %u", type);
18973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	if (code_min == code_max)
19073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" code %u", code_min);
19173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	else if (code_min != 0 || code_max != 0xFF)
19273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" codes %u-%u", code_min, code_max);
193b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell}
194b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
195997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void icmp6_print(const void *ip, const struct xt_entry_match *match,
196997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt                        int numeric)
197b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell{
198e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó	const struct ip6t_icmp *icmpv6 = (struct ip6t_icmp *)match->data;
199b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
20073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" ipv6-icmp");
201e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó	print_icmpv6type(icmpv6->type, icmpv6->code[0], icmpv6->code[1],
202e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó		       icmpv6->invflags & IP6T_ICMP_INV,
203b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell		       numeric);
204b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
205e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó	if (icmpv6->invflags & ~IP6T_ICMP_INV)
20673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" Unknown invflags: 0x%X",
207e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó		       icmpv6->invflags & ~IP6T_ICMP_INV);
208b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell}
209b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
210997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void icmp6_save(const void *ip, const struct xt_entry_match *match)
211b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell{
212e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó	const struct ip6t_icmp *icmpv6 = (struct ip6t_icmp *)match->data;
213b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
214e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó	if (icmpv6->invflags & IP6T_ICMP_INV)
21573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" !");
216b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
21773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" --icmpv6-type %u", icmpv6->type);
218e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó	if (icmpv6->code[0] != 0 || icmpv6->code[1] != 0xFF)
219e0bc7a4eabc45621a7a8cc2a32f178dae51f43e0András Kis-Szabó		printf("/%u", icmpv6->code[0]);
220b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell}
221b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
2228b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardtstatic struct xtables_match icmp6_mt6_reg = {
22302aa73312d6078b6de26757d5a558e0085ec20b5Harald Welte	.name 		= "icmp6",
2248b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.version 	= XTABLES_VERSION,
22503d99486d8283552705b58dc55b6085dffc38792Jan Engelhardt	.family		= NFPROTO_IPV6,
2268b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.size		= XT_ALIGN(sizeof(struct ip6t_icmp)),
2278b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.userspacesize	= XT_ALIGN(sizeof(struct ip6t_icmp)),
228997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.help		= icmp6_help,
229997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.init		= icmp6_init,
230997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.print		= icmp6_print,
231997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt	.save		= icmp6_save,
2321b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt	.x6_parse	= icmp6_parse,
2331b8db4f4ca250f13a0e7edddb31cfc1f82d42806Jan Engelhardt	.x6_options	= icmp6_opts,
234b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell};
235b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell
236b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundellvoid _init(void)
237b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell{
2388b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	xtables_register_match(&icmp6_mt6_reg);
239b47050c8c1ffb47ef63be37526e0afd15193c5a8Philip Blundell}
240