Index: tests/sys/netinet/libalias/2_natout.c =================================================================== --- tests/sys/netinet/libalias/2_natout.c +++ tests/sys/netinet/libalias/2_natout.c @@ -5,63 +5,6 @@ #include "util.h" -/* common ip ranges */ -static struct in_addr masq = { htonl(0x01020304) }; -static struct in_addr pub = { htonl(0x0102dead) }; -static struct in_addr prv1 = { htonl(0x0a00dead) }; -static struct in_addr prv2 = { htonl(0xac10dead) }; -static struct in_addr prv3 = { htonl(0xc0a8dead) }; -static struct in_addr cgn = { htonl(0x6440dead) }; -static struct in_addr ext = { htonl(0x12345678) }; - -#define NAT_CHECK(pip, src, msq) do { \ - int res; \ - int len = ntohs(pip->ip_len); \ - struct in_addr dst = pip->ip_dst; \ - pip->ip_src = src; \ - res = LibAliasOut(la, pip, len); \ - ATF_CHECK_MSG(res == PKT_ALIAS_OK, \ - ">%d< not met PKT_ALIAS_OK", res); \ - ATF_CHECK(addr_eq(msq, pip->ip_src)); \ - ATF_CHECK(addr_eq(dst, pip->ip_dst)); \ -} while(0) - -#define NAT_FAIL(pip, src, dst) do { \ - int res; \ - int len = ntohs(pip->ip_len); \ - pip->ip_src = src; \ - pip->ip_dst = dst; \ - res = LibAliasOut(la, pip, len); \ - ATF_CHECK_MSG(res != PKT_ALIAS_OK), \ - ">%d< not met !PKT_ALIAS_OK", res); \ - ATF_CHECK(addr_eq(src, pip->ip_src)); \ - ATF_CHECK(addr_eq(dst, pip->ip_dst)); \ -} while(0) - -#define UNNAT_CHECK(pip, src, dst, rel) do { \ - int res; \ - int len = ntohs(pip->ip_len); \ - pip->ip_src = src; \ - pip->ip_dst = dst; \ - res = LibAliasIn(la, pip, len); \ - ATF_CHECK_MSG(res == PKT_ALIAS_OK, \ - ">%d< not met PKT_ALIAS_OK", res); \ - ATF_CHECK(addr_eq(src, pip->ip_src)); \ - ATF_CHECK(addr_eq(rel, pip->ip_dst)); \ -} while(0) - -#define UNNAT_FAIL(pip, src, dst) do { \ - int res; \ - int len = ntohs(pip->ip_len); \ - pip->ip_src = src; \ - pip->ip_dst = dst; \ - res = LibAliasIn(la, pip, len); \ - ATF_CHECK_MSG(res != PKT_ALIAS_OK, \ - ">%d< not met !PKT_ALIAS_OK", res); \ - ATF_CHECK(addr_eq(src, pip->ip_src)); \ - ATF_CHECK(addr_eq(dst, pip->ip_dst)); \ -} while(0) - ATF_TC_WITHOUT_HEAD(1_simplemasq); ATF_TC_BODY(1_simplemasq, dummy) { Index: tests/sys/netinet/libalias/3_natin.c =================================================================== --- /dev/null +++ tests/sys/netinet/libalias/3_natin.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include + +#include "util.h" + +ATF_TC_WITHOUT_HEAD(1_portforward); +ATF_TC_BODY(1_portforward, dummy) +{ + struct libalias *la = LibAliasInit(NULL); + struct alias_link *pf1, *pf2, *pf3; + struct ip *p; + struct udphdr *u; + + ATF_REQUIRE(la != NULL); + LibAliasSetAddress(la, masq); + LibAliasSetMode(la, PKT_ALIAS_DENY_INCOMING, ~0); + + /* + * Fully specified + */ + pf1 = LibAliasRedirectPort(la, prv1, ntohs(0x1234), ext, ntohs(0x5678), masq, ntohs(0xabcd), IPPROTO_UDP); + ATF_REQUIRE(pf1 != NULL); + + p = ip_packet(ext, masq, 0, 64); + u = set_udp(p, 0x5678, 0xabcd); + UNNAT_CHECK(p, ext, masq, prv1); + ATF_CHECK(u->uh_sport == ntohs(0x5678)); + ATF_CHECK(u->uh_dport == ntohs(0x1234)); + + /* try again */ + u = set_udp(p, 0x5678, 0xabcd); + UNNAT_CHECK(p, ext, masq, prv1); + ATF_CHECK(u->uh_sport == ntohs(0x5678)); + ATF_CHECK(u->uh_dport == ntohs(0x1234)); + + /* different source */ + u = set_udp(p, 0x5678, 0xabcd); + UNNAT_FAIL(p, pub, masq); + u = set_udp(p, 0xdead, 0xabcd); + UNNAT_FAIL(p, ext, masq); + + LibAliasRedirectDelete(la, pf1); + /* try again */ + u = set_udp(p, 0x5678, 0xabcd); + UNNAT_FAIL(p, ext, masq); + + /* + * Any external port + */ + pf2 = LibAliasRedirectPort(la, prv2, ntohs(0x1234), ext, ntohs(0), masq, ntohs(0xabcd), IPPROTO_UDP); + ATF_REQUIRE(pf2 != NULL); + + u = set_udp(p, 0x6789, 0xabcd); + UNNAT_CHECK(p, ext, masq, prv2); + ATF_CHECK(u->uh_sport == ntohs(0x6789)); + ATF_CHECK(u->uh_dport == ntohs(0x1234)); + + /* try again */ + u = set_udp(p, 0x6789, 0xabcd); + UNNAT_CHECK(p, ext, masq, prv2); + ATF_CHECK(u->uh_sport == ntohs(0x6789)); + ATF_CHECK(u->uh_dport == ntohs(0x1234)); + + /* different source */ + u = set_udp(p, 0x6789, 0xabcd); + UNNAT_FAIL(p, pub, masq); + u = set_udp(p, 0xdead, 0xabcd); + UNNAT_CHECK(p, ext, masq, prv2); + ATF_CHECK(u->uh_sport == ntohs(0xdead)); + ATF_CHECK(u->uh_dport == ntohs(0x1234)); + + LibAliasRedirectDelete(la, pf2); + /* try again, but not the existing flow */ + u = set_udp(p, 0x78ab, 0xabcd); + UNNAT_FAIL(p, ext, masq); + + /* + * Any external host + */ + pf3 = LibAliasRedirectPort(la, prv3, ntohs(0x1234), ANY_ADDR, ntohs(0x789a), masq, ntohs(0xabcd), IPPROTO_UDP); + ATF_REQUIRE(pf3 != NULL); + + u = set_udp(p, 0x789a, 0xabcd); + UNNAT_CHECK(p, ext, masq, prv3); + ATF_CHECK(u->uh_sport == ntohs(0x789a)); + ATF_CHECK(u->uh_dport == ntohs(0x1234)); + + /* try again */ + u = set_udp(p, 0x789a, 0xabcd); + UNNAT_CHECK(p, ext, masq, prv3); + ATF_CHECK(u->uh_sport == ntohs(0x789a)); + ATF_CHECK(u->uh_dport == ntohs(0x1234)); + + /* different source */ + u = set_udp(p, 0x789a, 0xabcd); + UNNAT_CHECK(p, pub, masq, prv3); + ATF_CHECK(u->uh_sport == ntohs(0x789a)); + ATF_CHECK(u->uh_dport == ntohs(0x1234)); + u = set_udp(p, 0xeada, 0xabcd); + UNNAT_FAIL(p, ext, masq); + + LibAliasRedirectDelete(la, pf3); + /* try again, but not the existing flow */ + u = set_udp(p, 0x789a, 0xabcd); + UNNAT_FAIL(p, cgn, masq); + + free(p); + LibAliasUninit(la); +} + +ATF_TP_ADD_TCS(natin) +{ + /* Use "dd if=/dev/random bs=2 count=1 | od -x" to reproduce */ + srand(0xe859); + + ATF_TP_ADD_TC(natin, 1_portforward); + + return atf_no_error(); +} Index: tests/sys/netinet/libalias/Makefile =================================================================== --- tests/sys/netinet/libalias/Makefile +++ tests/sys/netinet/libalias/Makefile @@ -7,6 +7,7 @@ ATF_TESTS_C+= 1_instance \ 2_natout \ + 3_natin \ PROGS+= perf @@ -14,6 +15,7 @@ SRCS.1_instance=1_instance.c util.c SRCS.2_natout= 2_natout.c util.c +SRCS.3_natin= 3_natin.c util.c SRCS.perf= perf.c util.c .include Index: tests/sys/netinet/libalias/perf.c =================================================================== --- tests/sys/netinet/libalias/perf.c +++ tests/sys/netinet/libalias/perf.c @@ -5,11 +5,6 @@ #include "util.h" #include -/* common ip ranges */ -static struct in_addr masq = { htonl(0x01020304) }; -static struct in_addr prv = { htonl(0x0a000000) }; -static struct in_addr ext = { htonl(0x12000000) }; - #define timevalcmp(tv, uv, cmp) \ (((tv).tv_sec == (uv).tv_sec) \ ? ((tv).tv_usec cmp (uv).tv_usec) \ @@ -55,10 +50,10 @@ LibAliasSetAddress(la, masq); LibAliasSetMode(la, PKT_ALIAS_DENY_INCOMING, PKT_ALIAS_DENY_INCOMING); - prv.s_addr &= htonl(0xffff0000); + prv1.s_addr &= htonl(0xffff0000); ext.s_addr &= htonl(0xffff0000); - p = ip_packet(prv, ext, 0, 64); + p = ip_packet(prv1, ext, 0, 64); u = set_udp(p, 0, 0); if (NULL == (batch = calloc(batch_size, sizeof(*batch)))) { @@ -79,7 +74,7 @@ gettimeofday(&start, NULL); printf("%5.1f ", max_seconds - timevaldiff(timeout, start)/1000000.0f); for (cnt = i = 0; i < batch_size; i++, cnt++) { - batch[i].src.s_addr = prv.s_addr | htonl(rand_range(0, 0xffff)); + batch[i].src.s_addr = prv1.s_addr | htonl(rand_range(0, 0xffff)); batch[i].dst.s_addr = ext.s_addr | htonl(rand_range(0, 0xffff)); batch[i].sport = rand_range(1000, 60000); batch[i].dport = rand_range(1000, 60000); Index: tests/sys/netinet/libalias/util.h =================================================================== --- tests/sys/netinet/libalias/util.h +++ tests/sys/netinet/libalias/util.h @@ -7,6 +7,9 @@ #ifndef _UTIL_H #define _UTIL_H +/* common ip ranges */ +extern struct in_addr masq, pub, prv1, prv2, prv3, cgn, ext, ANY_ADDR; + int randcmp(const void *a, const void *b); void hexdump(void *p, size_t len); struct ip * ip_packet(struct in_addr src, struct in_addr dst, u_char protocol, size_t len); @@ -26,4 +29,52 @@ return min + rand()%(max - min); } +#define NAT_CHECK(pip, src, msq) do { \ + int res; \ + int len = ntohs(pip->ip_len); \ + struct in_addr dst = pip->ip_dst; \ + pip->ip_src = src; \ + res = LibAliasOut(la, pip, len); \ + ATF_CHECK_MSG(res == PKT_ALIAS_OK, \ + ">%d< not met PKT_ALIAS_OK", res); \ + ATF_CHECK(addr_eq(msq, pip->ip_src)); \ + ATF_CHECK(addr_eq(dst, pip->ip_dst)); \ +} while(0) + +#define NAT_FAIL(pip, src, dst) do { \ + int res; \ + int len = ntohs(pip->ip_len); \ + pip->ip_src = src; \ + pip->ip_dst = dst; \ + res = LibAliasOut(la, pip, len); \ + ATF_CHECK_MSG(res != PKT_ALIAS_OK), \ + ">%d< not met !PKT_ALIAS_OK", res); \ + ATF_CHECK(addr_eq(src, pip->ip_src)); \ + ATF_CHECK(addr_eq(dst, pip->ip_dst)); \ +} while(0) + +#define UNNAT_CHECK(pip, src, dst, rel) do { \ + int res; \ + int len = ntohs(pip->ip_len); \ + pip->ip_src = src; \ + pip->ip_dst = dst; \ + res = LibAliasIn(la, pip, len); \ + ATF_CHECK_MSG(res == PKT_ALIAS_OK, \ + ">%d< not met PKT_ALIAS_OK", res); \ + ATF_CHECK(addr_eq(src, pip->ip_src)); \ + ATF_CHECK(addr_eq(rel, pip->ip_dst)); \ +} while(0) + +#define UNNAT_FAIL(pip, src, dst) do { \ + int res; \ + int len = ntohs(pip->ip_len); \ + pip->ip_src = src; \ + pip->ip_dst = dst; \ + res = LibAliasIn(la, pip, len); \ + ATF_CHECK_MSG(res != PKT_ALIAS_OK, \ + ">%d< not met !PKT_ALIAS_OK", res); \ + ATF_CHECK(addr_eq(src, pip->ip_src)); \ + ATF_CHECK(addr_eq(dst, pip->ip_dst)); \ +} while(0) + #endif /* _UTIL_H */ Index: tests/sys/netinet/libalias/util.c =================================================================== --- tests/sys/netinet/libalias/util.c +++ tests/sys/netinet/libalias/util.c @@ -5,6 +5,16 @@ #include "util.h" +/* common ip ranges */ +struct in_addr masq = { htonl(0x01020304) }; +struct in_addr pub = { htonl(0x0102dead) }; +struct in_addr prv1 = { htonl(0x0a00dead) }; +struct in_addr prv2 = { htonl(0xac10dead) }; +struct in_addr prv3 = { htonl(0xc0a8dead) }; +struct in_addr cgn = { htonl(0x6440dead) }; +struct in_addr ext = { htonl(0x12345678) }; +struct in_addr ANY_ADDR = { 0 }; + #define REQUIRE(x) do { \ if (!(x)) { \ fprintf(stderr, "Failed in %s %s:%d.\n",\