Blame SOURCES/0016-ebt_ip-add-support-for-matching-ICMP-type-and-code.patch

05e71a
From fca4a7f4d3242ff4ad58081e69bc70ba1f6c46a5 Mon Sep 17 00:00:00 2001
05e71a
From: Matthias Schiffer <mschiffer@universe-factory.net>
05e71a
Date: Sun, 4 Mar 2018 09:28:57 +0100
05e71a
Subject: [PATCH] ebt_ip: add support for matching ICMP type and code
05e71a
05e71a
We already have ICMPv6 type/code matches. This adds support for IPv4 ICMP
05e71a
matches in the same way.
05e71a
05e71a
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
05e71a
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
05e71a
Signed-off-by: Phil Sutter <psutter@redhat.com>
05e71a
---
05e71a
 extensions/ebt_ip.c | 96 ++++++++++++++++++++++++++++++++++++++++++++-
05e71a
 1 file changed, 94 insertions(+), 2 deletions(-)
05e71a
05e71a
diff --git a/extensions/ebt_ip.c b/extensions/ebt_ip.c
05e71a
index 59559feffa50b..42660d4564fbf 100644
05e71a
--- a/extensions/ebt_ip.c
05e71a
+++ b/extensions/ebt_ip.c
05e71a
@@ -24,6 +24,7 @@
05e71a
 #define IP_PROTO  '4'
05e71a
 #define IP_SPORT  '5'
05e71a
 #define IP_DPORT  '6'
05e71a
+#define IP_ICMP   '7'
05e71a
 
05e71a
 static const struct option opts[] =
05e71a
 {
05e71a
@@ -38,9 +39,64 @@ static const struct option opts[] =
05e71a
 	{ "ip-sport"            , required_argument, 0, IP_SPORT  },
05e71a
 	{ "ip-destination-port" , required_argument, 0, IP_DPORT  },
05e71a
 	{ "ip-dport"            , required_argument, 0, IP_DPORT  },
05e71a
+	{ "ip-icmp-type"        , required_argument, 0, IP_ICMP   },
05e71a
 	{ 0 }
05e71a
 };
05e71a
 
05e71a
+static const struct ebt_icmp_names icmp_codes[] = {
05e71a
+	{ "echo-reply", 0, 0, 0xFF },
05e71a
+	/* Alias */ { "pong", 0, 0, 0xFF },
05e71a
+
05e71a
+	{ "destination-unreachable", 3, 0, 0xFF },
05e71a
+	{   "network-unreachable", 3, 0, 0 },
05e71a
+	{   "host-unreachable", 3, 1, 1 },
05e71a
+	{   "protocol-unreachable", 3, 2, 2 },
05e71a
+	{   "port-unreachable", 3, 3, 3 },
05e71a
+	{   "fragmentation-needed", 3, 4, 4 },
05e71a
+	{   "source-route-failed", 3, 5, 5 },
05e71a
+	{   "network-unknown", 3, 6, 6 },
05e71a
+	{   "host-unknown", 3, 7, 7 },
05e71a
+	{   "network-prohibited", 3, 9, 9 },
05e71a
+	{   "host-prohibited", 3, 10, 10 },
05e71a
+	{   "TOS-network-unreachable", 3, 11, 11 },
05e71a
+	{   "TOS-host-unreachable", 3, 12, 12 },
05e71a
+	{   "communication-prohibited", 3, 13, 13 },
05e71a
+	{   "host-precedence-violation", 3, 14, 14 },
05e71a
+	{   "precedence-cutoff", 3, 15, 15 },
05e71a
+
05e71a
+	{ "source-quench", 4, 0, 0xFF },
05e71a
+
05e71a
+	{ "redirect", 5, 0, 0xFF },
05e71a
+	{   "network-redirect", 5, 0, 0 },
05e71a
+	{   "host-redirect", 5, 1, 1 },
05e71a
+	{   "TOS-network-redirect", 5, 2, 2 },
05e71a
+	{   "TOS-host-redirect", 5, 3, 3 },
05e71a
+
05e71a
+	{ "echo-request", 8, 0, 0xFF },
05e71a
+	/* Alias */ { "ping", 8, 0, 0xFF },
05e71a
+
05e71a
+	{ "router-advertisement", 9, 0, 0xFF },
05e71a
+
05e71a
+	{ "router-solicitation", 10, 0, 0xFF },
05e71a
+
05e71a
+	{ "time-exceeded", 11, 0, 0xFF },
05e71a
+	/* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
05e71a
+	{   "ttl-zero-during-transit", 11, 0, 0 },
05e71a
+	{   "ttl-zero-during-reassembly", 11, 1, 1 },
05e71a
+
05e71a
+	{ "parameter-problem", 12, 0, 0xFF },
05e71a
+	{   "ip-header-bad", 12, 0, 0 },
05e71a
+	{   "required-option-missing", 12, 1, 1 },
05e71a
+
05e71a
+	{ "timestamp-request", 13, 0, 0xFF },
05e71a
+
05e71a
+	{ "timestamp-reply", 14, 0, 0xFF },
05e71a
+
05e71a
+	{ "address-mask-request", 17, 0, 0xFF },
05e71a
+
05e71a
+	{ "address-mask-reply", 18, 0, 0xFF }
05e71a
+};
05e71a
+
05e71a
 /* put the mask into 4 bytes */
05e71a
 /* transform a protocol and service name into a port number */
05e71a
 static uint16_t parse_port(const char *protocol, const char *name)
05e71a
@@ -105,7 +161,11 @@ static void print_help()
05e71a
 "--ip-tos    [!] tos           : ip tos specification\n"
05e71a
 "--ip-proto  [!] protocol      : ip protocol specification\n"
05e71a
 "--ip-sport  [!] port[:port]   : tcp/udp source port or port range\n"
05e71a
-"--ip-dport  [!] port[:port]   : tcp/udp destination port or port range\n");
05e71a
+"--ip-dport  [!] port[:port]   : tcp/udp destination port or port range\n"
05e71a
+"--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n");
05e71a
+
05e71a
+	printf("\nValid ICMP Types:\n");
05e71a
+	ebt_print_icmp_types(icmp_codes, ARRAY_SIZE(icmp_codes));
05e71a
 }
05e71a
 
05e71a
 static void init(struct ebt_entry_match *match)
05e71a
@@ -122,6 +182,7 @@ static void init(struct ebt_entry_match *match)
05e71a
 #define OPT_PROTO  0x08
05e71a
 #define OPT_SPORT  0x10
05e71a
 #define OPT_DPORT  0x20
05e71a
+#define OPT_ICMP   0x40
05e71a
 static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
05e71a
    unsigned int *flags, struct ebt_entry_match **match)
05e71a
 {
05e71a
@@ -170,6 +231,16 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
05e71a
 			parse_port_range(NULL, optarg, ipinfo->dport);
05e71a
 		break;
05e71a
 
05e71a
+	case IP_ICMP:
05e71a
+		ebt_check_option2(flags, OPT_ICMP);
05e71a
+		ipinfo->bitmask |= EBT_IP_ICMP;
05e71a
+		if (ebt_check_inverse2(optarg))
05e71a
+			ipinfo->invflags |= EBT_IP_ICMP;
05e71a
+		if (ebt_parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes), optarg,
05e71a
+				   ipinfo->icmp_type, ipinfo->icmp_code))
05e71a
+			return 0;
05e71a
+		break;
05e71a
+
05e71a
 	case IP_myTOS:
05e71a
 		ebt_check_option2(flags, OPT_TOS);
05e71a
 		if (ebt_check_inverse2(optarg))
05e71a
@@ -219,10 +290,17 @@ static void final_check(const struct ebt_u_entry *entry,
05e71a
 		(ipinfo->protocol!=IPPROTO_TCP &&
05e71a
 		 ipinfo->protocol!=IPPROTO_UDP &&
05e71a
 		 ipinfo->protocol!=IPPROTO_SCTP &&
05e71a
-		 ipinfo->protocol!=IPPROTO_DCCP)))
05e71a
+		 ipinfo->protocol!=IPPROTO_DCCP))) {
05e71a
 		ebt_print_error("For port filtering the IP protocol must be "
05e71a
 				"either 6 (tcp), 17 (udp), 33 (dccp) or "
05e71a
 				"132 (sctp)");
05e71a
+	} else if ((ipinfo->bitmask & EBT_IP_ICMP) &&
05e71a
+	         (!(ipinfo->bitmask & EBT_IP_PROTO) ||
05e71a
+	            ipinfo->invflags & EBT_IP_PROTO ||
05e71a
+	            ipinfo->protocol != IPPROTO_ICMP)) {
05e71a
+		ebt_print_error("For ICMP filtering the IP protocol must be "
05e71a
+				"1 (icmp)");
05e71a
+	}
05e71a
 }
05e71a
 
05e71a
 static void print(const struct ebt_u_entry *entry,
05e71a
@@ -280,6 +358,13 @@ static void print(const struct ebt_u_entry *entry,
05e71a
 			printf("! ");
05e71a
 		print_port_range(ipinfo->dport);
05e71a
 	}
05e71a
+	if (ipinfo->bitmask & EBT_IP_ICMP) {
05e71a
+		printf("--ip-icmp-type ");
05e71a
+		if (ipinfo->invflags & EBT_IP_ICMP)
05e71a
+			printf("! ");
05e71a
+		ebt_print_icmp_type(icmp_codes, ARRAY_SIZE(icmp_codes),
05e71a
+				    ipinfo->icmp_type, ipinfo->icmp_code);
05e71a
+	}
05e71a
 }
05e71a
 
05e71a
 static int compare(const struct ebt_entry_match *m1,
05e71a
@@ -322,6 +407,13 @@ static int compare(const struct ebt_entry_match *m1,
05e71a
 		   ipinfo1->dport[1] != ipinfo2->dport[1])
05e71a
 			return 0;
05e71a
 	}
05e71a
+	if (ipinfo1->bitmask & EBT_IP_ICMP) {
05e71a
+		if (ipinfo1->icmp_type[0] != ipinfo2->icmp_type[0] ||
05e71a
+		    ipinfo1->icmp_type[1] != ipinfo2->icmp_type[1] ||
05e71a
+		    ipinfo1->icmp_code[0] != ipinfo2->icmp_code[0] ||
05e71a
+		    ipinfo1->icmp_code[1] != ipinfo2->icmp_code[1])
05e71a
+			return 0;
05e71a
+	}
05e71a
 	return 1;
05e71a
 }
05e71a
 
05e71a
-- 
05e71a
2.21.0
05e71a