/* IPXWrapper test suite * Copyright (C) 2017-2023 Daniel Collins * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * 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 "../src/addr.h" #include "../src/addrcache.h" #include "../src/common.h" #include "tap/basic.h" /* Mock time() so we can test timing out of address cache records */ static time_t now = 0; static time_t mock_time(void) { return now; } /* Need to implement log_printf() and w32_error() for addrcache.c */ void log_printf(enum ipx_log_level level, const char *fmt, ...) { va_list argv; va_start(argv, fmt); vfprintf(stderr, fmt, argv); va_end(argv); fprintf(stderr, "\n"); } const char *w32_error(DWORD errnum) { static char buf[1024] = {'\0'}; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errnum, 0, buf, 1023, NULL); buf[strcspn(buf, "\r\n")] = '\0'; return buf; } int main() { extern time_t (*addrcache_time)(void); addrcache_time = &mock_time; plan_lazy(); { addr_cache_init(); SOCKADDR_STORAGE addr; size_t addrlen; ok(!addr_cache_get(&addr, &addrlen, addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), 1), "addr_cache_get() returns false when no addresses are known"); addr_cache_cleanup(); } { addr_cache_init(); struct sockaddr_in addr_in; memset(&addr_in, 0xAB, sizeof(addr_in)); addr_cache_set((struct sockaddr*)(&addr_in), sizeof(addr_in), addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), 1); SOCKADDR_STORAGE addr_out; size_t aolen; if(ok(addr_cache_get(&addr_out, &aolen, addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), 1), "addr_cache_get() returns true when address is known")) { is_int(sizeof(addr_in), aolen, "addr_cache_get() returns correct address length"); is_blob(&addr_in, &addr_out, sizeof(addr_in), "addr_cache_get() returns correct address data"); } addr_cache_cleanup(); } { addr_cache_init(); struct sockaddr_in addr_in; memset(&addr_in, 0xAB, sizeof(addr_in)); addr_cache_set((struct sockaddr*)(&addr_in), sizeof(addr_in), addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), 1); SOCKADDR_STORAGE addr_out; size_t aolen; now += 29; if(ok(addr_cache_get(&addr_out, &aolen, addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), 1), "addr_cache_get() returns true when address is about to expire")) { is_int(sizeof(addr_in), aolen, "addr_cache_get() returns correct address length"); is_blob(&addr_in, &addr_out, sizeof(addr_in), "addr_cache_get() returns correct address data"); } now += 1; ok(!addr_cache_get(&addr_out, &aolen, addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), 1), "addr_cache_get() returns false when address has expired"); addr_cache_cleanup(); } { addr_cache_init(); struct sockaddr_in addr_in; memset(&addr_in, 0xAB, sizeof(addr_in)); addr_cache_set((struct sockaddr*)(&addr_in), sizeof(addr_in), addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), 1); SOCKADDR_STORAGE addr_out; size_t aolen; ok(!addr_cache_get(&addr_out, &aolen, addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x02}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), 1), "addr_cache_get() returns false when network number differs"); addr_cache_cleanup(); } { addr_cache_init(); struct sockaddr_in addr_in; memset(&addr_in, 0xAB, sizeof(addr_in)); addr_cache_set((struct sockaddr*)(&addr_in), sizeof(addr_in), addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), 1); SOCKADDR_STORAGE addr_out; size_t aolen; ok(!addr_cache_get(&addr_out, &aolen, addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x02}), 1), "addr_cache_get() returns false when node number differs"); addr_cache_cleanup(); } { addr_cache_init(); struct sockaddr_in addr_in; memset(&addr_in, 0xAB, sizeof(addr_in)); addr_cache_set((struct sockaddr*)(&addr_in), sizeof(addr_in), addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), 1); SOCKADDR_STORAGE addr_out; size_t aolen; ok(!addr_cache_get(&addr_out, &aolen, addr32_in((unsigned char[]){0x00, 0x00, 0x00, 0x01}), addr48_in((unsigned char[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x01}), 2), "addr_cache_get() returns false when socket number differs"); addr_cache_cleanup(); } return 0; }