xref: /freebsd/tests/sys/netinet/libalias/2_natout.c (revision 7b8696bf)
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