* [PATCH] ebtables: extend ebt_ip6 to allow matching on ipv6-icmp types/codes
@ 2010-12-17 16:24 Florian Westphal
2010-12-18 16:35 ` Bart De Schuymer
0 siblings, 1 reply; 2+ messages in thread
From: Florian Westphal @ 2010-12-17 16:24 UTC (permalink / raw)
To: netfilter-devel
adds a --ip6-icmp-type option to match on ipv6-icmp types/codes.
The ipv6-icmp name list was taken from iptables 1.4.9.
Signed-off-by: Florian Westphal <fwestphal@astaro.com>
---
ebtables.8 | 11 +++
extensions/ebt_ip6.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++-
include/ebtables_u.h | 4 +
3 files changed, 240 insertions(+), 2 deletions(-)
diff --git a/ebtables.8 b/ebtables.8
index 957c445..6c7acf7 100644
--- a/ebtables.8
+++ b/ebtables.8
@@ -700,6 +700,17 @@ If
The flag
.B --ip6-dport
is an alias for this option.
+.TP
+.BR "--ip6-icmp-type " "[!] {\fItype\fP[:\fItype\fP]/\fIcode\fP[:\fIcode\fP]|\fItypename\fP}"
+Specify ipv6\-icmp type and code to match.
+Ranges for both type and code are supported. Type and code are
+separated by a slash. Valid numbers for type and range are 0 to 255.
+To match a single type including all valid codes, symbolic names can
+be used instead of numbers. The list of known type names is shown by the command
+.nf
+ ebtables \-\-help ip6
+.fi
+This option is only valid for \-\-ip6-prococol ipv6-icmp.
.SS limit
This module matches at a limited rate using a token bucket filter.
A rule using this extension will match until this limit is reached.
diff --git a/extensions/ebt_ip6.c b/extensions/ebt_ip6.c
index 5850523..9ab177d 100644
--- a/extensions/ebt_ip6.c
+++ b/extensions/ebt_ip6.c
@@ -11,6 +11,9 @@
*
*/
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -27,8 +30,9 @@
#define IP_PROTO '4'
#define IP_SPORT '5'
#define IP_DPORT '6'
+#define IP_ICMP6 '7'
-static struct option opts[] =
+static const struct option opts[] =
{
{ "ip6-source" , required_argument, 0, IP_SOURCE },
{ "ip6-src" , required_argument, 0, IP_SOURCE },
@@ -42,9 +46,55 @@ static struct option opts[] =
{ "ip6-sport" , required_argument, 0, IP_SPORT },
{ "ip6-destination-port" , required_argument, 0, IP_DPORT },
{ "ip6-dport" , required_argument, 0, IP_DPORT },
+ { "ip6-icmp-type" , required_argument, 0, IP_ICMP6 },
{ 0 }
};
+
+struct icmpv6_names {
+ const char *name;
+ u_int8_t type;
+ u_int8_t code_min, code_max;
+};
+
+static const struct icmpv6_names icmpv6_codes[] = {
+ { "destination-unreachable", 1, 0, 0xFF },
+ { "no-route", 1, 0, 0 },
+ { "communication-prohibited", 1, 1, 1 },
+ { "address-unreachable", 1, 3, 3 },
+ { "port-unreachable", 1, 4, 4 },
+
+ { "packet-too-big", 2, 0, 0xFF },
+
+ { "time-exceeded", 3, 0, 0xFF },
+ /* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
+ { "ttl-zero-during-transit", 3, 0, 0 },
+ { "ttl-zero-during-reassembly", 3, 1, 1 },
+
+ { "parameter-problem", 4, 0, 0xFF },
+ { "bad-header", 4, 0, 0 },
+ { "unknown-header-type", 4, 1, 1 },
+ { "unknown-option", 4, 2, 2 },
+
+ { "echo-request", 128, 0, 0xFF },
+ /* Alias */ { "ping", 128, 0, 0xFF },
+
+ { "echo-reply", 129, 0, 0xFF },
+ /* Alias */ { "pong", 129, 0, 0xFF },
+
+ { "router-solicitation", 133, 0, 0xFF },
+
+ { "router-advertisement", 134, 0, 0xFF },
+
+ { "neighbour-solicitation", 135, 0, 0xFF },
+ /* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
+
+ { "neighbour-advertisement", 136, 0, 0xFF },
+ /* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
+
+ { "redirect", 137, 0, 0xFF },
+};
+
/* transform a protocol and service name into a port number */
static uint16_t parse_port(const char *protocol, const char *name)
{
@@ -91,6 +141,97 @@ parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
free(buffer);
}
+static char*
+parse_num(const char *str, long min, long max, long *num)
+{
+ char *end;
+
+ errno = 0;
+ *num = strtol(str, &end, 10);
+ if (errno && (*num == LONG_MIN || *num == LONG_MAX)) {
+ ebt_print_error("Invalid number %s: %s", str, strerror(errno));
+ return NULL;
+ }
+ if (min <= max) {
+ if (*num > max || *num < min) {
+ ebt_print_error("Value %ld out of range (%ld, %ld)", *num, min, max);
+ return NULL;
+ }
+ }
+ if (*num == 0 && str == end)
+ return NULL;
+ return end;
+}
+
+static char *
+parse_range(const char *str, long min, long max, long num[])
+{
+ char *next;
+
+ next = parse_num(str, min, max, num);
+ if (next == NULL)
+ return NULL;
+ if (next && *next == ':')
+ next = parse_num(next+1, min, max, &num[1]);
+ else
+ num[1] = num[0];
+ return next;
+}
+
+static int
+parse_icmpv6(const char *icmpv6type, uint8_t type[], uint8_t code[])
+{
+ static const unsigned int limit = ARRAY_SIZE(icmpv6_codes);
+ unsigned int match = limit;
+ unsigned int i;
+ long number[2];
+
+ for (i = 0; i < limit; i++) {
+ if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type)))
+ continue;
+ if (match != limit)
+ ebt_print_error("Ambiguous ICMPv6 type `%s':"
+ " `%s' or `%s'?",
+ icmpv6type, icmpv6_codes[match].name,
+ icmpv6_codes[i].name);
+ match = i;
+ }
+
+ if (match < limit) {
+ type[0] = type[1] = icmpv6_codes[match].type;
+ code[0] = icmpv6_codes[match].code_min;
+ code[1] = icmpv6_codes[match].code_max;
+ } else {
+ char *next = parse_range(icmpv6type, 0, 255, number);
+ if (!next) {
+ ebt_print_error("Unknown ICMPv6 type `%s'",
+ icmpv6type);
+ return -1;
+ }
+ type[0] = (uint8_t) number[0];
+ type[1] = (uint8_t) number[1];
+ switch (*next) {
+ case 0:
+ code[0] = 0;
+ code[1] = 255;
+ return 0;
+ case '/':
+ next = parse_range(next+1, 0, 255, number);
+ code[0] = (uint8_t) number[0];
+ code[1] = (uint8_t) number[1];
+ if (next == NULL)
+ return -1;
+ if (next && *next == 0)
+ return 0;
+ /* fallthrough */
+ default:
+ ebt_print_error("unknown character %c", *next);
+ return -1;
+ }
+ }
+ return 0;
+}
+
static void print_port_range(uint16_t *ports)
{
if (ports[0] == ports[1])
@@ -99,6 +240,58 @@ static void print_port_range(uint16_t *ports)
printf("%d:%d ", ports[0], ports[1]);
}
+static void print_icmp_code(uint8_t *code)
+{
+ if (code[0] == code[1])
+ printf("/%"PRIu8 " ", code[0]);
+ else
+ printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]);
+}
+
+static void print_icmp_type(uint8_t *type, uint8_t *code)
+{
+ unsigned int i;
+
+ if (type[0] != type[1]) {
+ printf("%"PRIu8 ":%" PRIu8, type[0], type[1]);
+ print_icmp_code(code);
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(icmpv6_codes); i++) {
+ if (icmpv6_codes[i].type != type[0])
+ continue;
+
+ if (icmpv6_codes[i].code_min == code[0] &&
+ icmpv6_codes[i].code_max == code[1]) {
+ printf("%s ", icmpv6_codes[i].name);
+ return;
+ }
+ }
+ printf("%"PRIu8, type[0]);
+ print_icmp_code(code);
+}
+
+static void print_icmpv6types(void)
+{
+ unsigned int i;
+ printf("Valid ICMPv6 Types:");
+
+ for (i=0; i < ARRAY_SIZE(icmpv6_codes); i++) {
+ if (i && icmpv6_codes[i].type == icmpv6_codes[i-1].type) {
+ if (icmpv6_codes[i].code_min == icmpv6_codes[i-1].code_min
+ && (icmpv6_codes[i].code_max
+ == icmpv6_codes[i-1].code_max))
+ printf(" (%s)", icmpv6_codes[i].name);
+ else
+ printf("\n %s", icmpv6_codes[i].name);
+ }
+ else
+ printf("\n%s", icmpv6_codes[i].name);
+ }
+ printf("\n");
+}
+
static void print_help()
{
printf(
@@ -108,7 +301,9 @@ static void print_help()
"--ip6-tclass [!] tclass : ipv6 traffic class specification\n"
"--ip6-proto [!] protocol : ipv6 protocol specification\n"
"--ip6-sport [!] port[:port] : tcp/udp source port or port range\n"
-"--ip6-dport [!] port[:port] : tcp/udp destination port or port range\n");
+"--ip6-dport [!] port[:port] : tcp/udp destination port or port range\n"
+"--ip6-icmp-type [!] type[[:type]/code[:code]] : ipv6-icmp type/code or type/code range\n");
+print_icmpv6types();
}
static void init(struct ebt_entry_match *match)
@@ -170,6 +365,15 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
parse_port_range(NULL, optarg, ipinfo->dport);
break;
+ case IP_ICMP6:
+ ebt_check_option2(flags, EBT_IP6_ICMP6);
+ ipinfo->bitmask |= EBT_IP6_ICMP6;
+ if (ebt_check_inverse2(optarg))
+ ipinfo->invflags |= EBT_IP6_ICMP6;
+ if (parse_icmpv6(optarg, ipinfo->icmpv6_type, ipinfo->icmpv6_code))
+ return 0;
+ break;
+
case IP_TCLASS:
ebt_check_option2(flags, OPT_TCLASS);
if (ebt_check_inverse2(optarg))
@@ -223,6 +427,12 @@ static void final_check(const struct ebt_u_entry *entry,
ebt_print_error("For port filtering the IP protocol must be "
"either 6 (tcp), 17 (udp), 33 (dccp) or "
"132 (sctp)");
+ if ((ipinfo->bitmask & EBT_IP6_ICMP6) &&
+ (!(ipinfo->bitmask & EBT_IP6_PROTO) ||
+ ipinfo->invflags & EBT_IP6_PROTO ||
+ ipinfo->protocol != IPPROTO_ICMPV6))
+ ebt_print_error("For ipv6-icmp filtering the IP protocol must be "
+ "58 (ipv6-icmp)");
}
static void print(const struct ebt_u_entry *entry,
@@ -275,6 +485,12 @@ static void print(const struct ebt_u_entry *entry,
printf("! ");
print_port_range(ipinfo->dport);
}
+ if (ipinfo->bitmask & EBT_IP6_ICMP6) {
+ printf("--ip6-icmp-type ");
+ if (ipinfo->invflags & EBT_IP6_ICMP6)
+ printf("! ");
+ print_icmp_type(ipinfo->icmpv6_type, ipinfo->icmpv6_code);
+ }
}
static int compare(const struct ebt_entry_match *m1,
@@ -317,6 +533,13 @@ static int compare(const struct ebt_entry_match *m1,
ipinfo1->dport[1] != ipinfo2->dport[1])
return 0;
}
+ if (ipinfo1->bitmask & EBT_IP6_ICMP6) {
+ if (ipinfo1->icmpv6_type[0] != ipinfo2->icmpv6_type[0] ||
+ ipinfo1->icmpv6_type[1] != ipinfo2->icmpv6_type[1] ||
+ ipinfo1->icmpv6_code[0] != ipinfo2->icmpv6_code[0] ||
+ ipinfo1->icmpv6_code[1] != ipinfo2->icmpv6_code[1])
+ return 0;
+ }
return 1;
}
diff --git a/include/ebtables_u.h b/include/ebtables_u.h
index 910c213..c29476d 100644
--- a/include/ebtables_u.h
+++ b/include/ebtables_u.h
@@ -376,4 +376,8 @@ extern int ebt_printstyle_mac;
#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
#endif
#define ATOMIC_ENV_VARIABLE "EBTABLES_ATOMIC_FILE"
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
#endif /* EBTABLES_U_H */
--
1.7.2.2
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] ebtables: extend ebt_ip6 to allow matching on ipv6-icmp types/codes
2010-12-17 16:24 [PATCH] ebtables: extend ebt_ip6 to allow matching on ipv6-icmp types/codes Florian Westphal
@ 2010-12-18 16:35 ` Bart De Schuymer
0 siblings, 0 replies; 2+ messages in thread
From: Bart De Schuymer @ 2010-12-18 16:35 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel
Hi Florian,
This patch looks good. I'll apply it once the kernel patch is applied.
cheers,
Bart
On 17-12-10 17:24, Florian Westphal wrote:
> adds a --ip6-icmp-type option to match on ipv6-icmp types/codes.
> The ipv6-icmp name list was taken from iptables 1.4.9.
>
> Signed-off-by: Florian Westphal<fwestphal@astaro.com>
> ---
> ebtables.8 | 11 +++
> extensions/ebt_ip6.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++-
> include/ebtables_u.h | 4 +
> 3 files changed, 240 insertions(+), 2 deletions(-)
>
> diff --git a/ebtables.8 b/ebtables.8
> index 957c445..6c7acf7 100644
> --- a/ebtables.8
> +++ b/ebtables.8
> @@ -700,6 +700,17 @@ If
> The flag
> .B --ip6-dport
> is an alias for this option.
> +.TP
> +.BR "--ip6-icmp-type " "[!] {\fItype\fP[:\fItype\fP]/\fIcode\fP[:\fIcode\fP]|\fItypename\fP}"
> +Specify ipv6\-icmp type and code to match.
> +Ranges for both type and code are supported. Type and code are
> +separated by a slash. Valid numbers for type and range are 0 to 255.
> +To match a single type including all valid codes, symbolic names can
> +be used instead of numbers. The list of known type names is shown by the command
> +.nf
> + ebtables \-\-help ip6
> +.fi
> +This option is only valid for \-\-ip6-prococol ipv6-icmp.
> .SS limit
> This module matches at a limited rate using a token bucket filter.
> A rule using this extension will match until this limit is reached.
> diff --git a/extensions/ebt_ip6.c b/extensions/ebt_ip6.c
> index 5850523..9ab177d 100644
> --- a/extensions/ebt_ip6.c
> +++ b/extensions/ebt_ip6.c
> @@ -11,6 +11,9 @@
> *
> */
>
> +#include<errno.h>
> +#include<inttypes.h>
> +#include<limits.h>
> #include<stdio.h>
> #include<stdlib.h>
> #include<string.h>
> @@ -27,8 +30,9 @@
> #define IP_PROTO '4'
> #define IP_SPORT '5'
> #define IP_DPORT '6'
> +#define IP_ICMP6 '7'
>
> -static struct option opts[] =
> +static const struct option opts[] =
> {
> { "ip6-source" , required_argument, 0, IP_SOURCE },
> { "ip6-src" , required_argument, 0, IP_SOURCE },
> @@ -42,9 +46,55 @@ static struct option opts[] =
> { "ip6-sport" , required_argument, 0, IP_SPORT },
> { "ip6-destination-port" , required_argument, 0, IP_DPORT },
> { "ip6-dport" , required_argument, 0, IP_DPORT },
> + { "ip6-icmp-type" , required_argument, 0, IP_ICMP6 },
> { 0 }
> };
>
> +
> +struct icmpv6_names {
> + const char *name;
> + u_int8_t type;
> + u_int8_t code_min, code_max;
> +};
> +
> +static const struct icmpv6_names icmpv6_codes[] = {
> + { "destination-unreachable", 1, 0, 0xFF },
> + { "no-route", 1, 0, 0 },
> + { "communication-prohibited", 1, 1, 1 },
> + { "address-unreachable", 1, 3, 3 },
> + { "port-unreachable", 1, 4, 4 },
> +
> + { "packet-too-big", 2, 0, 0xFF },
> +
> + { "time-exceeded", 3, 0, 0xFF },
> + /* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
> + { "ttl-zero-during-transit", 3, 0, 0 },
> + { "ttl-zero-during-reassembly", 3, 1, 1 },
> +
> + { "parameter-problem", 4, 0, 0xFF },
> + { "bad-header", 4, 0, 0 },
> + { "unknown-header-type", 4, 1, 1 },
> + { "unknown-option", 4, 2, 2 },
> +
> + { "echo-request", 128, 0, 0xFF },
> + /* Alias */ { "ping", 128, 0, 0xFF },
> +
> + { "echo-reply", 129, 0, 0xFF },
> + /* Alias */ { "pong", 129, 0, 0xFF },
> +
> + { "router-solicitation", 133, 0, 0xFF },
> +
> + { "router-advertisement", 134, 0, 0xFF },
> +
> + { "neighbour-solicitation", 135, 0, 0xFF },
> + /* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
> +
> + { "neighbour-advertisement", 136, 0, 0xFF },
> + /* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
> +
> + { "redirect", 137, 0, 0xFF },
> +};
> +
> /* transform a protocol and service name into a port number */
> static uint16_t parse_port(const char *protocol, const char *name)
> {
> @@ -91,6 +141,97 @@ parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
> free(buffer);
> }
>
> +static char*
> +parse_num(const char *str, long min, long max, long *num)
> +{
> + char *end;
> +
> + errno = 0;
> + *num = strtol(str,&end, 10);
> + if (errno&& (*num == LONG_MIN || *num == LONG_MAX)) {
> + ebt_print_error("Invalid number %s: %s", str, strerror(errno));
> + return NULL;
> + }
> + if (min<= max) {
> + if (*num> max || *num< min) {
> + ebt_print_error("Value %ld out of range (%ld, %ld)", *num, min, max);
> + return NULL;
> + }
> + }
> + if (*num == 0&& str == end)
> + return NULL;
> + return end;
> +}
> +
> +static char *
> +parse_range(const char *str, long min, long max, long num[])
> +{
> + char *next;
> +
> + next = parse_num(str, min, max, num);
> + if (next == NULL)
> + return NULL;
> + if (next&& *next == ':')
> + next = parse_num(next+1, min, max,&num[1]);
> + else
> + num[1] = num[0];
> + return next;
> +}
> +
> +static int
> +parse_icmpv6(const char *icmpv6type, uint8_t type[], uint8_t code[])
> +{
> + static const unsigned int limit = ARRAY_SIZE(icmpv6_codes);
> + unsigned int match = limit;
> + unsigned int i;
> + long number[2];
> +
> + for (i = 0; i< limit; i++) {
> + if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type)))
> + continue;
> + if (match != limit)
> + ebt_print_error("Ambiguous ICMPv6 type `%s':"
> + " `%s' or `%s'?",
> + icmpv6type, icmpv6_codes[match].name,
> + icmpv6_codes[i].name);
> + match = i;
> + }
> +
> + if (match< limit) {
> + type[0] = type[1] = icmpv6_codes[match].type;
> + code[0] = icmpv6_codes[match].code_min;
> + code[1] = icmpv6_codes[match].code_max;
> + } else {
> + char *next = parse_range(icmpv6type, 0, 255, number);
> + if (!next) {
> + ebt_print_error("Unknown ICMPv6 type `%s'",
> + icmpv6type);
> + return -1;
> + }
> + type[0] = (uint8_t) number[0];
> + type[1] = (uint8_t) number[1];
> + switch (*next) {
> + case 0:
> + code[0] = 0;
> + code[1] = 255;
> + return 0;
> + case '/':
> + next = parse_range(next+1, 0, 255, number);
> + code[0] = (uint8_t) number[0];
> + code[1] = (uint8_t) number[1];
> + if (next == NULL)
> + return -1;
> + if (next&& *next == 0)
> + return 0;
> + /* fallthrough */
> + default:
> + ebt_print_error("unknown character %c", *next);
> + return -1;
> + }
> + }
> + return 0;
> +}
> +
> static void print_port_range(uint16_t *ports)
> {
> if (ports[0] == ports[1])
> @@ -99,6 +240,58 @@ static void print_port_range(uint16_t *ports)
> printf("%d:%d ", ports[0], ports[1]);
> }
>
> +static void print_icmp_code(uint8_t *code)
> +{
> + if (code[0] == code[1])
> + printf("/%"PRIu8 " ", code[0]);
> + else
> + printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]);
> +}
> +
> +static void print_icmp_type(uint8_t *type, uint8_t *code)
> +{
> + unsigned int i;
> +
> + if (type[0] != type[1]) {
> + printf("%"PRIu8 ":%" PRIu8, type[0], type[1]);
> + print_icmp_code(code);
> + return;
> + }
> +
> + for (i = 0; i< ARRAY_SIZE(icmpv6_codes); i++) {
> + if (icmpv6_codes[i].type != type[0])
> + continue;
> +
> + if (icmpv6_codes[i].code_min == code[0]&&
> + icmpv6_codes[i].code_max == code[1]) {
> + printf("%s ", icmpv6_codes[i].name);
> + return;
> + }
> + }
> + printf("%"PRIu8, type[0]);
> + print_icmp_code(code);
> +}
> +
> +static void print_icmpv6types(void)
> +{
> + unsigned int i;
> + printf("Valid ICMPv6 Types:");
> +
> + for (i=0; i< ARRAY_SIZE(icmpv6_codes); i++) {
> + if (i&& icmpv6_codes[i].type == icmpv6_codes[i-1].type) {
> + if (icmpv6_codes[i].code_min == icmpv6_codes[i-1].code_min
> + && (icmpv6_codes[i].code_max
> + == icmpv6_codes[i-1].code_max))
> + printf(" (%s)", icmpv6_codes[i].name);
> + else
> + printf("\n %s", icmpv6_codes[i].name);
> + }
> + else
> + printf("\n%s", icmpv6_codes[i].name);
> + }
> + printf("\n");
> +}
> +
> static void print_help()
> {
> printf(
> @@ -108,7 +301,9 @@ static void print_help()
> "--ip6-tclass [!] tclass : ipv6 traffic class specification\n"
> "--ip6-proto [!] protocol : ipv6 protocol specification\n"
> "--ip6-sport [!] port[:port] : tcp/udp source port or port range\n"
> -"--ip6-dport [!] port[:port] : tcp/udp destination port or port range\n");
> +"--ip6-dport [!] port[:port] : tcp/udp destination port or port range\n"
> +"--ip6-icmp-type [!] type[[:type]/code[:code]] : ipv6-icmp type/code or type/code range\n");
> +print_icmpv6types();
> }
>
> static void init(struct ebt_entry_match *match)
> @@ -170,6 +365,15 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
> parse_port_range(NULL, optarg, ipinfo->dport);
> break;
>
> + case IP_ICMP6:
> + ebt_check_option2(flags, EBT_IP6_ICMP6);
> + ipinfo->bitmask |= EBT_IP6_ICMP6;
> + if (ebt_check_inverse2(optarg))
> + ipinfo->invflags |= EBT_IP6_ICMP6;
> + if (parse_icmpv6(optarg, ipinfo->icmpv6_type, ipinfo->icmpv6_code))
> + return 0;
> + break;
> +
> case IP_TCLASS:
> ebt_check_option2(flags, OPT_TCLASS);
> if (ebt_check_inverse2(optarg))
> @@ -223,6 +427,12 @@ static void final_check(const struct ebt_u_entry *entry,
> ebt_print_error("For port filtering the IP protocol must be "
> "either 6 (tcp), 17 (udp), 33 (dccp) or "
> "132 (sctp)");
> + if ((ipinfo->bitmask& EBT_IP6_ICMP6)&&
> + (!(ipinfo->bitmask& EBT_IP6_PROTO) ||
> + ipinfo->invflags& EBT_IP6_PROTO ||
> + ipinfo->protocol != IPPROTO_ICMPV6))
> + ebt_print_error("For ipv6-icmp filtering the IP protocol must be "
> + "58 (ipv6-icmp)");
> }
>
> static void print(const struct ebt_u_entry *entry,
> @@ -275,6 +485,12 @@ static void print(const struct ebt_u_entry *entry,
> printf("! ");
> print_port_range(ipinfo->dport);
> }
> + if (ipinfo->bitmask& EBT_IP6_ICMP6) {
> + printf("--ip6-icmp-type ");
> + if (ipinfo->invflags& EBT_IP6_ICMP6)
> + printf("! ");
> + print_icmp_type(ipinfo->icmpv6_type, ipinfo->icmpv6_code);
> + }
> }
>
> static int compare(const struct ebt_entry_match *m1,
> @@ -317,6 +533,13 @@ static int compare(const struct ebt_entry_match *m1,
> ipinfo1->dport[1] != ipinfo2->dport[1])
> return 0;
> }
> + if (ipinfo1->bitmask& EBT_IP6_ICMP6) {
> + if (ipinfo1->icmpv6_type[0] != ipinfo2->icmpv6_type[0] ||
> + ipinfo1->icmpv6_type[1] != ipinfo2->icmpv6_type[1] ||
> + ipinfo1->icmpv6_code[0] != ipinfo2->icmpv6_code[0] ||
> + ipinfo1->icmpv6_code[1] != ipinfo2->icmpv6_code[1])
> + return 0;
> + }
> return 1;
> }
>
> diff --git a/include/ebtables_u.h b/include/ebtables_u.h
> index 910c213..c29476d 100644
> --- a/include/ebtables_u.h
> +++ b/include/ebtables_u.h
> @@ -376,4 +376,8 @@ extern int ebt_printstyle_mac;
> #define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
> #endif
> #define ATOMIC_ENV_VARIABLE "EBTABLES_ATOMIC_FILE"
> +
> +#ifndef ARRAY_SIZE
> +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
> +#endif
> #endif /* EBTABLES_U_H */
--
Bart De Schuymer
www.artinalgorithms.be
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2010-12-18 16:40 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-17 16:24 [PATCH] ebtables: extend ebt_ip6 to allow matching on ipv6-icmp types/codes Florian Westphal
2010-12-18 16:35 ` Bart De Schuymer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).