diff --git a/ircd/hostmask.c b/ircd/hostmask.c index 751adcee..48b2b1b3 100644 --- a/ircd/hostmask.c +++ b/ircd/hostmask.c @@ -67,10 +67,12 @@ _parse_netmask(const char *text, struct rb_sockaddr_storage *naddr, int *nb, boo if (endp == ptr || n < 0) return HM_HOST; if (n > 128 || *endp != '\0') + { if (strict) return HM_ERROR; else n = 128; + } *b = n; } else *b = 128; @@ -89,10 +91,12 @@ _parse_netmask(const char *text, struct rb_sockaddr_storage *naddr, int *nb, boo if (endp == ptr || n < 0) return HM_HOST; if (n > 32 || *endp != '\0') + { if (strict) return HM_ERROR; else n = 32; + } *b = n; } else *b = 32; diff --git a/tests/Makefile.am b/tests/Makefile.am index 2b06e5c6..f4754f63 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,7 @@ check_PROGRAMS = runtests \ msgbuf_parse1 \ msgbuf_unparse1 \ + hostmask1 \ rb_dictionary1 \ rb_snprintf_append1 \ rb_snprintf_try_append1 \ @@ -24,6 +25,7 @@ tap_libtap_a_SOURCES = tap/basic.c tap/basic.h \ msgbuf_parse1_SOURCES = msgbuf_parse1.c msgbuf_unparse1_SOURCES = msgbuf_unparse1.c +hostmask1_SOURCES = hostmask1.c rb_dictionary1_SOURCES = rb_dictionary1.c rb_snprintf_append1_SOURCES = rb_snprintf_append1.c rb_snprintf_try_append1_SOURCES = rb_snprintf_try_append1.c diff --git a/tests/TESTS b/tests/TESTS index 61e51d74..31cc388c 100644 --- a/tests/TESTS +++ b/tests/TESTS @@ -1,5 +1,6 @@ msgbuf_parse1 msgbuf_unparse1 +hostmask1 rb_dictionary1 rb_snprintf_append1 rb_snprintf_try_append1 diff --git a/tests/hostmask1.c b/tests/hostmask1.c new file mode 100644 index 00000000..295c8652 --- /dev/null +++ b/tests/hostmask1.c @@ -0,0 +1,218 @@ +/* + * hostmask1.c: Test parse_netmask + * Copyright 2020 Ed Kellett + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ +#include +#include +#include +#include +#include "tap/basic.h" + +#include "stdinc.h" +#include "ircd_defs.h" +#include "client.h" +#include "hostmask.h" + +#define MSG "%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__ + +struct Client me; + +static void plain_hostmask(void) +{ + int ty; + + ty = parse_netmask("foo.example", NULL, NULL); + is_int(HM_HOST, ty, MSG); + + ty = parse_netmask("*.example", NULL, NULL); + is_int(HM_HOST, ty, MSG); + + ty = parse_netmask("foo.examp?", NULL, NULL); + is_int(HM_HOST, ty, MSG); +} + +static void valid_ipv4(void) +{ + int ty, nb; + struct rb_sockaddr_storage addr; + char ip[1024]; + + ty = parse_netmask("10.20.30.40", &addr, &nb); + is_int(HM_IPV4, ty, MSG); + if (ty == HM_IPV4) + { + is_string("10.20.30.40", rb_inet_ntop_sock((struct sockaddr *)&addr, ip, sizeof ip), MSG); + is_int(32, nb, MSG); + } +} + +static void invalid_ipv4(void) +{ + int ty; + + ty = parse_netmask(".1", NULL, NULL); + is_int(HM_HOST, ty, MSG); + + ty = parse_netmask("10.20.30", NULL, NULL); + is_int(HM_HOST, ty, MSG); + + ty = parse_netmask("10.20.30.40.50", NULL, NULL); + is_int(HM_HOST, ty, MSG); +} + +static void valid_ipv4_cidr(void) +{ + int ty, nb; + struct rb_sockaddr_storage addr; + char ip[1024]; + + ty = parse_netmask("10.20.30.40/7", &addr, &nb); + is_int(HM_IPV4, ty, MSG); + if (ty == HM_IPV4) + { + is_string("10.20.30.40", rb_inet_ntop_sock((struct sockaddr *)&addr, ip, sizeof ip), MSG); + is_int(7, nb, MSG); + } +} + +static void invalid_ipv4_cidr(void) +{ + int ty, nb; + + ty = parse_netmask("10.20.30.40/aaa", NULL, NULL); + is_int(HM_HOST, ty, MSG); + + ty = parse_netmask("10.20.30.40/-1", NULL, NULL); + is_int(HM_HOST, ty, MSG); + + ty = parse_netmask("10.20.30.40/1000", NULL, &nb); + is_int(HM_IPV4, ty, MSG); + is_int(32, nb, MSG); + + ty = parse_netmask("10.20.30.40/1a", NULL, &nb); + is_int(HM_IPV4, ty, MSG); + is_int(32, nb, MSG); + + ty = parse_netmask_strict("10.20.30.40/1000", NULL, NULL); + is_int(HM_ERROR, ty, MSG); + + ty = parse_netmask_strict("10.20.30.40/1a", NULL, NULL); + is_int(HM_ERROR, ty, MSG); +} + +static void valid_ipv6(void) +{ + int ty, nb; + struct rb_sockaddr_storage addr; + char ip[1024]; + + ty = parse_netmask("1:2:3:4:5:6:7:8", &addr, &nb); + is_int(HM_IPV6, ty, MSG); + if (ty == HM_IPV6) + { + is_string("1:2:3:4:5:6:7:8", rb_inet_ntop_sock((struct sockaddr *)&addr, ip, sizeof ip), MSG); + is_int(128, nb, MSG); + } + + ty = parse_netmask("1:2::7:8", &addr, &nb); + is_int(HM_IPV6, ty, MSG); + if (ty == HM_IPV6) + { + is_string("1:2::7:8", rb_inet_ntop_sock((struct sockaddr *)&addr, ip, sizeof ip), MSG); + is_int(128, nb, MSG); + } +} + +static void invalid_ipv6(void) +{ + int ty; + + ty = parse_netmask(":1", NULL, NULL); + is_int(HM_HOST, ty, MSG); + + ty = parse_netmask("1:2:3:4:5", NULL, NULL); + is_int(HM_HOST, ty, MSG); + + ty = parse_netmask("1:2:3:4:5:6:7:8:9", NULL, NULL); + is_int(HM_HOST, ty, MSG); +} + +static void valid_ipv6_cidr(void) +{ + int ty, nb; + struct rb_sockaddr_storage addr; + char ip[1024]; + + ty = parse_netmask("1:2:3:4:5:6:7:8/96", &addr, &nb); + is_int(HM_IPV6, ty, MSG); + if (ty == HM_IPV6) + { + is_string("1:2:3:4:5:6:7:8", rb_inet_ntop_sock((struct sockaddr *)&addr, ip, sizeof ip), MSG); + is_int(96, nb, MSG); + } +} + +static void invalid_ipv6_cidr(void) +{ + int ty, nb; + + ty = parse_netmask("1:2::7:8/aaa", NULL, NULL); + is_int(HM_HOST, ty, MSG); + + ty = parse_netmask("1:2::7:8/-1", NULL, NULL); + is_int(HM_HOST, ty, MSG); + + ty = parse_netmask("1:2::7:8/1000", NULL, &nb); + is_int(HM_IPV6, ty, MSG); + is_int(128, nb, MSG); + + ty = parse_netmask("1:2::7:8/1a", NULL, &nb); + is_int(HM_IPV6, ty, MSG); + is_int(128, nb, MSG); + + ty = parse_netmask_strict("1:2::7:8/1000", NULL, NULL); + is_int(HM_ERROR, ty, MSG); + + ty = parse_netmask_strict("1:2::7:8/1a", NULL, NULL); + is_int(HM_ERROR, ty, MSG); +} + +int main(int argc, char *argv[]) +{ + memset(&me, 0, sizeof(me)); + strcpy(me.name, "me.name."); + + rb_lib_init(NULL, NULL, NULL, 0, 1024, DNODE_HEAP_SIZE, FD_HEAP_SIZE); + rb_linebuf_init(LINEBUF_HEAP_SIZE); + + plan_lazy(); + + plain_hostmask(); + + valid_ipv4(); + invalid_ipv4(); + valid_ipv4_cidr(); + invalid_ipv4_cidr(); + + valid_ipv6(); + invalid_ipv6(); + valid_ipv6_cidr(); + invalid_ipv6_cidr(); + + return 0; +}