xref: /freebsd/tests/sys/netinet/libalias/2_natout.c (revision c555dcdd)
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 ATF_TC_WITHOUT_HEAD(1_simplemasq);
42c1fbb54fSLutz Donnerhacke ATF_TC_BODY(1_simplemasq, dummy)
43c1fbb54fSLutz Donnerhacke {
44c1fbb54fSLutz Donnerhacke 	struct libalias *la = LibAliasInit(NULL);
45c1fbb54fSLutz Donnerhacke 	struct ip *pip;
46c1fbb54fSLutz Donnerhacke 
47c1fbb54fSLutz Donnerhacke 	ATF_REQUIRE(la != NULL);
48c1fbb54fSLutz Donnerhacke 	LibAliasSetAddress(la, masq);
49c1fbb54fSLutz Donnerhacke 	LibAliasSetMode(la, 0, ~0);
50c1fbb54fSLutz Donnerhacke 
51f1462ab0SLutz Donnerhacke 	pip = ip_packet(254, 64);
52f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv1, ext, masq);
53f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv2, ext, masq);
54f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv3, ext, masq);
55f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, cgn,  ext, masq);
56f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, pub,  ext, masq);
57c1fbb54fSLutz Donnerhacke 
58c1fbb54fSLutz Donnerhacke 	free(pip);
59c1fbb54fSLutz Donnerhacke 	LibAliasUninit(la);
60c1fbb54fSLutz Donnerhacke }
61c1fbb54fSLutz Donnerhacke 
62c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(2_unregistered);
63c1fbb54fSLutz Donnerhacke ATF_TC_BODY(2_unregistered, dummy)
64c1fbb54fSLutz Donnerhacke {
65c1fbb54fSLutz Donnerhacke 	struct libalias *la = LibAliasInit(NULL);
66c1fbb54fSLutz Donnerhacke 	struct ip *pip;
67c1fbb54fSLutz Donnerhacke 
68c1fbb54fSLutz Donnerhacke 	ATF_REQUIRE(la != NULL);
69c1fbb54fSLutz Donnerhacke 	LibAliasSetAddress(la, masq);
70c1fbb54fSLutz Donnerhacke 	LibAliasSetMode(la, PKT_ALIAS_UNREGISTERED_ONLY, ~0);
71c1fbb54fSLutz Donnerhacke 
72f1462ab0SLutz Donnerhacke 	pip = ip_packet(254, 64);
73f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv1, ext, masq);
74f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv2, ext, masq);
75f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv3, ext, masq);
76f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, cgn,  ext, cgn);
77f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, pub,  ext, pub);
78c1fbb54fSLutz Donnerhacke 
79c1fbb54fSLutz Donnerhacke 	/*
80c1fbb54fSLutz Donnerhacke 	 * State is only for new connections
81c1fbb54fSLutz Donnerhacke 	 * Because they are now active,
82c1fbb54fSLutz Donnerhacke 	 * the mode setting should be ignored
83c1fbb54fSLutz Donnerhacke 	 */
84c1fbb54fSLutz Donnerhacke 	LibAliasSetMode(la, 0, PKT_ALIAS_UNREGISTERED_ONLY);
85f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv1, ext, masq);
86f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv2, ext, masq);
87f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv3, ext, masq);
88f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, cgn,  ext, cgn);
89f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, pub,  ext, pub);
90c1fbb54fSLutz Donnerhacke 
91c1fbb54fSLutz Donnerhacke 	free(pip);
92c1fbb54fSLutz Donnerhacke 	LibAliasUninit(la);
93c1fbb54fSLutz Donnerhacke }
94c1fbb54fSLutz Donnerhacke 
95c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(3_cgn);
96c1fbb54fSLutz Donnerhacke ATF_TC_BODY(3_cgn, dummy)
97c1fbb54fSLutz Donnerhacke {
98c1fbb54fSLutz Donnerhacke 	struct libalias *la = LibAliasInit(NULL);
99c1fbb54fSLutz Donnerhacke 	struct ip *pip;
100c1fbb54fSLutz Donnerhacke 
101c1fbb54fSLutz Donnerhacke 	ATF_REQUIRE(la != NULL);
102c1fbb54fSLutz Donnerhacke 	LibAliasSetAddress(la, masq);
103c1fbb54fSLutz Donnerhacke 	LibAliasSetMode(la, PKT_ALIAS_UNREGISTERED_CGN, ~0);
104c1fbb54fSLutz Donnerhacke 
105f1462ab0SLutz Donnerhacke 	pip = ip_packet(254, 64);
106f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv1, ext, masq);
107f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv2, ext, masq);
108f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv3, ext, masq);
109f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, cgn,  ext, masq);
110f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, pub,  ext, pub);
111c1fbb54fSLutz Donnerhacke 
112c1fbb54fSLutz Donnerhacke 	/*
113c1fbb54fSLutz Donnerhacke 	 * State is only for new connections
114c1fbb54fSLutz Donnerhacke 	 * Because they are now active,
115c1fbb54fSLutz Donnerhacke 	 * the mode setting should be ignored
116c1fbb54fSLutz Donnerhacke 	 */
117c1fbb54fSLutz Donnerhacke 	LibAliasSetMode(la, 0, PKT_ALIAS_UNREGISTERED_CGN);
118f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv1, ext, masq);
119f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv2, ext, masq);
120f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, prv3, ext, masq);
121f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, cgn,  ext, masq);
122f1462ab0SLutz Donnerhacke 	NAT_CHECK(pip, pub,  ext, pub);
123c1fbb54fSLutz Donnerhacke 
124c1fbb54fSLutz Donnerhacke 	free(pip);
125c1fbb54fSLutz Donnerhacke 	LibAliasUninit(la);
126c1fbb54fSLutz Donnerhacke }
127c1fbb54fSLutz Donnerhacke 
128c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(4_udp);
129c1fbb54fSLutz Donnerhacke ATF_TC_BODY(4_udp, dummy)
130c1fbb54fSLutz Donnerhacke {
131c1fbb54fSLutz Donnerhacke 	struct libalias *la = LibAliasInit(NULL);
132c1fbb54fSLutz Donnerhacke 	struct ip  *po, *pi;
133c1fbb54fSLutz Donnerhacke 	struct udphdr *ui, *uo;
134c1fbb54fSLutz Donnerhacke 	uint16_t sport = 0x1234;
135c1fbb54fSLutz Donnerhacke 	uint16_t dport = 0x5678;
136c1fbb54fSLutz Donnerhacke 	uint16_t aport;
137c1fbb54fSLutz Donnerhacke 
138c1fbb54fSLutz Donnerhacke 	ATF_REQUIRE(la != NULL);
139c1fbb54fSLutz Donnerhacke 	LibAliasSetAddress(la, masq);
140c1fbb54fSLutz Donnerhacke 	LibAliasSetMode(la, 0, ~0);
141c1fbb54fSLutz Donnerhacke 
142c1fbb54fSLutz Donnerhacke 	/* Query from prv1 */
143f1462ab0SLutz Donnerhacke 	po = ip_packet(0, 64);
144f1462ab0SLutz Donnerhacke 	UDP_NAT_CHECK(po, uo, prv1, sport, ext, dport, masq);
145c1fbb54fSLutz Donnerhacke 	aport = ntohs(uo->uh_sport);
146c1fbb54fSLutz Donnerhacke 	/* should use a different external port */
147c1fbb54fSLutz Donnerhacke 	ATF_CHECK(aport != sport);
148c1fbb54fSLutz Donnerhacke 
149c1fbb54fSLutz Donnerhacke 	/* Response */
150f1462ab0SLutz Donnerhacke 	pi = ip_packet(0, 64);
151f1462ab0SLutz Donnerhacke 	UDP_UNNAT_CHECK(pi, ui, ext, dport, masq, aport, prv1, sport);
152c1fbb54fSLutz Donnerhacke 
153c1fbb54fSLutz Donnerhacke 	/* Query from different source with same ports */
154f1462ab0SLutz Donnerhacke 	UDP_NAT_CHECK(po, uo, prv2, sport, ext, dport, masq);
155c1fbb54fSLutz Donnerhacke 	/* should use a different external port */
156c1fbb54fSLutz Donnerhacke 	ATF_CHECK(uo->uh_sport != htons(aport));
157c1fbb54fSLutz Donnerhacke 
158c1fbb54fSLutz Donnerhacke 	/* Response to prv2 */
159c1fbb54fSLutz Donnerhacke 	ui->uh_dport = uo->uh_sport;
160f1462ab0SLutz Donnerhacke 	UDP_UNNAT_CHECK(pi, ui, ext, dport, masq, htons(uo->uh_sport), prv2, sport);
161c1fbb54fSLutz Donnerhacke 
162c1fbb54fSLutz Donnerhacke 	/* Response to prv1 again */
163f1462ab0SLutz Donnerhacke 	UDP_UNNAT_CHECK(pi, ui, ext, dport, masq, aport, prv1, sport);
164c1fbb54fSLutz Donnerhacke 
165c1fbb54fSLutz Donnerhacke 	free(pi);
166c1fbb54fSLutz Donnerhacke 	free(po);
167c1fbb54fSLutz Donnerhacke 	LibAliasUninit(la);
168c1fbb54fSLutz Donnerhacke }
169c1fbb54fSLutz Donnerhacke 
170c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(5_sameport);
171c1fbb54fSLutz Donnerhacke ATF_TC_BODY(5_sameport, dummy)
172c1fbb54fSLutz Donnerhacke {
173c1fbb54fSLutz Donnerhacke 	struct libalias *la = LibAliasInit(NULL);
174c1fbb54fSLutz Donnerhacke 	struct ip  *p;
175c1fbb54fSLutz Donnerhacke 	struct udphdr *u;
176c1fbb54fSLutz Donnerhacke 	uint16_t sport = 0x1234;
177c1fbb54fSLutz Donnerhacke 	uint16_t dport = 0x5678;
178c1fbb54fSLutz Donnerhacke 	uint16_t aport;
179c1fbb54fSLutz Donnerhacke 
180c1fbb54fSLutz Donnerhacke 	ATF_REQUIRE(la != NULL);
181c1fbb54fSLutz Donnerhacke 	LibAliasSetAddress(la, masq);
182c1fbb54fSLutz Donnerhacke 	LibAliasSetMode(la, PKT_ALIAS_SAME_PORTS, ~0);
183c1fbb54fSLutz Donnerhacke 
184c1fbb54fSLutz Donnerhacke 	/* Query from prv1 */
185f1462ab0SLutz Donnerhacke 	p = ip_packet(0, 64);
186f1462ab0SLutz Donnerhacke 	UDP_NAT_CHECK(p, u, prv1, sport, ext, dport, masq);
187c1fbb54fSLutz Donnerhacke 	aport = ntohs(u->uh_sport);
188c1fbb54fSLutz Donnerhacke 	/* should use the same external port */
189c1fbb54fSLutz Donnerhacke 	ATF_CHECK(aport == sport);
190c1fbb54fSLutz Donnerhacke 
191c1fbb54fSLutz Donnerhacke 	/* Query from different source with same ports */
192f1462ab0SLutz Donnerhacke 	UDP_NAT_CHECK(p, u, prv2, sport, ext, dport, masq);
193c1fbb54fSLutz Donnerhacke 	/* should use a different external port */
194c1fbb54fSLutz Donnerhacke 	ATF_CHECK(u->uh_sport != htons(aport));
195c1fbb54fSLutz Donnerhacke 
196c1fbb54fSLutz Donnerhacke 	free(p);
197c1fbb54fSLutz Donnerhacke 	LibAliasUninit(la);
198c1fbb54fSLutz Donnerhacke }
199c1fbb54fSLutz Donnerhacke 
200c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(6_cleartable);
201c1fbb54fSLutz Donnerhacke ATF_TC_BODY(6_cleartable, dummy)
202c1fbb54fSLutz Donnerhacke {
203c1fbb54fSLutz Donnerhacke 	struct libalias *la = LibAliasInit(NULL);
204c1fbb54fSLutz Donnerhacke 	struct ip  *po, *pi;
205c555dcddSJohn Baldwin 	struct udphdr *ui __unused, *uo;
206c1fbb54fSLutz Donnerhacke 	uint16_t sport = 0x1234;
207c1fbb54fSLutz Donnerhacke 	uint16_t dport = 0x5678;
208c1fbb54fSLutz Donnerhacke 	uint16_t aport;
209c1fbb54fSLutz Donnerhacke 
210c1fbb54fSLutz Donnerhacke 	ATF_REQUIRE(la != NULL);
211c1fbb54fSLutz Donnerhacke 	LibAliasSetAddress(la, masq);
212c1fbb54fSLutz Donnerhacke 	LibAliasSetMode(la, PKT_ALIAS_RESET_ON_ADDR_CHANGE, ~0);
213c1fbb54fSLutz Donnerhacke 	LibAliasSetMode(la, PKT_ALIAS_SAME_PORTS, PKT_ALIAS_SAME_PORTS);
214c1fbb54fSLutz Donnerhacke 	LibAliasSetMode(la, PKT_ALIAS_DENY_INCOMING, PKT_ALIAS_DENY_INCOMING);
215c1fbb54fSLutz Donnerhacke 
216c1fbb54fSLutz Donnerhacke 	/* Query from prv1 */
217f1462ab0SLutz Donnerhacke 	po = ip_packet(0, 64);
218f1462ab0SLutz Donnerhacke 	UDP_NAT_CHECK(po, uo, prv1, sport, ext, dport, masq);
219c1fbb54fSLutz Donnerhacke 	aport = ntohs(uo->uh_sport);
220c1fbb54fSLutz Donnerhacke 	/* should use the same external port */
221c1fbb54fSLutz Donnerhacke 	ATF_CHECK(aport == sport);
222c1fbb54fSLutz Donnerhacke 
223c1fbb54fSLutz Donnerhacke 	/* Response */
224f1462ab0SLutz Donnerhacke 	pi = ip_packet(0, 64);
225f1462ab0SLutz Donnerhacke 	UDP_UNNAT_CHECK(po, uo, ext, dport, masq, aport, prv1, sport);
226c1fbb54fSLutz Donnerhacke 
227c1fbb54fSLutz Donnerhacke 	/* clear table by keeping the address */
228c1fbb54fSLutz Donnerhacke 	LibAliasSetAddress(la, ext);
229c1fbb54fSLutz Donnerhacke 	LibAliasSetAddress(la, masq);
230c1fbb54fSLutz Donnerhacke 
231c1fbb54fSLutz Donnerhacke 	/* Response to prv1 again -> DENY_INCOMING */
232f1462ab0SLutz Donnerhacke 	UDP_UNNAT_FAIL(pi, ui, ext, dport, masq, aport);
233c1fbb54fSLutz Donnerhacke 
234c1fbb54fSLutz Donnerhacke 	/* Query from different source with same ports */
235f1462ab0SLutz Donnerhacke 	UDP_NAT_CHECK(po, uo, prv2, sport, ext, dport, masq);
236c1fbb54fSLutz Donnerhacke 	/* should use the same external port, because it's free */
237c1fbb54fSLutz Donnerhacke 	ATF_CHECK(uo->uh_sport == htons(aport));
238c1fbb54fSLutz Donnerhacke 
239c1fbb54fSLutz Donnerhacke 	/* Response to prv2 */
240f1462ab0SLutz Donnerhacke 	UDP_UNNAT_CHECK(po, uo, ext, dport, masq, htons(uo->uh_sport), prv2, sport);
241c1fbb54fSLutz Donnerhacke 
242c1fbb54fSLutz Donnerhacke 	free(pi);
243c1fbb54fSLutz Donnerhacke 	free(po);
244c1fbb54fSLutz Donnerhacke 	LibAliasUninit(la);
245c1fbb54fSLutz Donnerhacke }
246c1fbb54fSLutz Donnerhacke 
247c1fbb54fSLutz Donnerhacke ATF_TC_WITHOUT_HEAD(7_stress);
248c1fbb54fSLutz Donnerhacke ATF_TC_BODY(7_stress, dummy)
249c1fbb54fSLutz Donnerhacke {
250c1fbb54fSLutz Donnerhacke 	struct libalias *la = LibAliasInit(NULL);
251c1fbb54fSLutz Donnerhacke 	struct ip *p;
252c1fbb54fSLutz Donnerhacke 	struct udphdr *u;
253c1fbb54fSLutz Donnerhacke 	struct {
254c1fbb54fSLutz Donnerhacke 		struct in_addr src, dst;
255c1fbb54fSLutz Donnerhacke 		uint16_t sport, dport, aport;
256c1fbb54fSLutz Donnerhacke 	} *batch;
257a660948bSLutz Donnerhacke 	size_t const batch_size = 1200;
258c1fbb54fSLutz Donnerhacke 	size_t const rounds = 25;
259c1fbb54fSLutz Donnerhacke 	size_t i, j;
260c1fbb54fSLutz Donnerhacke 
261c1fbb54fSLutz Donnerhacke 	ATF_REQUIRE(la != NULL);
262c1fbb54fSLutz Donnerhacke 	LibAliasSetAddress(la, masq);
263c1fbb54fSLutz Donnerhacke 
264f1462ab0SLutz Donnerhacke 	p = ip_packet(0, 64);
265c1fbb54fSLutz Donnerhacke 
266c1fbb54fSLutz Donnerhacke 	batch = calloc(batch_size, sizeof(*batch));
267c1fbb54fSLutz Donnerhacke 	ATF_REQUIRE(batch != NULL);
268c1fbb54fSLutz Donnerhacke 	for (j = 0; j < rounds; j++) {
269c1fbb54fSLutz Donnerhacke 		for (i = 0; i < batch_size; i++) {
270c1fbb54fSLutz Donnerhacke 			struct in_addr s, d;
271c1fbb54fSLutz Donnerhacke 			switch (i&3) {
272c1fbb54fSLutz Donnerhacke 			case 0: s = prv1; d = ext; break;
273c1fbb54fSLutz Donnerhacke 			case 1: s = prv2; d = pub; break;
274c1fbb54fSLutz Donnerhacke 			case 2: s = prv3; d = ext; break;
275c1fbb54fSLutz Donnerhacke 			case 3: s = cgn;  d = pub; break;
276c1fbb54fSLutz Donnerhacke 			}
277c1fbb54fSLutz Donnerhacke 			s.s_addr &= htonl(0xffff0000);
278c1fbb54fSLutz Donnerhacke 			d.s_addr &= htonl(0xffff0000);
279c1fbb54fSLutz Donnerhacke 			batch[i].src.s_addr = s.s_addr | htonl(rand_range(0, 0xffff));
280c1fbb54fSLutz Donnerhacke 			batch[i].dst.s_addr = d.s_addr | htonl(rand_range(0, 0xffff));
281c1fbb54fSLutz Donnerhacke 			batch[i].sport = rand_range(1000, 60000);
282c1fbb54fSLutz Donnerhacke 			batch[i].dport = rand_range(1000, 60000);
283c1fbb54fSLutz Donnerhacke 		}
284c1fbb54fSLutz Donnerhacke 
285c1fbb54fSLutz Donnerhacke 		for (i = 0; i < batch_size; i++) {
286f1462ab0SLutz Donnerhacke 			UDP_NAT_CHECK(p, u,
287f1462ab0SLutz Donnerhacke 			    batch[i].src, batch[i].sport,
288f1462ab0SLutz Donnerhacke 			    batch[i].dst, batch[i].dport,
289f1462ab0SLutz Donnerhacke 			    masq);
290c1fbb54fSLutz Donnerhacke 			batch[i].aport = htons(u->uh_sport);
291c1fbb54fSLutz Donnerhacke 		}
292c1fbb54fSLutz Donnerhacke 
293c1fbb54fSLutz Donnerhacke 		qsort(batch, batch_size, sizeof(*batch), randcmp);
294c1fbb54fSLutz Donnerhacke 
295c1fbb54fSLutz Donnerhacke 		for (i = 0; i < batch_size; i++) {
296f1462ab0SLutz Donnerhacke 			UDP_UNNAT_CHECK(p, u,
297f1462ab0SLutz Donnerhacke 			    batch[i].dst,  batch[i].dport,
298f1462ab0SLutz Donnerhacke 			    masq, batch[i].aport,
299f1462ab0SLutz Donnerhacke 			    batch[i].src, batch[i].sport);
300c1fbb54fSLutz Donnerhacke 		}
301c1fbb54fSLutz Donnerhacke 	}
302c1fbb54fSLutz Donnerhacke 
303c1fbb54fSLutz Donnerhacke 	free(batch);
304c1fbb54fSLutz Donnerhacke 	free(p);
305c1fbb54fSLutz Donnerhacke 	LibAliasUninit(la);
306c1fbb54fSLutz Donnerhacke }
307c1fbb54fSLutz Donnerhacke 
3082c733b50SLutz Donnerhacke ATF_TC_WITHOUT_HEAD(8_portrange);
3092c733b50SLutz Donnerhacke ATF_TC_BODY(8_portrange, dummy)
3102c733b50SLutz Donnerhacke {
3112c733b50SLutz Donnerhacke 	struct libalias *la = LibAliasInit(NULL);
3122c733b50SLutz Donnerhacke 	struct ip  *po;
3132c733b50SLutz Donnerhacke 	struct udphdr *uo;
3142c733b50SLutz Donnerhacke 	uint16_t sport = 0x1234;
3152c733b50SLutz Donnerhacke 	uint16_t dport = 0x5678;
3162c733b50SLutz Donnerhacke 	uint16_t aport;
3172c733b50SLutz Donnerhacke 
3182c733b50SLutz Donnerhacke 	ATF_REQUIRE(la != NULL);
3192c733b50SLutz Donnerhacke 	LibAliasSetAddress(la, masq);
3202c733b50SLutz Donnerhacke 	LibAliasSetMode(la, 0, ~0);
3212c733b50SLutz Donnerhacke 	po = ip_packet(0, 64);
3222c733b50SLutz Donnerhacke 
3232c733b50SLutz Donnerhacke 	LibAliasSetAliasPortRange(la, 0, 0); /* reinit like ipfw */
3242c733b50SLutz Donnerhacke 	UDP_NAT_CHECK(po, uo, prv1, sport, ext, dport, masq);
3252c733b50SLutz Donnerhacke 	aport = ntohs(uo->uh_sport);
3262c733b50SLutz Donnerhacke 	ATF_CHECK(aport >= 0x8000);
3272c733b50SLutz Donnerhacke 
3282c733b50SLutz Donnerhacke 	/* Different larger range */
3292c733b50SLutz Donnerhacke 	LibAliasSetAliasPortRange(la, 2000, 3000);
3302c733b50SLutz Donnerhacke 	dport++;
3312c733b50SLutz Donnerhacke 	UDP_NAT_CHECK(po, uo, prv1, sport, ext, dport, masq);
3322c733b50SLutz Donnerhacke 	aport = ntohs(uo->uh_sport);
3332c733b50SLutz Donnerhacke 	ATF_CHECK(aport >= 2000 && aport < 3000);
3342c733b50SLutz Donnerhacke 
3352c733b50SLutz Donnerhacke 	/* Different small range (contains two ports) */
3362c733b50SLutz Donnerhacke 	LibAliasSetAliasPortRange(la, 4000, 4001);
3372c733b50SLutz Donnerhacke 	dport++;
3382c733b50SLutz Donnerhacke 	UDP_NAT_CHECK(po, uo, prv1, sport, ext, dport, masq);
3392c733b50SLutz Donnerhacke 	aport = ntohs(uo->uh_sport);
3402c733b50SLutz Donnerhacke 	ATF_CHECK(aport >= 4000 && aport <= 4001);
3412c733b50SLutz Donnerhacke 
3422c733b50SLutz Donnerhacke 	sport++;
3432c733b50SLutz Donnerhacke 	UDP_NAT_CHECK(po, uo, prv1, sport, ext, dport, masq);
3442c733b50SLutz Donnerhacke 	aport = ntohs(uo->uh_sport);
3452c733b50SLutz Donnerhacke 	ATF_CHECK(aport >= 4000 && aport <= 4001);
3462c733b50SLutz Donnerhacke 
3472c733b50SLutz Donnerhacke 	/* Third port not available in the range */
3482c733b50SLutz Donnerhacke 	sport++;
3492c733b50SLutz Donnerhacke 	UDP_NAT_FAIL(po, uo, prv1, sport, ext, dport);
3502c733b50SLutz Donnerhacke 
3512c733b50SLutz Donnerhacke 	/* Back to normal */
3522c733b50SLutz Donnerhacke 	LibAliasSetAliasPortRange(la, 0, 0);
3532c733b50SLutz Donnerhacke 	dport++;
3542c733b50SLutz Donnerhacke 	UDP_NAT_CHECK(po, uo, prv1, sport, ext, dport, masq);
3552c733b50SLutz Donnerhacke 	aport = ntohs(uo->uh_sport);
3562c733b50SLutz Donnerhacke 	ATF_CHECK(aport >= 0x8000);
3572c733b50SLutz Donnerhacke 
3582c733b50SLutz Donnerhacke 	free(po);
3592c733b50SLutz Donnerhacke 	LibAliasUninit(la);
3602c733b50SLutz Donnerhacke }
3612c733b50SLutz Donnerhacke 
ATF_TP_ADD_TCS(natout)362c1fbb54fSLutz Donnerhacke ATF_TP_ADD_TCS(natout)
363c1fbb54fSLutz Donnerhacke {
364c1fbb54fSLutz Donnerhacke 	/* Use "dd if=/dev/random bs=2 count=1 | od -x" to reproduce */
365c1fbb54fSLutz Donnerhacke 	srand(0x0b61);
366c1fbb54fSLutz Donnerhacke 
367c1fbb54fSLutz Donnerhacke 	ATF_TP_ADD_TC(natout, 1_simplemasq);
368c1fbb54fSLutz Donnerhacke 	ATF_TP_ADD_TC(natout, 2_unregistered);
369c1fbb54fSLutz Donnerhacke 	ATF_TP_ADD_TC(natout, 3_cgn);
370c1fbb54fSLutz Donnerhacke 	ATF_TP_ADD_TC(natout, 4_udp);
371c1fbb54fSLutz Donnerhacke 	ATF_TP_ADD_TC(natout, 5_sameport);
372c1fbb54fSLutz Donnerhacke 	ATF_TP_ADD_TC(natout, 6_cleartable);
373c1fbb54fSLutz Donnerhacke 	ATF_TP_ADD_TC(natout, 7_stress);
3742c733b50SLutz Donnerhacke 	ATF_TP_ADD_TC(natout, 8_portrange);
375c1fbb54fSLutz Donnerhacke 
376c1fbb54fSLutz Donnerhacke 	return atf_no_error();
377c1fbb54fSLutz Donnerhacke }
378