diff options
author | mtm <mtm@FreeBSD.org> | 2007-04-21 11:23:33 +0000 |
---|---|---|
committer | mtm <mtm@FreeBSD.org> | 2007-04-21 11:23:33 +0000 |
commit | e60ce7e12076f27ac5471441a6940e2254378506 (patch) | |
tree | 8ae66e2c330262a189bb2a86ccfba12c776df717 /tools/regression/netinet6 | |
parent | d0bcca2e7b47042964b48554853ab9c425026996 (diff) | |
download | FreeBSD-src-e60ce7e12076f27ac5471441a6940e2254378506.zip FreeBSD-src-e60ce7e12076f27ac5471441a6940e2254378506.tar.gz |
Regression tests for recent changes to inet6_rth_* family of functions
regarding RFC3542 compliance.
Diffstat (limited to 'tools/regression/netinet6')
-rw-r--r-- | tools/regression/netinet6/inet6_rth/Makefile | 10 | ||||
-rw-r--r-- | tools/regression/netinet6/inet6_rth/inet6_rth-segments.c | 336 | ||||
-rw-r--r-- | tools/regression/netinet6/inet6_rth/test_subr.c | 166 | ||||
-rw-r--r-- | tools/regression/netinet6/inet6_rth/test_subr.h | 44 |
4 files changed, 556 insertions, 0 deletions
diff --git a/tools/regression/netinet6/inet6_rth/Makefile b/tools/regression/netinet6/inet6_rth/Makefile new file mode 100644 index 0000000..ac284d3 --- /dev/null +++ b/tools/regression/netinet6/inet6_rth/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ +# +PROG= inet6_rth-segments +SRCS= test_subr.c inet6_rth-segments.c +NO_MAN= + +CFLAGS+= -Wall +DEBUG_FLAGS= -g + +.include <bsd.prog.mk> diff --git a/tools/regression/netinet6/inet6_rth/inet6_rth-segments.c b/tools/regression/netinet6/inet6_rth/inet6_rth-segments.c new file mode 100644 index 0000000..5ac1d97 --- /dev/null +++ b/tools/regression/netinet6/inet6_rth/inet6_rth-segments.c @@ -0,0 +1,336 @@ +/*- + * Copyright (c) 2007 Michael Telahun Makonnen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <netinet/ip6.h> + +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "test_subr.h" + +static void init_hdrs(struct msghdr *, struct cmsghdr *, char *, size_t); +static void test_cmsg_firsthdr(); +static void test_cmsg_nexthdr(); +static void test_rth_space(); +static void test_rth_segments(); +static void test_rth_add(); +static void test_rth_init(); + +int +main(int argc, char* argv[]) +{ + /* + * Initialize global variables. + */ + g_total = 0; + g_pass = 0; + g_fail = 0; + memset(g_funcname, 0, sizeof(g_funcname)); + + /* + * Start the tests. + */ + printf("Starting inet6_rth_* and cmsg macro regression tests...\n"); + + test_cmsg_firsthdr(); /* CMSG_FIRSTHDR */ + test_cmsg_nexthdr(); /* CMSG_NEXTHDR */ + test_rth_space(); /* inet6_rth_space */ + test_rth_segments(); /* inet6_rth_segments */ + test_rth_add(); /* inet6_rth_add */ + test_rth_init(); /* inet6_rth_space */ + + if (g_fail == 0) + printf("OK. "); + else + printf("NOT OK. "); + printf("Total: %d Pass: %d Fail: %d\n", g_total, g_pass, g_fail); + + return (g_fail); +} + +void +test_rth_init() +{ + char buf[10240]; + char *pbuf; + + set_funcname("test_rth_init", sizeof("test_rth_init\0")); + + pbuf = inet6_rth_init((void *)buf, 10, IPV6_RTHDR_TYPE_0, 100); + checkptr(NULL, pbuf, "buffer too small\0"); + + pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0); + checkptr((caddr_t)&buf, pbuf, "0 segments\0"); + + pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127); + checkptr((caddr_t)&buf, pbuf, "127 segments\0"); + + pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, -1); + checkptr(NULL, pbuf, "negative number of segments\0"); + + pbuf = inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 128); + checkptr(NULL, pbuf, "128 segments\0"); +} + +void +test_rth_add() +{ + int i, ret; + char buf[10240]; + struct addrinfo *res; + struct addrinfo hints; + + set_funcname("test_rth_add", sizeof("test_rth_add\0")); + + if (NULL == inet6_rth_init(buf, 10240, IPV6_RTHDR_TYPE_0, 127)) + abort(); + memset((void *)&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET6; + hints.ai_flags = AI_NUMERICHOST; + if (0 != getaddrinfo("::1", NULL, (const struct addrinfo *)&hints, &res)) + abort(); + for (i = 0; i < 127; i++) + inet6_rth_add((void *)buf, + &((struct sockaddr_in6 *)(res->ai_addr))->sin6_addr); + checknum(127, ((struct ip6_rthdr0 *)buf)->ip6r0_segleft, 0, + "add 127 segments\0"); + + ret = inet6_rth_add((void *)buf, + &((struct sockaddr_in6 *)(res->ai_addr))->sin6_addr); + checknum(-1, ret, 0, "add 128th segment to 127 segment header\0"); + + freeaddrinfo(res); +} + +void +test_rth_segments() +{ + int seg; + char buf[10240]; + + set_funcname("test_rth_segments", sizeof("test_rth_segments\0")); + + /* + * Test: invalid routing header type. + */ + if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0)) + abort(); + ((struct ip6_rthdr *)buf)->ip6r_type = ~IPV6_RTHDR_TYPE_0; + seg = inet6_rth_segments((const void *)buf); + checknum(-1, seg, 0, "invalid routing header type\0"); + + /* + * Test: 0 segments. + */ + if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0)) + abort(); + seg = inet6_rth_segments((const void *)buf); + checknum(0, seg, 0, "0 segments\0"); + + /* + * Test: 127 segments. + */ + if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127)) + abort(); + seg = inet6_rth_segments((const void *)buf); + checknum(127, seg, 0, "127 segments\0"); + + /* + * Test: -1 segments. + */ +/* + if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 0)) + abort(); + ((struct ip6_rthdr0 *)buf)->ip6r0_len = -1 * 2; + seg = inet6_rth_segments((const void *)buf); + checknum(-1, seg, 0, "-1 segments\0"); +*/ + /* + * Test: 128 segments. + */ +/* + if (NULL == inet6_rth_init((void *)buf, 10240, IPV6_RTHDR_TYPE_0, 127)) + abort(); + ((struct ip6_rthdr0 *)buf)->ip6r0_len = 128 * 2; + seg = inet6_rth_segments((const void *)buf); + checknum(-1, seg, 0, "128 segments\0"); +*/ +} + +void +test_rth_space() +{ + socklen_t len; + + set_funcname("test_rth_space", sizeof("test_rth_space\0")); + + /* + * Test: invalid routing header type. + */ + len = inet6_rth_space(~IPV6_RTHDR_TYPE_0, 0); + checknum(0, len, 0, "invalid routing header type\0"); + + /* + * Test: valid number of segments. + */ + len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 0); + checknum(0, len, 1, "0 segments\0"); + len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 127); + checknum(0, len, 1, "0 segments\0"); + + /* + * Test: invalid number of segments. + */ + len = inet6_rth_space(IPV6_RTHDR_TYPE_0, -1); + checknum(0, len, 0, "-1 segments\0"); + len = inet6_rth_space(IPV6_RTHDR_TYPE_0, 128); + checknum(0, len, 0, "128 segments\0"); +} + +void +test_cmsg_nexthdr() +{ + struct msghdr mh; + struct cmsghdr cmh; + struct cmsghdr *cmhp, *cmhnextp; + char ancbuf[10240]; + char magic[] = "MAGIC"; + + set_funcname("test_cmsg_nexthdr", sizeof("test_cmsg_nexthdr")); + + /* + * Test: More than one cmsghdr + */ + init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf)); + mh.msg_control = (caddr_t)ancbuf; + mh.msg_controllen = CMSG_SPACE(0) * 2; /* 2 cmsghdr with no data */ + cmh.cmsg_len = CMSG_LEN(0); + + /* + * Copy the same instance of cmsghdr twice. Use a magic value + * to id the second copy. + */ + bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh)); + strlcpy((char *)&cmh, (const char *)&magic, sizeof(magic)); + bcopy((void *)&cmh, + (void *)((caddr_t)ancbuf + CMSG_SPACE(0)), + sizeof(cmh)); + cmhp = CMSG_FIRSTHDR(&mh); + cmhnextp = CMSG_NXTHDR(&mh, cmhp); + checkstr((const char *)&magic, (const char *)cmhnextp, sizeof(magic), + "more than one cmsghdr\0"); + + /* + * Test: only one cmsghdr + */ + init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf)); + mh.msg_control = (caddr_t)ancbuf; + mh.msg_controllen = CMSG_SPACE(0); + cmh.cmsg_len = CMSG_LEN(0); + bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh)); + cmhp = CMSG_FIRSTHDR(&mh); + cmhnextp = CMSG_NXTHDR(&mh, cmhp); + checkptr(NULL, (caddr_t)cmhnextp, "only one cmsghdr\0"); + + /* + * Test: NULL cmsg pointer + */ + init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf)); + mh.msg_control = (caddr_t)ancbuf; + mh.msg_controllen = sizeof(ancbuf); + cmh.cmsg_len = sizeof(ancbuf); + bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh)); + cmhp = CMSG_FIRSTHDR(&mh); + cmhnextp = CMSG_NXTHDR(&mh, NULL); + checkptr((caddr_t)cmhp, (caddr_t)cmhnextp, "null second argument\0"); +} + +void +test_cmsg_firsthdr() +{ + struct msghdr mh; + struct cmsghdr cmh; + struct cmsghdr *cmhp; + char ancbuf[1024]; + char magic[] = "MAGIC"; + + set_funcname("test_cmsg_firsthdr", sizeof("test_cmsg_firsthdr")); + + /* CMSG_FIRSTHDR() where msg_control is NULL */ + init_hdrs(&mh, NULL, NULL, 0); + mh.msg_control = NULL; + cmhp = CMSG_FIRSTHDR(&mh); + checkptr(NULL, (caddr_t)cmhp, + "msg_control is NULL\0"); + + /* - where msg_controllen < sizeof cmsghdr */ + init_hdrs(&mh, NULL, NULL, 0); + mh.msg_control = (caddr_t)&cmh; + mh.msg_controllen = sizeof(cmh) - 1; + cmhp = CMSG_FIRSTHDR(&mh); + checkptr(NULL, (caddr_t)cmhp, + "msg_controllen < sizeof cmsghdr\0"); + + /* - where msg_controllen == 0 */ + init_hdrs(&mh, NULL, NULL, 0); + mh.msg_control = (caddr_t)&cmh; + mh.msg_controllen = 0; + cmhp = CMSG_FIRSTHDR(&mh); + checkptr(NULL, (caddr_t)cmhp, + "msg_controllen == 0\0"); + + /* no errors */ + init_hdrs(&mh, &cmh, ancbuf, sizeof(ancbuf)); + memset((void *)ancbuf, 0, sizeof(ancbuf)); + mh.msg_control = (caddr_t)ancbuf; + mh.msg_controllen = sizeof(ancbuf); + strlcpy((char *)&cmh, (const char *)&magic, sizeof(magic)); + bcopy((void *)&cmh, (void *)ancbuf, sizeof(cmh)); + cmhp = CMSG_FIRSTHDR(&mh); + checkstr((const char *)&magic, (const char *)cmhp, sizeof(magic), + "with payload\0"); +} + +void +init_hdrs(struct msghdr *mhp, struct cmsghdr *cmhp, char *bufp, size_t bufsize) +{ + if (mhp != NULL) + memset((void *)mhp, 0, sizeof(struct msghdr)); + if (cmhp != NULL) + memset((void *)cmhp, 0, sizeof(struct cmsghdr)); + if (bufp != NULL) + memset((void *)bufp, 0, bufsize); +} diff --git a/tools/regression/netinet6/inet6_rth/test_subr.c b/tools/regression/netinet6/inet6_rth/test_subr.c new file mode 100644 index 0000000..ab09ec8 --- /dev/null +++ b/tools/regression/netinet6/inet6_rth/test_subr.c @@ -0,0 +1,166 @@ +/*- + * Copyright (c) 2007 Michael Telahun Makonnen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "test_subr.h" + +int g_total; +int g_pass; +int g_fail; +char g_funcname[FUNCNAMESIZE]; +char g_testdesc[LINESIZE]; +char g_errbuf[LINESIZE]; + +void +set_funcname(char *bufp, size_t bufsize) +{ + strlcpy(g_funcname, bufp, + bufsize < FUNCNAMESIZE ? bufsize : FUNCNAMESIZE); +} + +/* + * desc is a NULL-terminated string. + */ +void +checkptr(caddr_t expected, caddr_t got, const char *desc) +{ + int len; + int failed; + char sbuf[LINESIZE]; + + memset((void *)sbuf, 0, LINESIZE); + snprintf(g_testdesc, LINESIZE, desc); + + failed = 1; + g_total++; + if (got == expected) { + len = snprintf(sbuf, LINESIZE, "ok"); + g_pass++; + failed = 0; + } else { + len = snprintf(sbuf, LINESIZE, "not ok"); + snprintf(g_errbuf, LINESIZE, " : Expected %#x, but got %#x", + (unsigned int)expected, (unsigned int)got); + g_fail++; + } + snprintf(sbuf + len, LINESIZE - len, " %d - %s (%s)", + g_total, g_funcname, g_testdesc); + printf(sbuf); + if (failed) + printf(g_errbuf); + printf("\n"); + fflush(NULL); + memset((void *)g_errbuf, 0, LINESIZE); + memset((void *)g_testdesc, 0, LINESIZE); +} + +void +checkstr(const char *expected, const char *got, size_t explen, const char *desc) +{ + int len; + int failed; + char sbuf[LINESIZE]; + + memset((void *)sbuf, 0, LINESIZE); + snprintf(g_testdesc, LINESIZE, desc); + + failed = 1; + g_total++; + if (strncmp(expected, got, explen) == 0) { + len = snprintf(sbuf, LINESIZE, "ok"); + g_pass++; + failed = 0; + } else { + len = snprintf(sbuf, LINESIZE, "not ok"); + snprintf(g_errbuf, LINESIZE, + " : Expected %s, but got %s", expected, got); + g_fail++; + } + snprintf(sbuf + len, LINESIZE - len, " %d - %s (%s)", + g_total, g_funcname, g_testdesc); + printf(sbuf); + if (failed) + printf(g_errbuf); + printf("\n"); + fflush(NULL); + memset((void *)g_errbuf, 0, LINESIZE); + memset((void *)g_testdesc, 0, LINESIZE); +} + +void +checknum(int expected, int got, int cmp, const char *desc) +{ + int len; + int pass; + int failed; + char sbuf[LINESIZE]; + + memset((void *)sbuf, 0, LINESIZE); + snprintf(g_testdesc, LINESIZE, desc); + + failed = 1; + pass = 0; + g_total++; + switch(cmp) { + case 0: + pass = (got == expected) ? 1 : 0; + break; + case 1: + pass = (got > expected) ? 1 : 0; + break; + case -1: + pass = (got < expected) ? 1 : 0; + break; + } + if (pass != 0) { + len = snprintf(sbuf, LINESIZE, "ok"); + g_pass++; + failed = 0; + } else { + len = snprintf(sbuf, LINESIZE, "not ok"); + snprintf(g_errbuf, LINESIZE, + " : Expected %d, but got %d", expected, got); + g_fail++; + } + snprintf(sbuf + len, LINESIZE - len, " %d - %s (%s)", + g_total, g_funcname, g_testdesc); + printf(sbuf); + if (failed) + printf(g_errbuf); + printf("\n"); + fflush(NULL); + memset((void *)g_errbuf, 0, LINESIZE); + memset((void *)g_testdesc, 0, LINESIZE); +} diff --git a/tools/regression/netinet6/inet6_rth/test_subr.h b/tools/regression/netinet6/inet6_rth/test_subr.h new file mode 100644 index 0000000..f0463da --- /dev/null +++ b/tools/regression/netinet6/inet6_rth/test_subr.h @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2007 Michael Telahun Makonnen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/types.h> + +#define LINESIZE 256 +#define FUNCNAMESIZE 32 + +extern int g_total; +extern int g_pass; +extern int g_fail; +extern char g_funcname[FUNCNAMESIZE]; +extern char g_testdesc[LINESIZE]; +extern char g_errbuf[LINESIZE]; + +void set_funcname(char *, size_t); +void checkptr(caddr_t, caddr_t, const char *); +void checkstr(const char *, const char *, size_t, const char*); +void checknum(int, int, int, const char *); |