17b8696bfSLutz Donnerhacke /* 27b8696bfSLutz Donnerhacke * SPDX-License-Identifier: BSD-3-Clause 37b8696bfSLutz Donnerhacke * 47b8696bfSLutz Donnerhacke * Copyright 2021 Lutz Donnerhacke 57b8696bfSLutz Donnerhacke * 67b8696bfSLutz Donnerhacke * Redistribution and use in source and binary forms, with or without 77b8696bfSLutz Donnerhacke * modification, are permitted provided that the following conditions 87b8696bfSLutz Donnerhacke * are met: 97b8696bfSLutz Donnerhacke * 107b8696bfSLutz Donnerhacke * 1. Redistributions of source code must retain the above copyright 117b8696bfSLutz Donnerhacke * notice, this list of conditions and the following disclaimer. 127b8696bfSLutz Donnerhacke * 2. Redistributions in binary form must reproduce the above 137b8696bfSLutz Donnerhacke * copyright notice, this list of conditions and the following 147b8696bfSLutz Donnerhacke * disclaimer in the documentation and/or other materials provided 157b8696bfSLutz Donnerhacke * with the distribution. 167b8696bfSLutz Donnerhacke * 3. Neither the name of the copyright holder nor the names of its 177b8696bfSLutz Donnerhacke * contributors may be used to endorse or promote products derived 187b8696bfSLutz Donnerhacke * from this software without specific prior written permission. 197b8696bfSLutz Donnerhacke * 207b8696bfSLutz Donnerhacke * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 217b8696bfSLutz Donnerhacke * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 227b8696bfSLutz Donnerhacke * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 237b8696bfSLutz Donnerhacke * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 247b8696bfSLutz Donnerhacke * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 257b8696bfSLutz Donnerhacke * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 267b8696bfSLutz Donnerhacke * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 277b8696bfSLutz Donnerhacke * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 287b8696bfSLutz Donnerhacke * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 297b8696bfSLutz Donnerhacke * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 307b8696bfSLutz Donnerhacke * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 317b8696bfSLutz Donnerhacke * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 327b8696bfSLutz Donnerhacke * SUCH DAMAGE. 337b8696bfSLutz Donnerhacke */ 34c1fbb54fSLutz Donnerhacke #include <atf-c.h> 35c1fbb54fSLutz Donnerhacke #include <alias.h> 36c1fbb54fSLutz Donnerhacke #include <stdio.h> 37c1fbb54fSLutz Donnerhacke #include <stdlib.h> 38c1fbb54fSLutz Donnerhacke 39c1fbb54fSLutz Donnerhacke #include "util.h" 40c1fbb54fSLutz Donnerhacke 41c1fbb54fSLutz Donnerhacke /* common ip ranges */ 42c1fbb54fSLutz Donnerhacke static struct in_addr masq = { htonl(0x01020304) }; 43c1fbb54fSLutz Donnerhacke static struct in_addr pub = { htonl(0x0102dead) }; 44c1fbb54fSLutz Donnerhacke static struct in_addr prv1 = { htonl(0x0a00dead) }; 45c1fbb54fSLutz Donnerhacke static struct in_addr prv2 = { htonl(0xac10dead) }; 46c1fbb54fSLutz Donnerhacke static struct in_addr prv3 = { htonl(0xc0a8dead) }; 47c1fbb54fSLutz Donnerhacke static struct in_addr cgn = { htonl(0x6440dead) }; 48c1fbb54fSLutz Donnerhacke static struct in_addr ext = { htonl(0x12345678) }; 49c1fbb54fSLutz Donnerhacke 50c1fbb54fSLutz Donnerhacke #define NAT_CHECK(pip, src, msq) do { \ 51c1fbb54fSLutz Donnerhacke int res; \ 52c1fbb54fSLutz Donnerhacke int len = ntohs(pip->ip_len); \ 53c1fbb54fSLutz Donnerhacke struct in_addr dst = pip->ip_dst; \ 54c1fbb54fSLutz Donnerhacke pip->ip_src = src; \ 55c1fbb54fSLutz Donnerhacke res = LibAliasOut(la, pip, len); \ 56c1fbb54fSLutz Donnerhacke ATF_CHECK_MSG(res == PKT_ALIAS_OK, \ 57c1fbb54fSLutz Donnerhacke ">%d< not met PKT_ALIAS_OK", res); \ 58c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(msq, pip->ip_src)); \ 59c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(dst, pip->ip_dst)); \ 60c1fbb54fSLutz Donnerhacke } while(0) 61c1fbb54fSLutz Donnerhacke 62c1fbb54fSLutz Donnerhacke #define NAT_FAIL(pip, src, dst) do { \ 63c1fbb54fSLutz Donnerhacke int res; \ 64c1fbb54fSLutz Donnerhacke int len = ntohs(pip->ip_len); \ 65c1fbb54fSLutz Donnerhacke pip->ip_src = src; \ 66c1fbb54fSLutz Donnerhacke pip->ip_dst = dst; \ 67c1fbb54fSLutz Donnerhacke res = LibAliasOut(la, pip, len); \ 68c1fbb54fSLutz Donnerhacke ATF_CHECK_MSG(res != PKT_ALIAS_OK), \ 69c1fbb54fSLutz Donnerhacke ">%d< not met !PKT_ALIAS_OK", res); \ 70c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(src, pip->ip_src)); \ 71c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(dst, pip->ip_dst)); \ 72c1fbb54fSLutz Donnerhacke } while(0) 73c1fbb54fSLutz Donnerhacke 74c1fbb54fSLutz Donnerhacke #define UNNAT_CHECK(pip, src, dst, rel) do { \ 75c1fbb54fSLutz Donnerhacke int res; \ 76c1fbb54fSLutz Donnerhacke int len = ntohs(pip->ip_len); \ 77c1fbb54fSLutz Donnerhacke pip->ip_src = src; \ 78c1fbb54fSLutz Donnerhacke pip->ip_dst = dst; \ 79c1fbb54fSLutz Donnerhacke res = LibAliasIn(la, pip, len); \ 80c1fbb54fSLutz Donnerhacke ATF_CHECK_MSG(res == PKT_ALIAS_OK, \ 81c1fbb54fSLutz Donnerhacke ">%d< not met PKT_ALIAS_OK", res); \ 82c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(src, pip->ip_src)); \ 83c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(rel, pip->ip_dst)); \ 84c1fbb54fSLutz Donnerhacke } while(0) 85c1fbb54fSLutz Donnerhacke 86c1fbb54fSLutz Donnerhacke #define UNNAT_FAIL(pip, src, dst) do { \ 87c1fbb54fSLutz Donnerhacke int res; \ 88c1fbb54fSLutz Donnerhacke int len = ntohs(pip->ip_len); \ 89c1fbb54fSLutz Donnerhacke pip->ip_src = src; \ 90c1fbb54fSLutz Donnerhacke pip->ip_dst = dst; \ 91c1fbb54fSLutz Donnerhacke res = LibAliasIn(la, pip, len); \ 92c1fbb54fSLutz Donnerhacke ATF_CHECK_MSG(res != PKT_ALIAS_OK, \ 93c1fbb54fSLutz Donnerhacke ">%d< not met !PKT_ALIAS_OK", res); \ 94c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(src, pip->ip_src)); \ 95c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(dst, pip->ip_dst)); \ 96c1fbb54fSLutz Donnerhacke } while(0) 97c1fbb54fSLutz Donnerhacke 98c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(1_simplemasq); 99c1fbb54fSLutz Donnerhacke ATF_TC_BODY(1_simplemasq, dummy) 100c1fbb54fSLutz Donnerhacke { 101c1fbb54fSLutz Donnerhacke struct libalias *la = LibAliasInit(NULL); 102c1fbb54fSLutz Donnerhacke struct ip *pip; 103c1fbb54fSLutz Donnerhacke 104c1fbb54fSLutz Donnerhacke ATF_REQUIRE(la != NULL); 105c1fbb54fSLutz Donnerhacke LibAliasSetAddress(la, masq); 106c1fbb54fSLutz Donnerhacke LibAliasSetMode(la, 0, ~0); 107c1fbb54fSLutz Donnerhacke 108c1fbb54fSLutz Donnerhacke pip = ip_packet(prv1, ext, 254, 64); 109c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv1, masq); 110c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv2, masq); 111c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv3, masq); 112c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, cgn, masq); 113c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, pub, masq); 114c1fbb54fSLutz Donnerhacke 115c1fbb54fSLutz Donnerhacke free(pip); 116c1fbb54fSLutz Donnerhacke LibAliasUninit(la); 117c1fbb54fSLutz Donnerhacke } 118c1fbb54fSLutz Donnerhacke 119c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(2_unregistered); 120c1fbb54fSLutz Donnerhacke ATF_TC_BODY(2_unregistered, dummy) 121c1fbb54fSLutz Donnerhacke { 122c1fbb54fSLutz Donnerhacke struct libalias *la = LibAliasInit(NULL); 123c1fbb54fSLutz Donnerhacke struct ip *pip; 124c1fbb54fSLutz Donnerhacke 125c1fbb54fSLutz Donnerhacke ATF_REQUIRE(la != NULL); 126c1fbb54fSLutz Donnerhacke LibAliasSetAddress(la, masq); 127c1fbb54fSLutz Donnerhacke LibAliasSetMode(la, PKT_ALIAS_UNREGISTERED_ONLY, ~0); 128c1fbb54fSLutz Donnerhacke 129c1fbb54fSLutz Donnerhacke pip = ip_packet(prv1, ext, 254, 64); 130c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv1, masq); 131c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv2, masq); 132c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv3, masq); 133c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, cgn, cgn); 134c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, pub, pub); 135c1fbb54fSLutz Donnerhacke 136c1fbb54fSLutz Donnerhacke /* 137c1fbb54fSLutz Donnerhacke * State is only for new connections 138c1fbb54fSLutz Donnerhacke * Because they are now active, 139c1fbb54fSLutz Donnerhacke * the mode setting should be ignored 140c1fbb54fSLutz Donnerhacke */ 141c1fbb54fSLutz Donnerhacke LibAliasSetMode(la, 0, PKT_ALIAS_UNREGISTERED_ONLY); 142c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv1, masq); 143c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv2, masq); 144c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv3, masq); 145c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, cgn, cgn); 146c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, pub, pub); 147c1fbb54fSLutz Donnerhacke 148c1fbb54fSLutz Donnerhacke free(pip); 149c1fbb54fSLutz Donnerhacke LibAliasUninit(la); 150c1fbb54fSLutz Donnerhacke } 151c1fbb54fSLutz Donnerhacke 152c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(3_cgn); 153c1fbb54fSLutz Donnerhacke ATF_TC_BODY(3_cgn, dummy) 154c1fbb54fSLutz Donnerhacke { 155c1fbb54fSLutz Donnerhacke struct libalias *la = LibAliasInit(NULL); 156c1fbb54fSLutz Donnerhacke struct ip *pip; 157c1fbb54fSLutz Donnerhacke 158c1fbb54fSLutz Donnerhacke ATF_REQUIRE(la != NULL); 159c1fbb54fSLutz Donnerhacke LibAliasSetAddress(la, masq); 160c1fbb54fSLutz Donnerhacke LibAliasSetMode(la, PKT_ALIAS_UNREGISTERED_CGN, ~0); 161c1fbb54fSLutz Donnerhacke 162c1fbb54fSLutz Donnerhacke pip = ip_packet(prv1, ext, 254, 64); 163c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv1, masq); 164c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv2, masq); 165c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv3, masq); 166c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, cgn, masq); 167c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, pub, pub); 168c1fbb54fSLutz Donnerhacke 169c1fbb54fSLutz Donnerhacke /* 170c1fbb54fSLutz Donnerhacke * State is only for new connections 171c1fbb54fSLutz Donnerhacke * Because they are now active, 172c1fbb54fSLutz Donnerhacke * the mode setting should be ignored 173c1fbb54fSLutz Donnerhacke */ 174c1fbb54fSLutz Donnerhacke LibAliasSetMode(la, 0, PKT_ALIAS_UNREGISTERED_CGN); 175c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv1, masq); 176c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv2, masq); 177c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, prv3, masq); 178c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, cgn, masq); 179c1fbb54fSLutz Donnerhacke NAT_CHECK(pip, pub, pub); 180c1fbb54fSLutz Donnerhacke 181c1fbb54fSLutz Donnerhacke free(pip); 182c1fbb54fSLutz Donnerhacke LibAliasUninit(la); 183c1fbb54fSLutz Donnerhacke } 184c1fbb54fSLutz Donnerhacke 185c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(4_udp); 186c1fbb54fSLutz Donnerhacke ATF_TC_BODY(4_udp, dummy) 187c1fbb54fSLutz Donnerhacke { 188c1fbb54fSLutz Donnerhacke struct libalias *la = LibAliasInit(NULL); 189c1fbb54fSLutz Donnerhacke struct ip *po, *pi; 190c1fbb54fSLutz Donnerhacke struct udphdr *ui, *uo; 191c1fbb54fSLutz Donnerhacke uint16_t sport = 0x1234; 192c1fbb54fSLutz Donnerhacke uint16_t dport = 0x5678; 193c1fbb54fSLutz Donnerhacke uint16_t aport; 194c1fbb54fSLutz Donnerhacke 195c1fbb54fSLutz Donnerhacke ATF_REQUIRE(la != NULL); 196c1fbb54fSLutz Donnerhacke LibAliasSetAddress(la, masq); 197c1fbb54fSLutz Donnerhacke LibAliasSetMode(la, 0, ~0); 198c1fbb54fSLutz Donnerhacke 199c1fbb54fSLutz Donnerhacke /* Query from prv1 */ 200c1fbb54fSLutz Donnerhacke po = ip_packet(prv1, ext, 0, 64); 201c1fbb54fSLutz Donnerhacke uo = set_udp(po, sport, dport); 202c1fbb54fSLutz Donnerhacke NAT_CHECK(po, prv1, masq); 203c1fbb54fSLutz Donnerhacke ATF_CHECK(uo->uh_dport == htons(dport)); 204c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(po->ip_dst, ext)); 205c1fbb54fSLutz Donnerhacke aport = ntohs(uo->uh_sport); 206c1fbb54fSLutz Donnerhacke /* should use a different external port */ 207c1fbb54fSLutz Donnerhacke ATF_CHECK(aport != sport); 208c1fbb54fSLutz Donnerhacke 209c1fbb54fSLutz Donnerhacke /* Response */ 210c1fbb54fSLutz Donnerhacke pi = ip_packet(po->ip_dst, po->ip_src, 0, 64); 211c1fbb54fSLutz Donnerhacke ui = set_udp(pi, ntohs(uo->uh_dport), ntohs(uo->uh_sport)); 212c1fbb54fSLutz Donnerhacke UNNAT_CHECK(pi, ext, masq, prv1); 213c1fbb54fSLutz Donnerhacke ATF_CHECK(ui->uh_sport == htons(dport)); 214c1fbb54fSLutz Donnerhacke ATF_CHECK(ui->uh_dport == htons(sport)); 215c1fbb54fSLutz Donnerhacke 216c1fbb54fSLutz Donnerhacke /* Query from different source with same ports */ 217c1fbb54fSLutz Donnerhacke uo = set_udp(po, sport, dport); 218c1fbb54fSLutz Donnerhacke NAT_CHECK(po, prv2, masq); 219c1fbb54fSLutz Donnerhacke ATF_CHECK(uo->uh_dport == htons(dport)); 220c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(po->ip_dst, ext)); 221c1fbb54fSLutz Donnerhacke /* should use a different external port */ 222c1fbb54fSLutz Donnerhacke ATF_CHECK(uo->uh_sport != htons(aport)); 223c1fbb54fSLutz Donnerhacke 224c1fbb54fSLutz Donnerhacke /* Response to prv2 */ 225c1fbb54fSLutz Donnerhacke ui->uh_dport = uo->uh_sport; 226c1fbb54fSLutz Donnerhacke UNNAT_CHECK(pi, ext, masq, prv2); 227c1fbb54fSLutz Donnerhacke ATF_CHECK(ui->uh_sport == htons(dport)); 228c1fbb54fSLutz Donnerhacke ATF_CHECK(ui->uh_dport == htons(sport)); 229c1fbb54fSLutz Donnerhacke 230c1fbb54fSLutz Donnerhacke /* Response to prv1 again */ 231c1fbb54fSLutz Donnerhacke ui->uh_dport = htons(aport); 232c1fbb54fSLutz Donnerhacke UNNAT_CHECK(pi, ext, masq, prv1); 233c1fbb54fSLutz Donnerhacke ATF_CHECK(ui->uh_sport == htons(dport)); 234c1fbb54fSLutz Donnerhacke ATF_CHECK(ui->uh_dport == htons(sport)); 235c1fbb54fSLutz Donnerhacke 236c1fbb54fSLutz Donnerhacke free(pi); 237c1fbb54fSLutz Donnerhacke free(po); 238c1fbb54fSLutz Donnerhacke LibAliasUninit(la); 239c1fbb54fSLutz Donnerhacke } 240c1fbb54fSLutz Donnerhacke 241c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(5_sameport); 242c1fbb54fSLutz Donnerhacke ATF_TC_BODY(5_sameport, dummy) 243c1fbb54fSLutz Donnerhacke { 244c1fbb54fSLutz Donnerhacke struct libalias *la = LibAliasInit(NULL); 245c1fbb54fSLutz Donnerhacke struct ip *p; 246c1fbb54fSLutz Donnerhacke struct udphdr *u; 247c1fbb54fSLutz Donnerhacke uint16_t sport = 0x1234; 248c1fbb54fSLutz Donnerhacke uint16_t dport = 0x5678; 249c1fbb54fSLutz Donnerhacke uint16_t aport; 250c1fbb54fSLutz Donnerhacke 251c1fbb54fSLutz Donnerhacke ATF_REQUIRE(la != NULL); 252c1fbb54fSLutz Donnerhacke LibAliasSetAddress(la, masq); 253c1fbb54fSLutz Donnerhacke LibAliasSetMode(la, PKT_ALIAS_SAME_PORTS, ~0); 254c1fbb54fSLutz Donnerhacke 255c1fbb54fSLutz Donnerhacke /* Query from prv1 */ 256c1fbb54fSLutz Donnerhacke p = ip_packet(prv1, ext, 0, 64); 257c1fbb54fSLutz Donnerhacke u = set_udp(p, sport, dport); 258c1fbb54fSLutz Donnerhacke NAT_CHECK(p, prv1, masq); 259c1fbb54fSLutz Donnerhacke ATF_CHECK(u->uh_dport == htons(dport)); 260c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(p->ip_dst, ext)); 261c1fbb54fSLutz Donnerhacke aport = ntohs(u->uh_sport); 262c1fbb54fSLutz Donnerhacke /* should use the same external port */ 263c1fbb54fSLutz Donnerhacke ATF_CHECK(aport == sport); 264c1fbb54fSLutz Donnerhacke 265c1fbb54fSLutz Donnerhacke /* Query from different source with same ports */ 266c1fbb54fSLutz Donnerhacke u = set_udp(p, sport, dport); 267c1fbb54fSLutz Donnerhacke NAT_CHECK(p, prv2, masq); 268c1fbb54fSLutz Donnerhacke ATF_CHECK(u->uh_dport == htons(dport)); 269c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(p->ip_dst, ext)); 270c1fbb54fSLutz Donnerhacke /* should use a different external port */ 271c1fbb54fSLutz Donnerhacke ATF_CHECK(u->uh_sport != htons(aport)); 272c1fbb54fSLutz Donnerhacke 273c1fbb54fSLutz Donnerhacke free(p); 274c1fbb54fSLutz Donnerhacke LibAliasUninit(la); 275c1fbb54fSLutz Donnerhacke } 276c1fbb54fSLutz Donnerhacke 277c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(6_cleartable); 278c1fbb54fSLutz Donnerhacke ATF_TC_BODY(6_cleartable, dummy) 279c1fbb54fSLutz Donnerhacke { 280c1fbb54fSLutz Donnerhacke struct libalias *la = LibAliasInit(NULL); 281c1fbb54fSLutz Donnerhacke struct ip *po, *pi; 282c1fbb54fSLutz Donnerhacke struct udphdr *ui, *uo; 283c1fbb54fSLutz Donnerhacke uint16_t sport = 0x1234; 284c1fbb54fSLutz Donnerhacke uint16_t dport = 0x5678; 285c1fbb54fSLutz Donnerhacke uint16_t aport; 286c1fbb54fSLutz Donnerhacke 287c1fbb54fSLutz Donnerhacke ATF_REQUIRE(la != NULL); 288c1fbb54fSLutz Donnerhacke LibAliasSetAddress(la, masq); 289c1fbb54fSLutz Donnerhacke LibAliasSetMode(la, PKT_ALIAS_RESET_ON_ADDR_CHANGE, ~0); 290c1fbb54fSLutz Donnerhacke LibAliasSetMode(la, PKT_ALIAS_SAME_PORTS, PKT_ALIAS_SAME_PORTS); 291c1fbb54fSLutz Donnerhacke LibAliasSetMode(la, PKT_ALIAS_DENY_INCOMING, PKT_ALIAS_DENY_INCOMING); 292c1fbb54fSLutz Donnerhacke 293c1fbb54fSLutz Donnerhacke /* Query from prv1 */ 294c1fbb54fSLutz Donnerhacke po = ip_packet(prv1, ext, 0, 64); 295c1fbb54fSLutz Donnerhacke uo = set_udp(po, sport, dport); 296c1fbb54fSLutz Donnerhacke NAT_CHECK(po, prv1, masq); 297c1fbb54fSLutz Donnerhacke ATF_CHECK(uo->uh_dport == htons(dport)); 298c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(po->ip_dst, ext)); 299c1fbb54fSLutz Donnerhacke aport = ntohs(uo->uh_sport); 300c1fbb54fSLutz Donnerhacke /* should use the same external port */ 301c1fbb54fSLutz Donnerhacke ATF_CHECK(aport == sport); 302c1fbb54fSLutz Donnerhacke 303c1fbb54fSLutz Donnerhacke /* Response */ 304c1fbb54fSLutz Donnerhacke pi = ip_packet(po->ip_dst, po->ip_src, 0, 64); 305c1fbb54fSLutz Donnerhacke ui = set_udp(pi, ntohs(uo->uh_dport), ntohs(uo->uh_sport)); 306c1fbb54fSLutz Donnerhacke UNNAT_CHECK(pi, ext, masq, prv1); 307c1fbb54fSLutz Donnerhacke ATF_CHECK(ui->uh_sport == htons(dport)); 308c1fbb54fSLutz Donnerhacke ATF_CHECK(ui->uh_dport == htons(sport)); 309c1fbb54fSLutz Donnerhacke 310c1fbb54fSLutz Donnerhacke /* clear table by keeping the address */ 311c1fbb54fSLutz Donnerhacke LibAliasSetAddress(la, ext); 312c1fbb54fSLutz Donnerhacke LibAliasSetAddress(la, masq); 313c1fbb54fSLutz Donnerhacke 314c1fbb54fSLutz Donnerhacke /* Response to prv1 again -> DENY_INCOMING */ 315c1fbb54fSLutz Donnerhacke ui->uh_dport = htons(aport); 316c1fbb54fSLutz Donnerhacke UNNAT_FAIL(pi, ext, masq); 317c1fbb54fSLutz Donnerhacke 318c1fbb54fSLutz Donnerhacke /* Query from different source with same ports */ 319c1fbb54fSLutz Donnerhacke uo = set_udp(po, sport, dport); 320c1fbb54fSLutz Donnerhacke NAT_CHECK(po, prv2, masq); 321c1fbb54fSLutz Donnerhacke ATF_CHECK(uo->uh_dport == htons(dport)); 322c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(po->ip_dst, ext)); 323c1fbb54fSLutz Donnerhacke /* should use the same external port, because it's free */ 324c1fbb54fSLutz Donnerhacke ATF_CHECK(uo->uh_sport == htons(aport)); 325c1fbb54fSLutz Donnerhacke 326c1fbb54fSLutz Donnerhacke /* Response to prv2 */ 327c1fbb54fSLutz Donnerhacke ui->uh_dport = uo->uh_sport; 328c1fbb54fSLutz Donnerhacke UNNAT_CHECK(pi, ext, masq, prv2); 329c1fbb54fSLutz Donnerhacke ATF_CHECK(ui->uh_sport == htons(dport)); 330c1fbb54fSLutz Donnerhacke ATF_CHECK(ui->uh_dport == htons(sport)); 331c1fbb54fSLutz Donnerhacke 332c1fbb54fSLutz Donnerhacke free(pi); 333c1fbb54fSLutz Donnerhacke free(po); 334c1fbb54fSLutz Donnerhacke LibAliasUninit(la); 335c1fbb54fSLutz Donnerhacke } 336c1fbb54fSLutz Donnerhacke 337c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(7_stress); 338c1fbb54fSLutz Donnerhacke ATF_TC_BODY(7_stress, dummy) 339c1fbb54fSLutz Donnerhacke { 340c1fbb54fSLutz Donnerhacke struct libalias *la = LibAliasInit(NULL); 341c1fbb54fSLutz Donnerhacke struct ip *p; 342c1fbb54fSLutz Donnerhacke struct udphdr *u; 343c1fbb54fSLutz Donnerhacke struct { 344c1fbb54fSLutz Donnerhacke struct in_addr src, dst; 345c1fbb54fSLutz Donnerhacke uint16_t sport, dport, aport; 346c1fbb54fSLutz Donnerhacke } *batch; 347a660948bSLutz Donnerhacke size_t const batch_size = 1200; 348c1fbb54fSLutz Donnerhacke size_t const rounds = 25; 349c1fbb54fSLutz Donnerhacke size_t i, j; 350c1fbb54fSLutz Donnerhacke 351c1fbb54fSLutz Donnerhacke ATF_REQUIRE(la != NULL); 352c1fbb54fSLutz Donnerhacke LibAliasSetAddress(la, masq); 353c1fbb54fSLutz Donnerhacke 354c1fbb54fSLutz Donnerhacke p = ip_packet(prv1, ext, 0, 64); 355c1fbb54fSLutz Donnerhacke u = set_udp(p, 0, 0); 356c1fbb54fSLutz Donnerhacke 357c1fbb54fSLutz Donnerhacke batch = calloc(batch_size, sizeof(*batch)); 358c1fbb54fSLutz Donnerhacke ATF_REQUIRE(batch != NULL); 359c1fbb54fSLutz Donnerhacke for (j = 0; j < rounds; j++) { 360c1fbb54fSLutz Donnerhacke for (i = 0; i < batch_size; i++) { 361c1fbb54fSLutz Donnerhacke struct in_addr s, d; 362c1fbb54fSLutz Donnerhacke switch (i&3) { 363c1fbb54fSLutz Donnerhacke case 0: s = prv1; d = ext; break; 364c1fbb54fSLutz Donnerhacke case 1: s = prv2; d = pub; break; 365c1fbb54fSLutz Donnerhacke case 2: s = prv3; d = ext; break; 366c1fbb54fSLutz Donnerhacke case 3: s = cgn; d = pub; break; 367c1fbb54fSLutz Donnerhacke } 368c1fbb54fSLutz Donnerhacke s.s_addr &= htonl(0xffff0000); 369c1fbb54fSLutz Donnerhacke d.s_addr &= htonl(0xffff0000); 370c1fbb54fSLutz Donnerhacke batch[i].src.s_addr = s.s_addr | htonl(rand_range(0, 0xffff)); 371c1fbb54fSLutz Donnerhacke batch[i].dst.s_addr = d.s_addr | htonl(rand_range(0, 0xffff)); 372c1fbb54fSLutz Donnerhacke batch[i].sport = rand_range(1000, 60000); 373c1fbb54fSLutz Donnerhacke batch[i].dport = rand_range(1000, 60000); 374c1fbb54fSLutz Donnerhacke } 375c1fbb54fSLutz Donnerhacke 376c1fbb54fSLutz Donnerhacke for (i = 0; i < batch_size; i++) { 377c1fbb54fSLutz Donnerhacke p->ip_dst = batch[i].dst; 378c1fbb54fSLutz Donnerhacke u = set_udp(p, batch[i].sport, batch[i].dport); 379c1fbb54fSLutz Donnerhacke NAT_CHECK(p, batch[i].src, masq); 380c1fbb54fSLutz Donnerhacke ATF_CHECK(u->uh_dport == htons(batch[i].dport)); 381c1fbb54fSLutz Donnerhacke ATF_CHECK(addr_eq(p->ip_dst, batch[i].dst)); 382c1fbb54fSLutz Donnerhacke batch[i].aport = htons(u->uh_sport); 383c1fbb54fSLutz Donnerhacke } 384c1fbb54fSLutz Donnerhacke 385c1fbb54fSLutz Donnerhacke qsort(batch, batch_size, sizeof(*batch), randcmp); 386c1fbb54fSLutz Donnerhacke 387c1fbb54fSLutz Donnerhacke for (i = 0; i < batch_size; i++) { 388c1fbb54fSLutz Donnerhacke u = set_udp(p, batch[i].dport, batch[i].aport); 389c1fbb54fSLutz Donnerhacke UNNAT_CHECK(p, batch[i].dst, masq, batch[i].src); 390c1fbb54fSLutz Donnerhacke ATF_CHECK(u->uh_dport == htons(batch[i].sport)); 391c1fbb54fSLutz Donnerhacke ATF_CHECK(u->uh_sport == htons(batch[i].dport)); 392c1fbb54fSLutz Donnerhacke } 393c1fbb54fSLutz Donnerhacke } 394c1fbb54fSLutz Donnerhacke 395c1fbb54fSLutz Donnerhacke free(batch); 396c1fbb54fSLutz Donnerhacke free(p); 397c1fbb54fSLutz Donnerhacke LibAliasUninit(la); 398c1fbb54fSLutz Donnerhacke } 399c1fbb54fSLutz Donnerhacke 400c1fbb54fSLutz Donnerhacke ATF_TP_ADD_TCS(natout) 401c1fbb54fSLutz Donnerhacke { 402c1fbb54fSLutz Donnerhacke /* Use "dd if=/dev/random bs=2 count=1 | od -x" to reproduce */ 403c1fbb54fSLutz Donnerhacke srand(0x0b61); 404c1fbb54fSLutz Donnerhacke 405c1fbb54fSLutz Donnerhacke ATF_TP_ADD_TC(natout, 1_simplemasq); 406c1fbb54fSLutz Donnerhacke ATF_TP_ADD_TC(natout, 2_unregistered); 407c1fbb54fSLutz Donnerhacke ATF_TP_ADD_TC(natout, 3_cgn); 408c1fbb54fSLutz Donnerhacke ATF_TP_ADD_TC(natout, 4_udp); 409c1fbb54fSLutz Donnerhacke ATF_TP_ADD_TC(natout, 5_sameport); 410c1fbb54fSLutz Donnerhacke ATF_TP_ADD_TC(natout, 6_cleartable); 411c1fbb54fSLutz Donnerhacke ATF_TP_ADD_TC(natout, 7_stress); 412c1fbb54fSLutz Donnerhacke 413c1fbb54fSLutz Donnerhacke return atf_no_error(); 414c1fbb54fSLutz Donnerhacke } 415