From patchwork Sun Mar 4 08:28:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthias Schiffer X-Patchwork-Id: 881145 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=universe-factory.net Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zvGZ72kBrz9s1l for ; Sun, 4 Mar 2018 19:35:11 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752542AbeCDIfH (ORCPT ); Sun, 4 Mar 2018 03:35:07 -0500 Received: from orthanc.universe-factory.net ([104.238.176.138]:33554 "EHLO orthanc.universe-factory.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752493AbeCDIfE (ORCPT ); Sun, 4 Mar 2018 03:35:04 -0500 Received: from localhost.localdomain (unknown [IPv6:2001:19f0:6c01:100::2]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by orthanc.universe-factory.net (Postfix) with ESMTPSA id 81A6A1F4ED; Sun, 4 Mar 2018 09:29:19 +0100 (CET) From: Matthias Schiffer To: pablo@netfilter.org Cc: kadlec@blackhole.kfki.hu, fw@strlen.de, netfilter-devel@vger.kernel.org Subject: [PATCH ebtables 2/4] Move ICMP type handling functions from ebt_ip6 to useful_functions.c Date: Sun, 4 Mar 2018 09:28:56 +0100 Message-Id: X-Mailer: git-send-email 2.16.2 In-Reply-To: References: In-Reply-To: References: Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Allow using these functions for ebt_ip as well. Signed-off-by: Matthias Schiffer --- 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 -#include -#include #include #include #include @@ -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 +#include +#include #include #include #include @@ -34,6 +37,7 @@ #include #include + 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"); +}