Blame SOURCES/0015-Move-ICMP-type-handling-functions-from-ebt_ip6-to-us.patch

05e71a
From 67de7ef4ab4d3042f8f24f7f5ef20d5711e6820b Mon Sep 17 00:00:00 2001
05e71a
From: Matthias Schiffer <mschiffer@universe-factory.net>
05e71a
Date: Sun, 4 Mar 2018 09:28:56 +0100
05e71a
Subject: [PATCH] Move ICMP type handling functions from ebt_ip6 to
05e71a
 useful_functions.c
05e71a
05e71a
Allow using these functions for ebt_ip as well.
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_ip6.c | 165 +++----------------------------------------
05e71a
 include/ebtables_u.h |  17 ++++-
05e71a
 useful_functions.c   | 151 ++++++++++++++++++++++++++++++++++++++-
05e71a
 3 files changed, 174 insertions(+), 159 deletions(-)
05e71a
05e71a
diff --git a/extensions/ebt_ip6.c b/extensions/ebt_ip6.c
05e71a
index dd48547b0010b..347797b4afe18 100644
05e71a
--- a/extensions/ebt_ip6.c
05e71a
+++ b/extensions/ebt_ip6.c
05e71a
@@ -11,9 +11,6 @@
05e71a
  *
05e71a
  */
05e71a
 
05e71a
-#include <errno.h>
05e71a
-#include <inttypes.h>
05e71a
-#include <limits.h>
05e71a
 #include <stdio.h>
05e71a
 #include <stdlib.h>
05e71a
 #include <string.h>
05e71a
@@ -51,13 +48,7 @@ static const struct option opts[] =
05e71a
 };
05e71a
 
05e71a
 
05e71a
-struct icmpv6_names {
05e71a
-	const char *name;
05e71a
-	uint8_t type;
05e71a
-	uint8_t code_min, code_max;
05e71a
-};
05e71a
-
05e71a
-static const struct icmpv6_names icmpv6_codes[] = {
05e71a
+static const struct ebt_icmp_names icmpv6_codes[] = {
05e71a
 	{ "destination-unreachable", 1, 0, 0xFF },
05e71a
 	{ "no-route", 1, 0, 0 },
05e71a
 	{ "communication-prohibited", 1, 1, 1 },
05e71a
@@ -141,97 +132,6 @@ parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
05e71a
 	free(buffer);
05e71a
 }
05e71a
 
05e71a
-static char*
05e71a
-parse_num(const char *str, long min, long max, long *num)
05e71a
-{
05e71a
-	char *end;
05e71a
-
05e71a
-	errno = 0;
05e71a
-	*num = strtol(str, &end, 10);
05e71a
-	if (errno && (*num == LONG_MIN || *num == LONG_MAX)) {
05e71a
-		ebt_print_error("Invalid number %s: %s", str, strerror(errno));
05e71a
-		return NULL;
05e71a
-	}
05e71a
-	if (min <= max) {
05e71a
-		if (*num > max || *num < min) {
05e71a
-			ebt_print_error("Value %ld out of range (%ld, %ld)", *num, min, max);
05e71a
-			return NULL;
05e71a
-		}
05e71a
-	}
05e71a
-	if (*num == 0 && str == end)
05e71a
-		return NULL;
05e71a
-	return end;
05e71a
-}
05e71a
-
05e71a
-static char *
05e71a
-parse_range(const char *str, long min, long max, long num[])
05e71a
-{
05e71a
-	char *next;
05e71a
-
05e71a
-	next = parse_num(str, min, max, num);
05e71a
-	if (next == NULL)
05e71a
-		return NULL;
05e71a
-	if (next && *next == ':')
05e71a
-		next = parse_num(next+1, min, max, &num[1]);
05e71a
-	else
05e71a
-		num[1] = num[0];
05e71a
-	return next;
05e71a
-}
05e71a
-
05e71a
-static int
05e71a
-parse_icmpv6(const char *icmpv6type, uint8_t type[], uint8_t code[])
05e71a
-{
05e71a
-	static const unsigned int limit = ARRAY_SIZE(icmpv6_codes);
05e71a
-	unsigned int match = limit;
05e71a
-	unsigned int i;
05e71a
-	long number[2];
05e71a
-
05e71a
-	for (i = 0; i < limit; i++) {
05e71a
-		if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type)))
05e71a
-			continue;
05e71a
-		if (match != limit)
05e71a
-			ebt_print_error("Ambiguous ICMPv6 type `%s':"
05e71a
-					" `%s' or `%s'?",
05e71a
-					icmpv6type, icmpv6_codes[match].name,
05e71a
-					icmpv6_codes[i].name);
05e71a
-		match = i;
05e71a
-	}
05e71a
-
05e71a
-	if (match < limit) {
05e71a
-		type[0] = type[1] = icmpv6_codes[match].type;
05e71a
-		code[0] = icmpv6_codes[match].code_min;
05e71a
-		code[1] = icmpv6_codes[match].code_max;
05e71a
-	} else {
05e71a
-		char *next = parse_range(icmpv6type, 0, 255, number);
05e71a
-		if (!next) {
05e71a
-			ebt_print_error("Unknown ICMPv6 type `%s'",
05e71a
-							icmpv6type);
05e71a
-			return -1;
05e71a
-		}
05e71a
-		type[0] = (uint8_t) number[0];
05e71a
-		type[1] = (uint8_t) number[1];
05e71a
-		switch (*next) {
05e71a
-		case 0:
05e71a
-			code[0] = 0;
05e71a
-			code[1] = 255;
05e71a
-			return 0;
05e71a
-		case '/':
05e71a
-			next = parse_range(next+1, 0, 255, number);
05e71a
-			code[0] = (uint8_t) number[0];
05e71a
-			code[1] = (uint8_t) number[1];
05e71a
-			if (next == NULL)
05e71a
-				return -1;
05e71a
-			if (next && *next == 0)
05e71a
-				return 0;
05e71a
-		/* fallthrough */
05e71a
-		default:
05e71a
-			ebt_print_error("unknown character %c", *next);
05e71a
-			return -1;
05e71a
-		}
05e71a
-	}
05e71a
-	return 0;
05e71a
-}
05e71a
-
05e71a
 static void print_port_range(uint16_t *ports)
05e71a
 {
05e71a
 	if (ports[0] == ports[1])
05e71a
@@ -240,58 +140,6 @@ static void print_port_range(uint16_t *ports)
05e71a
 		printf("%d:%d ", ports[0], ports[1]);
05e71a
 }
05e71a
 
05e71a
-static void print_icmp_code(uint8_t *code)
05e71a
-{
05e71a
-	if (code[0] == code[1])
05e71a
-		printf("/%"PRIu8 " ", code[0]);
05e71a
-	else
05e71a
-		printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]);
05e71a
-}
05e71a
-
05e71a
-static void print_icmp_type(uint8_t *type, uint8_t *code)
05e71a
-{
05e71a
-	unsigned int i;
05e71a
-
05e71a
-	if (type[0] != type[1]) {
05e71a
-		printf("%"PRIu8 ":%" PRIu8, type[0], type[1]);
05e71a
-		print_icmp_code(code);
05e71a
-		return;
05e71a
-	}
05e71a
-
05e71a
-	for (i = 0; i < ARRAY_SIZE(icmpv6_codes); i++) {
05e71a
-		if (icmpv6_codes[i].type != type[0])
05e71a
-			continue;
05e71a
-
05e71a
-		if (icmpv6_codes[i].code_min == code[0] &&
05e71a
-		    icmpv6_codes[i].code_max == code[1]) {
05e71a
-			printf("%s ", icmpv6_codes[i].name);
05e71a
-			return;
05e71a
-		}
05e71a
-	}
05e71a
-	printf("%"PRIu8, type[0]);
05e71a
-	print_icmp_code(code);
05e71a
-}
05e71a
-
05e71a
-static void print_icmpv6types(void)
05e71a
-{
05e71a
-	unsigned int i;
05e71a
-        printf("Valid ICMPv6 Types:");
05e71a
-
05e71a
-	for (i=0; i < ARRAY_SIZE(icmpv6_codes); i++) {
05e71a
-		if (i && icmpv6_codes[i].type == icmpv6_codes[i-1].type) {
05e71a
-			if (icmpv6_codes[i].code_min == icmpv6_codes[i-1].code_min
05e71a
-			    && (icmpv6_codes[i].code_max
05e71a
-			        == icmpv6_codes[i-1].code_max))
05e71a
-				printf(" (%s)", icmpv6_codes[i].name);
05e71a
-			else
05e71a
-				printf("\n   %s", icmpv6_codes[i].name);
05e71a
-		}
05e71a
-		else
05e71a
-			printf("\n%s", icmpv6_codes[i].name);
05e71a
-	}
05e71a
-	printf("\n");
05e71a
-}
05e71a
-
05e71a
 static void print_help()
05e71a
 {
05e71a
 	printf(
05e71a
@@ -303,7 +151,9 @@ static void print_help()
05e71a
 "--ip6-sport  [!] port[:port]   : tcp/udp source port or port range\n"
05e71a
 "--ip6-dport  [!] port[:port]   : tcp/udp destination port or port range\n"
05e71a
 "--ip6-icmp-type [!] type[[:type]/code[:code]] : ipv6-icmp type/code or type/code range\n");
05e71a
-print_icmpv6types();
05e71a
+
05e71a
+	printf("\nValid ICMPv6 Types:\n");
05e71a
+	ebt_print_icmp_types(icmpv6_codes, ARRAY_SIZE(icmpv6_codes));
05e71a
 }
05e71a
 
05e71a
 static void init(struct ebt_entry_match *match)
05e71a
@@ -374,7 +224,9 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
05e71a
 		ipinfo->bitmask |= EBT_IP6_ICMP6;
05e71a
 		if (ebt_check_inverse2(optarg))
05e71a
 			ipinfo->invflags |= EBT_IP6_ICMP6;
05e71a
-		if (parse_icmpv6(optarg, ipinfo->icmpv6_type, ipinfo->icmpv6_code))
05e71a
+		if (ebt_parse_icmp(icmpv6_codes, ARRAY_SIZE(icmpv6_codes),
05e71a
+				   optarg, ipinfo->icmpv6_type,
05e71a
+				   ipinfo->icmpv6_code))
05e71a
 			return 0;
05e71a
 		break;
05e71a
 
05e71a
@@ -493,7 +345,8 @@ static void print(const struct ebt_u_entry *entry,
05e71a
 		printf("--ip6-icmp-type ");
05e71a
 		if (ipinfo->invflags & EBT_IP6_ICMP6)
05e71a
 			printf("! ");
05e71a
-		print_icmp_type(ipinfo->icmpv6_type, ipinfo->icmpv6_code);
05e71a
+		ebt_print_icmp_type(icmpv6_codes, ARRAY_SIZE(icmpv6_codes),
05e71a
+				    ipinfo->icmpv6_type, ipinfo->icmpv6_code);
05e71a
 	}
05e71a
 }
05e71a
 
05e71a
diff --git a/include/ebtables_u.h b/include/ebtables_u.h
05e71a
index 35a5bcc54c865..17afa9487f5ad 100644
05e71a
--- a/include/ebtables_u.h
05e71a
+++ b/include/ebtables_u.h
05e71a
@@ -222,6 +222,15 @@ struct ebt_u_target
05e71a
 	struct ebt_u_target *next;
05e71a
 };
05e71a
 
05e71a
+
05e71a
+struct ebt_icmp_names {
05e71a
+	const char *name;
05e71a
+	uint8_t type;
05e71a
+	uint8_t code_min, code_max;
05e71a
+};
05e71a
+
05e71a
+
05e71a
+
05e71a
 /* libebtc.c */
05e71a
 
05e71a
 extern struct ebt_u_table *ebt_tables;
05e71a
@@ -300,11 +309,17 @@ void ebt_print_mac_and_mask(const unsigned char *mac, const unsigned char *mask)
05e71a
 int ebt_get_mac_and_mask(const char *from, unsigned char *to, unsigned char *mask);
05e71a
 void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk);
05e71a
 char *ebt_mask_to_dotted(uint32_t mask);
05e71a
-void ebt_parse_ip6_address(char *address, struct in6_addr *addr, 
05e71a
+void ebt_parse_ip6_address(char *address, struct in6_addr *addr,
05e71a
 						   struct in6_addr *msk);
05e71a
 char *ebt_ip6_to_numeric(const struct in6_addr *addrp);
05e71a
 char *ebt_ip6_mask_to_string(const struct in6_addr *msk);
05e71a
 
05e71a
+int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes,
05e71a
+		   const char *icmptype, uint8_t type[], uint8_t code[]);
05e71a
+void ebt_print_icmp_type(const struct ebt_icmp_names *icmp_codes,
05e71a
+			 size_t n_codes, uint8_t *type, uint8_t *code);
05e71a
+void ebt_print_icmp_types(const struct ebt_icmp_names *icmp_codes,
05e71a
+			  size_t n_codes);
05e71a
 
05e71a
 int do_command(int argc, char *argv[], int exec_style,
05e71a
                struct ebt_u_replace *replace_);
05e71a
diff --git a/useful_functions.c b/useful_functions.c
05e71a
index d14cbe9dbdba1..8f54bae83fae8 100644
05e71a
--- a/useful_functions.c
05e71a
+++ b/useful_functions.c
05e71a
@@ -24,6 +24,9 @@
05e71a
  */
05e71a
 #include "include/ebtables_u.h"
05e71a
 #include "include/ethernetdb.h"
05e71a
+#include <errno.h>
05e71a
+#include <inttypes.h>
05e71a
+#include <limits.h>
05e71a
 #include <stdio.h>
05e71a
 #include <netinet/ether.h>
05e71a
 #include <string.h>
05e71a
@@ -34,6 +37,7 @@
05e71a
 #include <sys/socket.h>
05e71a
 #include <arpa/inet.h>
05e71a
 
05e71a
+
05e71a
 const unsigned char mac_type_unicast[ETH_ALEN] =   {0,0,0,0,0,0};
05e71a
 const unsigned char msk_type_unicast[ETH_ALEN] =   {1,0,0,0,0,0};
05e71a
 const unsigned char mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
05e71a
@@ -188,7 +192,7 @@ static int undot_ip(char *ip, unsigned char *ip2)
05e71a
 			return -1;
05e71a
 		*q = '\0';
05e71a
 		onebyte = strtol(p, &end, 10);
05e71a
-		if (*end != '\0' || onebyte > 255 || onebyte < 0)   
05e71a
+		if (*end != '\0' || onebyte > 255 || onebyte < 0)
05e71a
 			return -1;
05e71a
 		ip2[i] = (unsigned char)onebyte;
05e71a
 		p = q + 1;
05e71a
@@ -275,7 +279,7 @@ char *ebt_mask_to_dotted(uint32_t mask)
05e71a
 		*buf = '\0';
05e71a
 	else
05e71a
 		/* Mask was not a decent combination of 1's and 0's */
05e71a
-		sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0], 
05e71a
+		sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0],
05e71a
 		   ((unsigned char *)&mask)[1], ((unsigned char *)&mask)[2],
05e71a
 		   ((unsigned char *)&mask)[3]);
05e71a
 
05e71a
@@ -424,3 +428,146 @@ char *ebt_ip6_mask_to_string(const struct in6_addr *msk)
05e71a
 		sprintf(buf, "/%s", ebt_ip6_to_numeric(msk));
05e71a
 	return buf;
05e71a
 }
05e71a
+
05e71a
+static char*
05e71a
+parse_num(const char *str, long min, long max, long *num)
05e71a
+{
05e71a
+	char *end;
05e71a
+
05e71a
+	errno = 0;
05e71a
+	*num = strtol(str, &end, 10);
05e71a
+	if (errno && (*num == LONG_MIN || *num == LONG_MAX)) {
05e71a
+		ebt_print_error("Invalid number %s: %s", str, strerror(errno));
05e71a
+		return NULL;
05e71a
+	}
05e71a
+	if (min <= max) {
05e71a
+		if (*num > max || *num < min) {
05e71a
+			ebt_print_error("Value %ld out of range (%ld, %ld)", *num, min, max);
05e71a
+			return NULL;
05e71a
+		}
05e71a
+	}
05e71a
+	if (*num == 0 && str == end)
05e71a
+		return NULL;
05e71a
+	return end;
05e71a
+}
05e71a
+
05e71a
+static char *
05e71a
+parse_range(const char *str, long min, long max, long num[])
05e71a
+{
05e71a
+	char *next;
05e71a
+
05e71a
+	next = parse_num(str, min, max, num);
05e71a
+	if (next == NULL)
05e71a
+		return NULL;
05e71a
+	if (next && *next == ':')
05e71a
+		next = parse_num(next+1, min, max, &num[1]);
05e71a
+	else
05e71a
+		num[1] = num[0];
05e71a
+	return next;
05e71a
+}
05e71a
+
05e71a
+int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes,
05e71a
+		   const char *icmptype, uint8_t type[], uint8_t code[])
05e71a
+{
05e71a
+	unsigned int match = n_codes;
05e71a
+	unsigned int i;
05e71a
+	long number[2];
05e71a
+
05e71a
+	for (i = 0; i < n_codes; i++) {
05e71a
+		if (strncasecmp(icmp_codes[i].name, icmptype, strlen(icmptype)))
05e71a
+			continue;
05e71a
+		if (match != n_codes)
05e71a
+			ebt_print_error("Ambiguous ICMP type `%s':"
05e71a
+					" `%s' or `%s'?",
05e71a
+					icmptype, icmp_codes[match].name,
05e71a
+					icmp_codes[i].name);
05e71a
+		match = i;
05e71a
+	}
05e71a
+
05e71a
+	if (match < n_codes) {
05e71a
+		type[0] = type[1] = icmp_codes[match].type;
05e71a
+		code[0] = icmp_codes[match].code_min;
05e71a
+		code[1] = icmp_codes[match].code_max;
05e71a
+	} else {
05e71a
+		char *next = parse_range(icmptype, 0, 255, number);
05e71a
+		if (!next) {
05e71a
+			ebt_print_error("Unknown ICMP type `%s'",
05e71a
+							icmptype);
05e71a
+			return -1;
05e71a
+		}
05e71a
+		type[0] = (uint8_t) number[0];
05e71a
+		type[1] = (uint8_t) number[1];
05e71a
+		switch (*next) {
05e71a
+		case 0:
05e71a
+			code[0] = 0;
05e71a
+			code[1] = 255;
05e71a
+			return 0;
05e71a
+		case '/':
05e71a
+			next = parse_range(next+1, 0, 255, number);
05e71a
+			code[0] = (uint8_t) number[0];
05e71a
+			code[1] = (uint8_t) number[1];
05e71a
+			if (next == NULL)
05e71a
+				return -1;
05e71a
+			if (next && *next == 0)
05e71a
+				return 0;
05e71a
+		/* fallthrough */
05e71a
+		default:
05e71a
+			ebt_print_error("unknown character %c", *next);
05e71a
+			return -1;
05e71a
+		}
05e71a
+	}
05e71a
+	return 0;
05e71a
+}
05e71a
+
05e71a
+static void print_icmp_code(uint8_t *code)
05e71a
+{
05e71a
+	if (code[0] == code[1])
05e71a
+		printf("/%"PRIu8 " ", code[0]);
05e71a
+	else
05e71a
+		printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]);
05e71a
+}
05e71a
+
05e71a
+void ebt_print_icmp_type(const struct ebt_icmp_names *icmp_codes,
05e71a
+			 size_t n_codes, uint8_t *type, uint8_t *code)
05e71a
+{
05e71a
+	unsigned int i;
05e71a
+
05e71a
+	if (type[0] != type[1]) {
05e71a
+		printf("%"PRIu8 ":%" PRIu8, type[0], type[1]);
05e71a
+		print_icmp_code(code);
05e71a
+		return;
05e71a
+	}
05e71a
+
05e71a
+	for (i = 0; i < n_codes; i++) {
05e71a
+		if (icmp_codes[i].type != type[0])
05e71a
+			continue;
05e71a
+
05e71a
+		if (icmp_codes[i].code_min == code[0] &&
05e71a
+		    icmp_codes[i].code_max == code[1]) {
05e71a
+			printf("%s ", icmp_codes[i].name);
05e71a
+			return;
05e71a
+		}
05e71a
+	}
05e71a
+	printf("%"PRIu8, type[0]);
05e71a
+	print_icmp_code(code);
05e71a
+}
05e71a
+
05e71a
+void ebt_print_icmp_types(const struct ebt_icmp_names *icmp_codes,
05e71a
+			  size_t n_codes)
05e71a
+{
05e71a
+	unsigned int i;
05e71a
+
05e71a
+	for (i = 0; i < n_codes; i++) {
05e71a
+		if (i && icmp_codes[i].type == icmp_codes[i-1].type) {
05e71a
+			if (icmp_codes[i].code_min == icmp_codes[i-1].code_min
05e71a
+			    && (icmp_codes[i].code_max
05e71a
+			        == icmp_codes[i-1].code_max))
05e71a
+				printf(" (%s)", icmp_codes[i].name);
05e71a
+			else
05e71a
+				printf("\n   %s", icmp_codes[i].name);
05e71a
+		}
05e71a
+		else
05e71a
+			printf("\n%s", icmp_codes[i].name);
05e71a
+	}
05e71a
+	printf("\n");
05e71a
+}
05e71a
-- 
05e71a
2.21.0
05e71a