From 67de7ef4ab4d3042f8f24f7f5ef20d5711e6820b Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 4 Mar 2018 09:28:56 +0100 Subject: [PATCH] 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 Signed-off-by: Pablo Neira Ayuso Signed-off-by: Phil Sutter --- 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 dd48547b0010b..347797b4afe18 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 35a5bcc54c865..17afa9487f5ad 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 d14cbe9dbdba1..8f54bae83fae8 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"); +} -- 2.21.0