1184 lines
38 KiB
Diff
1184 lines
38 KiB
Diff
From: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
Date: Sun, 4 Mar 2018 10:26:34 +0100
|
|
Subject: ebtables: add support for ICMP/IGMP type matches
|
|
|
|
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
|
|
diff --git a/package/network/utils/ebtables/patches/301-0001-include-sync-linux-netfilter_bridge-ebt_ip.h-with-ke.patch b/package/network/utils/ebtables/patches/301-0001-include-sync-linux-netfilter_bridge-ebt_ip.h-with-ke.patch
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..b6f42c6a4affc9bb04a6ac9269698e751a932f2a
|
|
--- /dev/null
|
|
+++ b/package/network/utils/ebtables/patches/301-0001-include-sync-linux-netfilter_bridge-ebt_ip.h-with-ke.patch
|
|
@@ -0,0 +1,56 @@
|
|
+From 44fcc3392bb7d52df2ad52b8e9437255b8c29d5a Mon Sep 17 00:00:00 2001
|
|
+Message-Id: <44fcc3392bb7d52df2ad52b8e9437255b8c29d5a.1520151963.git.mschiffer@universe-factory.net>
|
|
+In-Reply-To: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+References: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+From: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+Date: Sat, 3 Mar 2018 12:14:48 +0100
|
|
+Subject: [PATCH ebtables 1/4] include: sync linux/netfilter_bridge/ebt_ip.h
|
|
+ with kernel
|
|
+
|
|
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+---
|
|
+ include/linux/netfilter_bridge/ebt_ip.h | 16 +++++++++++++---
|
|
+ 1 file changed, 13 insertions(+), 3 deletions(-)
|
|
+
|
|
+diff --git a/include/linux/netfilter_bridge/ebt_ip.h b/include/linux/netfilter_bridge/ebt_ip.h
|
|
+index c4bbc41b0ea4..46d6261370b0 100644
|
|
+--- a/include/linux/netfilter_bridge/ebt_ip.h
|
|
++++ b/include/linux/netfilter_bridge/ebt_ip.h
|
|
+@@ -1,3 +1,4 @@
|
|
++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
|
+ /*
|
|
+ * ebt_ip
|
|
+ *
|
|
+@@ -23,8 +24,10 @@
|
|
+ #define EBT_IP_PROTO 0x08
|
|
+ #define EBT_IP_SPORT 0x10
|
|
+ #define EBT_IP_DPORT 0x20
|
|
++#define EBT_IP_ICMP 0x40
|
|
++#define EBT_IP_IGMP 0x80
|
|
+ #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
|
|
+- EBT_IP_SPORT | EBT_IP_DPORT )
|
|
++ EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP)
|
|
+ #define EBT_IP_MATCH "ip"
|
|
+
|
|
+ /* the same values are used for the invflags */
|
|
+@@ -37,8 +40,15 @@ struct ebt_ip_info {
|
|
+ __u8 protocol;
|
|
+ __u8 bitmask;
|
|
+ __u8 invflags;
|
|
+- __u16 sport[2];
|
|
+- __u16 dport[2];
|
|
++ union {
|
|
++ __u16 sport[2];
|
|
++ __u8 icmp_type[2];
|
|
++ __u8 igmp_type[2];
|
|
++ };
|
|
++ union {
|
|
++ __u16 dport[2];
|
|
++ __u8 icmp_code[2];
|
|
++ };
|
|
+ };
|
|
+
|
|
+ #endif
|
|
+--
|
|
+2.16.2
|
|
+
|
|
diff --git a/package/network/utils/ebtables/patches/301-0002-Move-ICMP-type-handling-functions-from-ebt_ip6-to-us.patch b/package/network/utils/ebtables/patches/301-0002-Move-ICMP-type-handling-functions-from-ebt_ip6-to-us.patch
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..c3eaec4412fcaebffa84b409a0a66e2f714a0e8d
|
|
--- /dev/null
|
|
+++ b/package/network/utils/ebtables/patches/301-0002-Move-ICMP-type-handling-functions-from-ebt_ip6-to-us.patch
|
|
@@ -0,0 +1,465 @@
|
|
+From e40c68fcf13e2244ab6c87844126167e998ccb56 Mon Sep 17 00:00:00 2001
|
|
+Message-Id: <e40c68fcf13e2244ab6c87844126167e998ccb56.1520151963.git.mschiffer@universe-factory.net>
|
|
+In-Reply-To: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+References: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+From: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+Date: Sun, 4 Mar 2018 08:18:18 +0100
|
|
+Subject: [PATCH ebtables 2/4] Move ICMP type handling functions from ebt_ip6
|
|
+ to useful_functions.c
|
|
+
|
|
+Allow using these functions for ebt_ip as well.
|
|
+
|
|
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+---
|
|
+ extensions/ebt_ip6.c | 165 +++------------------------------------------------
|
|
+ include/ebtables_u.h | 17 +++++-
|
|
+ useful_functions.c | 151 +++++++++++++++++++++++++++++++++++++++++++++-
|
|
+ 3 files changed, 174 insertions(+), 159 deletions(-)
|
|
+
|
|
+diff --git a/extensions/ebt_ip6.c b/extensions/ebt_ip6.c
|
|
+index dd48547b0010..347797b4afe1 100644
|
|
+--- a/extensions/ebt_ip6.c
|
|
++++ b/extensions/ebt_ip6.c
|
|
+@@ -11,9 +11,6 @@
|
|
+ *
|
|
+ */
|
|
+
|
|
+-#include <errno.h>
|
|
+-#include <inttypes.h>
|
|
+-#include <limits.h>
|
|
+ #include <stdio.h>
|
|
+ #include <stdlib.h>
|
|
+ #include <string.h>
|
|
+@@ -51,13 +48,7 @@ static const struct option opts[] =
|
|
+ };
|
|
+
|
|
+
|
|
+-struct icmpv6_names {
|
|
+- const char *name;
|
|
+- uint8_t type;
|
|
+- uint8_t code_min, code_max;
|
|
+-};
|
|
+-
|
|
+-static const struct icmpv6_names icmpv6_codes[] = {
|
|
++static const struct ebt_icmp_names icmpv6_codes[] = {
|
|
+ { "destination-unreachable", 1, 0, 0xFF },
|
|
+ { "no-route", 1, 0, 0 },
|
|
+ { "communication-prohibited", 1, 1, 1 },
|
|
+@@ -141,97 +132,6 @@ 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])
|
|
+@@ -240,58 +140,6 @@ 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(
|
|
+@@ -303,7 +151,9 @@ static void print_help()
|
|
+ "--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-icmp-type [!] type[[:type]/code[:code]] : ipv6-icmp type/code or type/code range\n");
|
|
+-print_icmpv6types();
|
|
++
|
|
++ printf("\nValid ICMPv6 Types:\n");
|
|
++ ebt_print_icmp_types(icmpv6_codes, ARRAY_SIZE(icmpv6_codes));
|
|
+ }
|
|
+
|
|
+ static void init(struct ebt_entry_match *match)
|
|
+@@ -374,7 +224,9 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
|
|
+ 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))
|
|
++ if (ebt_parse_icmp(icmpv6_codes, ARRAY_SIZE(icmpv6_codes),
|
|
++ optarg, ipinfo->icmpv6_type,
|
|
++ ipinfo->icmpv6_code))
|
|
+ return 0;
|
|
+ break;
|
|
+
|
|
+@@ -493,7 +345,8 @@ static void print(const struct ebt_u_entry *entry,
|
|
+ printf("--ip6-icmp-type ");
|
|
+ if (ipinfo->invflags & EBT_IP6_ICMP6)
|
|
+ printf("! ");
|
|
+- print_icmp_type(ipinfo->icmpv6_type, ipinfo->icmpv6_code);
|
|
++ ebt_print_icmp_type(icmpv6_codes, ARRAY_SIZE(icmpv6_codes),
|
|
++ ipinfo->icmpv6_type, ipinfo->icmpv6_code);
|
|
+ }
|
|
+ }
|
|
+
|
|
+diff --git a/include/ebtables_u.h b/include/ebtables_u.h
|
|
+index 35a5bcc54c86..17afa9487f5a 100644
|
|
+--- a/include/ebtables_u.h
|
|
++++ b/include/ebtables_u.h
|
|
+@@ -222,6 +222,15 @@ struct ebt_u_target
|
|
+ struct ebt_u_target *next;
|
|
+ };
|
|
+
|
|
++
|
|
++struct ebt_icmp_names {
|
|
++ const char *name;
|
|
++ uint8_t type;
|
|
++ uint8_t code_min, code_max;
|
|
++};
|
|
++
|
|
++
|
|
++
|
|
+ /* libebtc.c */
|
|
+
|
|
+ extern struct ebt_u_table *ebt_tables;
|
|
+@@ -300,11 +309,17 @@ void ebt_print_mac_and_mask(const unsigned char *mac, const unsigned char *mask)
|
|
+ int ebt_get_mac_and_mask(const char *from, unsigned char *to, unsigned char *mask);
|
|
+ void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk);
|
|
+ char *ebt_mask_to_dotted(uint32_t mask);
|
|
+-void ebt_parse_ip6_address(char *address, struct in6_addr *addr,
|
|
++void ebt_parse_ip6_address(char *address, struct in6_addr *addr,
|
|
+ struct in6_addr *msk);
|
|
+ char *ebt_ip6_to_numeric(const struct in6_addr *addrp);
|
|
+ char *ebt_ip6_mask_to_string(const struct in6_addr *msk);
|
|
+
|
|
++int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes,
|
|
++ const char *icmptype, uint8_t type[], uint8_t code[]);
|
|
++void ebt_print_icmp_type(const struct ebt_icmp_names *icmp_codes,
|
|
++ size_t n_codes, uint8_t *type, uint8_t *code);
|
|
++void ebt_print_icmp_types(const struct ebt_icmp_names *icmp_codes,
|
|
++ size_t n_codes);
|
|
+
|
|
+ int do_command(int argc, char *argv[], int exec_style,
|
|
+ struct ebt_u_replace *replace_);
|
|
+diff --git a/useful_functions.c b/useful_functions.c
|
|
+index d14cbe9dbdba..8f54bae83fae 100644
|
|
+--- a/useful_functions.c
|
|
++++ b/useful_functions.c
|
|
+@@ -24,6 +24,9 @@
|
|
+ */
|
|
+ #include "include/ebtables_u.h"
|
|
+ #include "include/ethernetdb.h"
|
|
++#include <errno.h>
|
|
++#include <inttypes.h>
|
|
++#include <limits.h>
|
|
+ #include <stdio.h>
|
|
+ #include <netinet/ether.h>
|
|
+ #include <string.h>
|
|
+@@ -34,6 +37,7 @@
|
|
+ #include <sys/socket.h>
|
|
+ #include <arpa/inet.h>
|
|
+
|
|
++
|
|
+ const unsigned char mac_type_unicast[ETH_ALEN] = {0,0,0,0,0,0};
|
|
+ const unsigned char msk_type_unicast[ETH_ALEN] = {1,0,0,0,0,0};
|
|
+ const unsigned char mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
|
|
+@@ -188,7 +192,7 @@ static int undot_ip(char *ip, unsigned char *ip2)
|
|
+ return -1;
|
|
+ *q = '\0';
|
|
+ onebyte = strtol(p, &end, 10);
|
|
+- if (*end != '\0' || onebyte > 255 || onebyte < 0)
|
|
++ if (*end != '\0' || onebyte > 255 || onebyte < 0)
|
|
+ return -1;
|
|
+ ip2[i] = (unsigned char)onebyte;
|
|
+ p = q + 1;
|
|
+@@ -275,7 +279,7 @@ char *ebt_mask_to_dotted(uint32_t mask)
|
|
+ *buf = '\0';
|
|
+ else
|
|
+ /* Mask was not a decent combination of 1's and 0's */
|
|
+- sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0],
|
|
++ sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0],
|
|
+ ((unsigned char *)&mask)[1], ((unsigned char *)&mask)[2],
|
|
+ ((unsigned char *)&mask)[3]);
|
|
+
|
|
+@@ -424,3 +428,146 @@ char *ebt_ip6_mask_to_string(const struct in6_addr *msk)
|
|
+ sprintf(buf, "/%s", ebt_ip6_to_numeric(msk));
|
|
+ return buf;
|
|
+ }
|
|
++
|
|
++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;
|
|
++}
|
|
++
|
|
++int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes,
|
|
++ const char *icmptype, uint8_t type[], uint8_t code[])
|
|
++{
|
|
++ unsigned int match = n_codes;
|
|
++ unsigned int i;
|
|
++ long number[2];
|
|
++
|
|
++ for (i = 0; i < n_codes; i++) {
|
|
++ if (strncasecmp(icmp_codes[i].name, icmptype, strlen(icmptype)))
|
|
++ continue;
|
|
++ if (match != n_codes)
|
|
++ ebt_print_error("Ambiguous ICMP type `%s':"
|
|
++ " `%s' or `%s'?",
|
|
++ icmptype, icmp_codes[match].name,
|
|
++ icmp_codes[i].name);
|
|
++ match = i;
|
|
++ }
|
|
++
|
|
++ if (match < n_codes) {
|
|
++ type[0] = type[1] = icmp_codes[match].type;
|
|
++ code[0] = icmp_codes[match].code_min;
|
|
++ code[1] = icmp_codes[match].code_max;
|
|
++ } else {
|
|
++ char *next = parse_range(icmptype, 0, 255, number);
|
|
++ if (!next) {
|
|
++ ebt_print_error("Unknown ICMP type `%s'",
|
|
++ icmptype);
|
|
++ 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_icmp_code(uint8_t *code)
|
|
++{
|
|
++ if (code[0] == code[1])
|
|
++ printf("/%"PRIu8 " ", code[0]);
|
|
++ else
|
|
++ printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]);
|
|
++}
|
|
++
|
|
++void ebt_print_icmp_type(const struct ebt_icmp_names *icmp_codes,
|
|
++ size_t n_codes, 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 < n_codes; i++) {
|
|
++ if (icmp_codes[i].type != type[0])
|
|
++ continue;
|
|
++
|
|
++ if (icmp_codes[i].code_min == code[0] &&
|
|
++ icmp_codes[i].code_max == code[1]) {
|
|
++ printf("%s ", icmp_codes[i].name);
|
|
++ return;
|
|
++ }
|
|
++ }
|
|
++ printf("%"PRIu8, type[0]);
|
|
++ print_icmp_code(code);
|
|
++}
|
|
++
|
|
++void ebt_print_icmp_types(const struct ebt_icmp_names *icmp_codes,
|
|
++ size_t n_codes)
|
|
++{
|
|
++ unsigned int i;
|
|
++
|
|
++ for (i = 0; i < n_codes; i++) {
|
|
++ if (i && icmp_codes[i].type == icmp_codes[i-1].type) {
|
|
++ if (icmp_codes[i].code_min == icmp_codes[i-1].code_min
|
|
++ && (icmp_codes[i].code_max
|
|
++ == icmp_codes[i-1].code_max))
|
|
++ printf(" (%s)", icmp_codes[i].name);
|
|
++ else
|
|
++ printf("\n %s", icmp_codes[i].name);
|
|
++ }
|
|
++ else
|
|
++ printf("\n%s", icmp_codes[i].name);
|
|
++ }
|
|
++ printf("\n");
|
|
++}
|
|
+--
|
|
+2.16.2
|
|
+
|
|
diff --git a/package/network/utils/ebtables/patches/301-0003-ebt_ip-add-support-for-matching-ICMP-type-and-code.patch b/package/network/utils/ebtables/patches/301-0003-ebt_ip-add-support-for-matching-ICMP-type-and-code.patch
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..2c83168933d88535747f0bc18d3ebbe03c6b1f30
|
|
--- /dev/null
|
|
+++ b/package/network/utils/ebtables/patches/301-0003-ebt_ip-add-support-for-matching-ICMP-type-and-code.patch
|
|
@@ -0,0 +1,182 @@
|
|
+From 76bc7b4ede217228e782a6d4dfaa67f772a08441 Mon Sep 17 00:00:00 2001
|
|
+Message-Id: <76bc7b4ede217228e782a6d4dfaa67f772a08441.1520151963.git.mschiffer@universe-factory.net>
|
|
+In-Reply-To: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+References: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+From: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+Date: Sat, 3 Mar 2018 12:42:46 +0100
|
|
+Subject: [PATCH ebtables 3/4] ebt_ip: add support for matching ICMP type and
|
|
+ code
|
|
+
|
|
+We already have ICMPv6 type/code matches. This adds support for IPv4 ICMP
|
|
+matches in the same way.
|
|
+
|
|
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+---
|
|
+ extensions/ebt_ip.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++--
|
|
+ 1 file changed, 94 insertions(+), 2 deletions(-)
|
|
+
|
|
+diff --git a/extensions/ebt_ip.c b/extensions/ebt_ip.c
|
|
+index 59559feffa50..42660d4564fb 100644
|
|
+--- a/extensions/ebt_ip.c
|
|
++++ b/extensions/ebt_ip.c
|
|
+@@ -24,6 +24,7 @@
|
|
+ #define IP_PROTO '4'
|
|
+ #define IP_SPORT '5'
|
|
+ #define IP_DPORT '6'
|
|
++#define IP_ICMP '7'
|
|
+
|
|
+ static const struct option opts[] =
|
|
+ {
|
|
+@@ -38,9 +39,64 @@ static const struct option opts[] =
|
|
+ { "ip-sport" , required_argument, 0, IP_SPORT },
|
|
+ { "ip-destination-port" , required_argument, 0, IP_DPORT },
|
|
+ { "ip-dport" , required_argument, 0, IP_DPORT },
|
|
++ { "ip-icmp-type" , required_argument, 0, IP_ICMP },
|
|
+ { 0 }
|
|
+ };
|
|
+
|
|
++static const struct ebt_icmp_names icmp_codes[] = {
|
|
++ { "echo-reply", 0, 0, 0xFF },
|
|
++ /* Alias */ { "pong", 0, 0, 0xFF },
|
|
++
|
|
++ { "destination-unreachable", 3, 0, 0xFF },
|
|
++ { "network-unreachable", 3, 0, 0 },
|
|
++ { "host-unreachable", 3, 1, 1 },
|
|
++ { "protocol-unreachable", 3, 2, 2 },
|
|
++ { "port-unreachable", 3, 3, 3 },
|
|
++ { "fragmentation-needed", 3, 4, 4 },
|
|
++ { "source-route-failed", 3, 5, 5 },
|
|
++ { "network-unknown", 3, 6, 6 },
|
|
++ { "host-unknown", 3, 7, 7 },
|
|
++ { "network-prohibited", 3, 9, 9 },
|
|
++ { "host-prohibited", 3, 10, 10 },
|
|
++ { "TOS-network-unreachable", 3, 11, 11 },
|
|
++ { "TOS-host-unreachable", 3, 12, 12 },
|
|
++ { "communication-prohibited", 3, 13, 13 },
|
|
++ { "host-precedence-violation", 3, 14, 14 },
|
|
++ { "precedence-cutoff", 3, 15, 15 },
|
|
++
|
|
++ { "source-quench", 4, 0, 0xFF },
|
|
++
|
|
++ { "redirect", 5, 0, 0xFF },
|
|
++ { "network-redirect", 5, 0, 0 },
|
|
++ { "host-redirect", 5, 1, 1 },
|
|
++ { "TOS-network-redirect", 5, 2, 2 },
|
|
++ { "TOS-host-redirect", 5, 3, 3 },
|
|
++
|
|
++ { "echo-request", 8, 0, 0xFF },
|
|
++ /* Alias */ { "ping", 8, 0, 0xFF },
|
|
++
|
|
++ { "router-advertisement", 9, 0, 0xFF },
|
|
++
|
|
++ { "router-solicitation", 10, 0, 0xFF },
|
|
++
|
|
++ { "time-exceeded", 11, 0, 0xFF },
|
|
++ /* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
|
|
++ { "ttl-zero-during-transit", 11, 0, 0 },
|
|
++ { "ttl-zero-during-reassembly", 11, 1, 1 },
|
|
++
|
|
++ { "parameter-problem", 12, 0, 0xFF },
|
|
++ { "ip-header-bad", 12, 0, 0 },
|
|
++ { "required-option-missing", 12, 1, 1 },
|
|
++
|
|
++ { "timestamp-request", 13, 0, 0xFF },
|
|
++
|
|
++ { "timestamp-reply", 14, 0, 0xFF },
|
|
++
|
|
++ { "address-mask-request", 17, 0, 0xFF },
|
|
++
|
|
++ { "address-mask-reply", 18, 0, 0xFF }
|
|
++};
|
|
++
|
|
+ /* put the mask into 4 bytes */
|
|
+ /* transform a protocol and service name into a port number */
|
|
+ static uint16_t parse_port(const char *protocol, const char *name)
|
|
+@@ -105,7 +161,11 @@ static void print_help()
|
|
+ "--ip-tos [!] tos : ip tos specification\n"
|
|
+ "--ip-proto [!] protocol : ip protocol specification\n"
|
|
+ "--ip-sport [!] port[:port] : tcp/udp source port or port range\n"
|
|
+-"--ip-dport [!] port[:port] : tcp/udp destination port or port range\n");
|
|
++"--ip-dport [!] port[:port] : tcp/udp destination port or port range\n"
|
|
++"--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n");
|
|
++
|
|
++ printf("\nValid ICMP Types:\n");
|
|
++ ebt_print_icmp_types(icmp_codes, ARRAY_SIZE(icmp_codes));
|
|
+ }
|
|
+
|
|
+ static void init(struct ebt_entry_match *match)
|
|
+@@ -122,6 +182,7 @@ static void init(struct ebt_entry_match *match)
|
|
+ #define OPT_PROTO 0x08
|
|
+ #define OPT_SPORT 0x10
|
|
+ #define OPT_DPORT 0x20
|
|
++#define OPT_ICMP 0x40
|
|
+ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
|
|
+ unsigned int *flags, struct ebt_entry_match **match)
|
|
+ {
|
|
+@@ -170,6 +231,16 @@ 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_ICMP:
|
|
++ ebt_check_option2(flags, OPT_ICMP);
|
|
++ ipinfo->bitmask |= EBT_IP_ICMP;
|
|
++ if (ebt_check_inverse2(optarg))
|
|
++ ipinfo->invflags |= EBT_IP_ICMP;
|
|
++ if (ebt_parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes), optarg,
|
|
++ ipinfo->icmp_type, ipinfo->icmp_code))
|
|
++ return 0;
|
|
++ break;
|
|
++
|
|
+ case IP_myTOS:
|
|
+ ebt_check_option2(flags, OPT_TOS);
|
|
+ if (ebt_check_inverse2(optarg))
|
|
+@@ -219,10 +290,17 @@ static void final_check(const struct ebt_u_entry *entry,
|
|
+ (ipinfo->protocol!=IPPROTO_TCP &&
|
|
+ ipinfo->protocol!=IPPROTO_UDP &&
|
|
+ ipinfo->protocol!=IPPROTO_SCTP &&
|
|
+- ipinfo->protocol!=IPPROTO_DCCP)))
|
|
++ ipinfo->protocol!=IPPROTO_DCCP))) {
|
|
+ ebt_print_error("For port filtering the IP protocol must be "
|
|
+ "either 6 (tcp), 17 (udp), 33 (dccp) or "
|
|
+ "132 (sctp)");
|
|
++ } else if ((ipinfo->bitmask & EBT_IP_ICMP) &&
|
|
++ (!(ipinfo->bitmask & EBT_IP_PROTO) ||
|
|
++ ipinfo->invflags & EBT_IP_PROTO ||
|
|
++ ipinfo->protocol != IPPROTO_ICMP)) {
|
|
++ ebt_print_error("For ICMP filtering the IP protocol must be "
|
|
++ "1 (icmp)");
|
|
++ }
|
|
+ }
|
|
+
|
|
+ static void print(const struct ebt_u_entry *entry,
|
|
+@@ -280,6 +358,13 @@ static void print(const struct ebt_u_entry *entry,
|
|
+ printf("! ");
|
|
+ print_port_range(ipinfo->dport);
|
|
+ }
|
|
++ if (ipinfo->bitmask & EBT_IP_ICMP) {
|
|
++ printf("--ip-icmp-type ");
|
|
++ if (ipinfo->invflags & EBT_IP_ICMP)
|
|
++ printf("! ");
|
|
++ ebt_print_icmp_type(icmp_codes, ARRAY_SIZE(icmp_codes),
|
|
++ ipinfo->icmp_type, ipinfo->icmp_code);
|
|
++ }
|
|
+ }
|
|
+
|
|
+ static int compare(const struct ebt_entry_match *m1,
|
|
+@@ -322,6 +407,13 @@ static int compare(const struct ebt_entry_match *m1,
|
|
+ ipinfo1->dport[1] != ipinfo2->dport[1])
|
|
+ return 0;
|
|
+ }
|
|
++ if (ipinfo1->bitmask & EBT_IP_ICMP) {
|
|
++ if (ipinfo1->icmp_type[0] != ipinfo2->icmp_type[0] ||
|
|
++ ipinfo1->icmp_type[1] != ipinfo2->icmp_type[1] ||
|
|
++ ipinfo1->icmp_code[0] != ipinfo2->icmp_code[0] ||
|
|
++ ipinfo1->icmp_code[1] != ipinfo2->icmp_code[1])
|
|
++ return 0;
|
|
++ }
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+--
|
|
+2.16.2
|
|
+
|
|
diff --git a/package/network/utils/ebtables/patches/301-0004-ebt_ip-add-support-for-matching-IGMP-type.patch b/package/network/utils/ebtables/patches/301-0004-ebt_ip-add-support-for-matching-IGMP-type.patch
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..1a7fe6d2ffcd0baf620dd36d6d3ba200f8b823e9
|
|
--- /dev/null
|
|
+++ b/package/network/utils/ebtables/patches/301-0004-ebt_ip-add-support-for-matching-IGMP-type.patch
|
|
@@ -0,0 +1,207 @@
|
|
+From b20e495bdf0c5eec3244cf7f98bae24316ffc3ab Mon Sep 17 00:00:00 2001
|
|
+Message-Id: <b20e495bdf0c5eec3244cf7f98bae24316ffc3ab.1520151963.git.mschiffer@universe-factory.net>
|
|
+In-Reply-To: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+References: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+From: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+Date: Sat, 3 Mar 2018 13:50:23 +0100
|
|
+Subject: [PATCH ebtables 4/4] ebt_ip: add support for matching IGMP type
|
|
+
|
|
+We already have ICMPv6 type/code matches (which can be used to distinguish
|
|
+different types of MLD packets). Add support for IPv4 IGMP matches in the
|
|
+same way.
|
|
+
|
|
+To reuse as much code as possible, the ICMP type/code handling functions
|
|
+are extended to allow passing a NULL code range.
|
|
+
|
|
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+---
|
|
+ extensions/ebt_ip.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
|
|
+ useful_functions.c | 35 ++++++++++++++++++++++-------------
|
|
+ 2 files changed, 65 insertions(+), 14 deletions(-)
|
|
+
|
|
+diff --git a/extensions/ebt_ip.c b/extensions/ebt_ip.c
|
|
+index 42660d4564fb..1ffdb95f156d 100644
|
|
+--- a/extensions/ebt_ip.c
|
|
++++ b/extensions/ebt_ip.c
|
|
+@@ -25,6 +25,7 @@
|
|
+ #define IP_SPORT '5'
|
|
+ #define IP_DPORT '6'
|
|
+ #define IP_ICMP '7'
|
|
++#define IP_IGMP '8'
|
|
+
|
|
+ static const struct option opts[] =
|
|
+ {
|
|
+@@ -40,6 +41,7 @@ static const struct option opts[] =
|
|
+ { "ip-destination-port" , required_argument, 0, IP_DPORT },
|
|
+ { "ip-dport" , required_argument, 0, IP_DPORT },
|
|
+ { "ip-icmp-type" , required_argument, 0, IP_ICMP },
|
|
++ { "ip-igmp-type" , required_argument, 0, IP_IGMP },
|
|
+ { 0 }
|
|
+ };
|
|
+
|
|
+@@ -97,6 +99,14 @@ static const struct ebt_icmp_names icmp_codes[] = {
|
|
+ { "address-mask-reply", 18, 0, 0xFF }
|
|
+ };
|
|
+
|
|
++static const struct ebt_icmp_names igmp_types[] = {
|
|
++ { "membership-query", 0x11 },
|
|
++ { "membership-report-v1", 0x12 },
|
|
++ { "membership-report-v2", 0x16 },
|
|
++ { "leave-group", 0x17 },
|
|
++ { "membership-report-v3", 0x22 },
|
|
++};
|
|
++
|
|
+ /* put the mask into 4 bytes */
|
|
+ /* transform a protocol and service name into a port number */
|
|
+ static uint16_t parse_port(const char *protocol, const char *name)
|
|
+@@ -162,10 +172,13 @@ static void print_help()
|
|
+ "--ip-proto [!] protocol : ip protocol specification\n"
|
|
+ "--ip-sport [!] port[:port] : tcp/udp source port or port range\n"
|
|
+ "--ip-dport [!] port[:port] : tcp/udp destination port or port range\n"
|
|
+-"--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n");
|
|
++"--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n"
|
|
++"--ip-igmp-type [!] type[:type] : igmp type or type range\n");
|
|
+
|
|
+ printf("\nValid ICMP Types:\n");
|
|
+ ebt_print_icmp_types(icmp_codes, ARRAY_SIZE(icmp_codes));
|
|
++ printf("\nValid IGMP Types:\n");
|
|
++ ebt_print_icmp_types(igmp_types, ARRAY_SIZE(igmp_types));
|
|
+ }
|
|
+
|
|
+ static void init(struct ebt_entry_match *match)
|
|
+@@ -183,6 +196,7 @@ static void init(struct ebt_entry_match *match)
|
|
+ #define OPT_SPORT 0x10
|
|
+ #define OPT_DPORT 0x20
|
|
+ #define OPT_ICMP 0x40
|
|
++#define OPT_IGMP 0x80
|
|
+ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
|
|
+ unsigned int *flags, struct ebt_entry_match **match)
|
|
+ {
|
|
+@@ -241,6 +255,16 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
|
|
+ return 0;
|
|
+ break;
|
|
+
|
|
++ case IP_IGMP:
|
|
++ ebt_check_option2(flags, OPT_IGMP);
|
|
++ ipinfo->bitmask |= EBT_IP_IGMP;
|
|
++ if (ebt_check_inverse2(optarg))
|
|
++ ipinfo->invflags |= EBT_IP_IGMP;
|
|
++ if (ebt_parse_icmp(igmp_types, ARRAY_SIZE(igmp_types), optarg,
|
|
++ ipinfo->igmp_type, NULL))
|
|
++ return 0;
|
|
++ break;
|
|
++
|
|
+ case IP_myTOS:
|
|
+ ebt_check_option2(flags, OPT_TOS);
|
|
+ if (ebt_check_inverse2(optarg))
|
|
+@@ -300,6 +324,12 @@ static void final_check(const struct ebt_u_entry *entry,
|
|
+ ipinfo->protocol != IPPROTO_ICMP)) {
|
|
+ ebt_print_error("For ICMP filtering the IP protocol must be "
|
|
+ "1 (icmp)");
|
|
++ } else if ((ipinfo->bitmask & EBT_IP_IGMP) &&
|
|
++ (!(ipinfo->bitmask & EBT_IP_PROTO) ||
|
|
++ ipinfo->invflags & EBT_IP_PROTO ||
|
|
++ ipinfo->protocol != IPPROTO_IGMP)) {
|
|
++ ebt_print_error("For IGMP filtering the IP protocol must be "
|
|
++ "2 (igmp)");
|
|
+ }
|
|
+ }
|
|
+
|
|
+@@ -365,6 +395,13 @@ static void print(const struct ebt_u_entry *entry,
|
|
+ ebt_print_icmp_type(icmp_codes, ARRAY_SIZE(icmp_codes),
|
|
+ ipinfo->icmp_type, ipinfo->icmp_code);
|
|
+ }
|
|
++ if (ipinfo->bitmask & EBT_IP_IGMP) {
|
|
++ printf("--ip-igmp-type ");
|
|
++ if (ipinfo->invflags & EBT_IP_IGMP)
|
|
++ printf("! ");
|
|
++ ebt_print_icmp_type(igmp_types, ARRAY_SIZE(igmp_types),
|
|
++ ipinfo->igmp_type, NULL);
|
|
++ }
|
|
+ }
|
|
+
|
|
+ static int compare(const struct ebt_entry_match *m1,
|
|
+@@ -414,6 +451,11 @@ static int compare(const struct ebt_entry_match *m1,
|
|
+ ipinfo1->icmp_code[1] != ipinfo2->icmp_code[1])
|
|
+ return 0;
|
|
+ }
|
|
++ if (ipinfo1->bitmask & EBT_IP_IGMP) {
|
|
++ if (ipinfo1->igmp_type[0] != ipinfo2->igmp_type[0] ||
|
|
++ ipinfo1->igmp_type[1] != ipinfo2->igmp_type[1])
|
|
++ return 0;
|
|
++ }
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+diff --git a/useful_functions.c b/useful_functions.c
|
|
+index 8f54bae83fae..8a34f820f230 100644
|
|
+--- a/useful_functions.c
|
|
++++ b/useful_functions.c
|
|
+@@ -486,8 +486,10 @@ int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes,
|
|
+
|
|
+ if (match < n_codes) {
|
|
+ type[0] = type[1] = icmp_codes[match].type;
|
|
+- code[0] = icmp_codes[match].code_min;
|
|
+- code[1] = icmp_codes[match].code_max;
|
|
++ if (code) {
|
|
++ code[0] = icmp_codes[match].code_min;
|
|
++ code[1] = icmp_codes[match].code_max;
|
|
++ }
|
|
+ } else {
|
|
+ char *next = parse_range(icmptype, 0, 255, number);
|
|
+ if (!next) {
|
|
+@@ -499,17 +501,21 @@ int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes,
|
|
+ type[1] = (uint8_t) number[1];
|
|
+ switch (*next) {
|
|
+ case 0:
|
|
+- code[0] = 0;
|
|
+- code[1] = 255;
|
|
++ if (code) {
|
|
++ 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;
|
|
++ if (code) {
|
|
++ 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);
|
|
+@@ -521,6 +527,9 @@ int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes,
|
|
+
|
|
+ static void print_icmp_code(uint8_t *code)
|
|
+ {
|
|
++ if (!code)
|
|
++ return;
|
|
++
|
|
+ if (code[0] == code[1])
|
|
+ printf("/%"PRIu8 " ", code[0]);
|
|
+ else
|
|
+@@ -542,8 +551,8 @@ void ebt_print_icmp_type(const struct ebt_icmp_names *icmp_codes,
|
|
+ if (icmp_codes[i].type != type[0])
|
|
+ continue;
|
|
+
|
|
+- if (icmp_codes[i].code_min == code[0] &&
|
|
+- icmp_codes[i].code_max == code[1]) {
|
|
++ if (!code || (icmp_codes[i].code_min == code[0] &&
|
|
++ icmp_codes[i].code_max == code[1])) {
|
|
+ printf("%s ", icmp_codes[i].name);
|
|
+ return;
|
|
+ }
|
|
+--
|
|
+2.16.2
|
|
+
|
|
diff --git a/target/linux/generic/patches-4.4/614-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch b/target/linux/generic/patches-4.4/614-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..1f3d1a2fea50154238c03707b0d7a96db8d1f5d9
|
|
--- /dev/null
|
|
+++ b/target/linux/generic/patches-4.4/614-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch
|
|
@@ -0,0 +1,139 @@
|
|
+From 4f8fa78149e0921c8efdc1adc5e12686ffe7667f Mon Sep 17 00:00:00 2001
|
|
+Message-Id: <4f8fa78149e0921c8efdc1adc5e12686ffe7667f.1520150717.git.mschiffer@universe-factory.net>
|
|
+In-Reply-To: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+References: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+From: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+Date: Sat, 3 Mar 2018 11:55:21 +0100
|
|
+Subject: [PATCH nf-next 1/2] ebtables: add support for matching ICMP type and
|
|
+ code
|
|
+
|
|
+We already have ICMPv6 type/code matches. This adds support for IPv4 ICMP
|
|
+matches in the same way.
|
|
+
|
|
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+---
|
|
+ include/uapi/linux/netfilter_bridge/ebt_ip.h | 13 +++++++--
|
|
+ net/bridge/netfilter/ebt_ip.c | 43 +++++++++++++++++++++-------
|
|
+ 2 files changed, 43 insertions(+), 13 deletions(-)
|
|
+
|
|
+--- a/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
|
++++ b/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
|
+@@ -23,8 +23,9 @@
|
|
+ #define EBT_IP_PROTO 0x08
|
|
+ #define EBT_IP_SPORT 0x10
|
|
+ #define EBT_IP_DPORT 0x20
|
|
++#define EBT_IP_ICMP 0x40
|
|
+ #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
|
|
+- EBT_IP_SPORT | EBT_IP_DPORT )
|
|
++ EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP)
|
|
+ #define EBT_IP_MATCH "ip"
|
|
+
|
|
+ /* the same values are used for the invflags */
|
|
+@@ -37,8 +38,14 @@ struct ebt_ip_info {
|
|
+ __u8 protocol;
|
|
+ __u8 bitmask;
|
|
+ __u8 invflags;
|
|
+- __u16 sport[2];
|
|
+- __u16 dport[2];
|
|
++ union {
|
|
++ __u16 sport[2];
|
|
++ __u8 icmp_type[2];
|
|
++ };
|
|
++ union {
|
|
++ __u16 dport[2];
|
|
++ __u8 icmp_code[2];
|
|
++ };
|
|
+ };
|
|
+
|
|
+ #endif
|
|
+--- a/net/bridge/netfilter/ebt_ip.c
|
|
++++ b/net/bridge/netfilter/ebt_ip.c
|
|
+@@ -19,9 +19,15 @@
|
|
+ #include <linux/netfilter_bridge/ebtables.h>
|
|
+ #include <linux/netfilter_bridge/ebt_ip.h>
|
|
+
|
|
+-struct tcpudphdr {
|
|
+- __be16 src;
|
|
+- __be16 dst;
|
|
++union pkthdr {
|
|
++ struct {
|
|
++ __be16 src;
|
|
++ __be16 dst;
|
|
++ } tcpudphdr;
|
|
++ struct {
|
|
++ u8 type;
|
|
++ u8 code;
|
|
++ } icmphdr;
|
|
+ };
|
|
+
|
|
+ static bool
|
|
+@@ -30,8 +36,8 @@ ebt_ip_mt(const struct sk_buff *skb, str
|
|
+ const struct ebt_ip_info *info = par->matchinfo;
|
|
+ const struct iphdr *ih;
|
|
+ struct iphdr _iph;
|
|
+- const struct tcpudphdr *pptr;
|
|
+- struct tcpudphdr _ports;
|
|
++ const union pkthdr *pptr;
|
|
++ union pkthdr _pkthdr;
|
|
+
|
|
+ ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
|
|
+ if (ih == NULL)
|
|
+@@ -50,29 +56,38 @@ ebt_ip_mt(const struct sk_buff *skb, str
|
|
+ if (info->bitmask & EBT_IP_PROTO) {
|
|
+ if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO))
|
|
+ return false;
|
|
+- if (!(info->bitmask & EBT_IP_DPORT) &&
|
|
+- !(info->bitmask & EBT_IP_SPORT))
|
|
++ if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT |
|
|
++ EBT_IP_ICMP)))
|
|
+ return true;
|
|
+ if (ntohs(ih->frag_off) & IP_OFFSET)
|
|
+ return false;
|
|
++
|
|
++ /* min icmp headersize is 4, so sizeof(_pkthdr) is ok. */
|
|
+ pptr = skb_header_pointer(skb, ih->ihl*4,
|
|
+- sizeof(_ports), &_ports);
|
|
++ sizeof(_pkthdr), &_pkthdr);
|
|
+ if (pptr == NULL)
|
|
+ return false;
|
|
+ if (info->bitmask & EBT_IP_DPORT) {
|
|
+- u32 dst = ntohs(pptr->dst);
|
|
++ u32 dst = ntohs(pptr->tcpudphdr.dst);
|
|
+ if (FWINV(dst < info->dport[0] ||
|
|
+ dst > info->dport[1],
|
|
+ EBT_IP_DPORT))
|
|
+ return false;
|
|
+ }
|
|
+ if (info->bitmask & EBT_IP_SPORT) {
|
|
+- u32 src = ntohs(pptr->src);
|
|
++ u32 src = ntohs(pptr->tcpudphdr.src);
|
|
+ if (FWINV(src < info->sport[0] ||
|
|
+ src > info->sport[1],
|
|
+ EBT_IP_SPORT))
|
|
+ return false;
|
|
+ }
|
|
++ if ((info->bitmask & EBT_IP_ICMP) &&
|
|
++ FWINV(pptr->icmphdr.type < info->icmp_type[0] ||
|
|
++ pptr->icmphdr.type > info->icmp_type[1] ||
|
|
++ pptr->icmphdr.code < info->icmp_code[0] ||
|
|
++ pptr->icmphdr.code > info->icmp_code[1],
|
|
++ EBT_IP_ICMP))
|
|
++ return false;
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+@@ -101,6 +116,14 @@ static int ebt_ip_mt_check(const struct
|
|
+ return -EINVAL;
|
|
+ if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1])
|
|
+ return -EINVAL;
|
|
++ if (info->bitmask & EBT_IP_ICMP) {
|
|
++ if ((info->invflags & EBT_IP_PROTO) ||
|
|
++ info->protocol != IPPROTO_ICMP)
|
|
++ return -EINVAL;
|
|
++ if (info->icmp_type[0] > info->icmp_type[1] ||
|
|
++ info->icmp_code[0] > info->icmp_code[1])
|
|
++ return -EINVAL;
|
|
++ }
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
diff --git a/target/linux/generic/patches-4.4/614-0002-ebtables-add-support-for-matching-IGMP-type.patch b/target/linux/generic/patches-4.4/614-0002-ebtables-add-support-for-matching-IGMP-type.patch
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..3c8760dbebefddb9bb6a0b9bb724210c573d854c
|
|
--- /dev/null
|
|
+++ b/target/linux/generic/patches-4.4/614-0002-ebtables-add-support-for-matching-IGMP-type.patch
|
|
@@ -0,0 +1,92 @@
|
|
+From 68c6d1b60803e9690f2a6168b80a92ae45c6578b Mon Sep 17 00:00:00 2001
|
|
+Message-Id: <68c6d1b60803e9690f2a6168b80a92ae45c6578b.1520150717.git.mschiffer@universe-factory.net>
|
|
+In-Reply-To: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+References: <cover.1520150717.git.mschiffer@universe-factory.net>
|
|
+From: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+Date: Sat, 3 Mar 2018 12:02:21 +0100
|
|
+Subject: [PATCH nf-next 2/2] ebtables: add support for matching IGMP type
|
|
+
|
|
+We already have ICMPv6 type/code matches (which can be used to distinguish
|
|
+different types of MLD packets). Add support for IPv4 IGMP matches in the
|
|
+same way.
|
|
+
|
|
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
|
|
+---
|
|
+ include/uapi/linux/netfilter_bridge/ebt_ip.h | 4 +++-
|
|
+ net/bridge/netfilter/ebt_ip.c | 19 +++++++++++++++++--
|
|
+ 2 files changed, 20 insertions(+), 3 deletions(-)
|
|
+
|
|
+--- a/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
|
++++ b/include/uapi/linux/netfilter_bridge/ebt_ip.h
|
|
+@@ -24,8 +24,9 @@
|
|
+ #define EBT_IP_SPORT 0x10
|
|
+ #define EBT_IP_DPORT 0x20
|
|
+ #define EBT_IP_ICMP 0x40
|
|
++#define EBT_IP_IGMP 0x80
|
|
+ #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
|
|
+- EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP)
|
|
++ EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP)
|
|
+ #define EBT_IP_MATCH "ip"
|
|
+
|
|
+ /* the same values are used for the invflags */
|
|
+@@ -41,6 +42,7 @@ struct ebt_ip_info {
|
|
+ union {
|
|
+ __u16 sport[2];
|
|
+ __u8 icmp_type[2];
|
|
++ __u8 igmp_type[2];
|
|
+ };
|
|
+ union {
|
|
+ __u16 dport[2];
|
|
+--- a/net/bridge/netfilter/ebt_ip.c
|
|
++++ b/net/bridge/netfilter/ebt_ip.c
|
|
+@@ -28,6 +28,9 @@ union pkthdr {
|
|
+ u8 type;
|
|
+ u8 code;
|
|
+ } icmphdr;
|
|
++ struct {
|
|
++ u8 type;
|
|
++ } igmphdr;
|
|
+ };
|
|
+
|
|
+ static bool
|
|
+@@ -57,12 +60,12 @@ ebt_ip_mt(const struct sk_buff *skb, str
|
|
+ if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO))
|
|
+ return false;
|
|
+ if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT |
|
|
+- EBT_IP_ICMP)))
|
|
++ EBT_IP_ICMP | EBT_IP_IGMP)))
|
|
+ return true;
|
|
+ if (ntohs(ih->frag_off) & IP_OFFSET)
|
|
+ return false;
|
|
+
|
|
+- /* min icmp headersize is 4, so sizeof(_pkthdr) is ok. */
|
|
++ /* min icmp/igmp headersize is 4, so sizeof(_pkthdr) is ok. */
|
|
+ pptr = skb_header_pointer(skb, ih->ihl*4,
|
|
+ sizeof(_pkthdr), &_pkthdr);
|
|
+ if (pptr == NULL)
|
|
+@@ -88,6 +91,11 @@ ebt_ip_mt(const struct sk_buff *skb, str
|
|
+ pptr->icmphdr.code > info->icmp_code[1],
|
|
+ EBT_IP_ICMP))
|
|
+ return false;
|
|
++ if ((info->bitmask & EBT_IP_IGMP) &&
|
|
++ FWINV(pptr->igmphdr.type < info->igmp_type[0] ||
|
|
++ pptr->igmphdr.type > info->igmp_type[1],
|
|
++ EBT_IP_IGMP))
|
|
++ return false;
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+@@ -124,6 +132,13 @@ static int ebt_ip_mt_check(const struct
|
|
+ info->icmp_code[0] > info->icmp_code[1])
|
|
+ return -EINVAL;
|
|
+ }
|
|
++ if (info->bitmask & EBT_IP_IGMP) {
|
|
++ if ((info->invflags & EBT_IP_PROTO) ||
|
|
++ info->protocol != IPPROTO_IGMP)
|
|
++ return -EINVAL;
|
|
++ if (info->igmp_type[0] > info->igmp_type[1])
|
|
++ return -EINVAL;
|
|
++ }
|
|
+ return 0;
|
|
+ }
|
|
+
|