xref: /freebsd/tests/sys/netinet/libalias/3_natin.c (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright 2021 Lutz Donnerhacke
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above
13  *    copyright notice, this list of conditions and the following
14  *    disclaimer in the documentation and/or other materials provided
15  *    with the distribution.
16  * 3. Neither the name of the copyright holder nor the names of its
17  *    contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
21  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
22  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
31  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 #include <atf-c.h>
35 #include <alias.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 
39 #include "util.h"
40 
41 ATF_TC_WITHOUT_HEAD(1_portforward);
42 ATF_TC_BODY(1_portforward, dummy)
43 {
44 	struct libalias *la = LibAliasInit(NULL);
45 	struct alias_link *pf1, *pf2, *pf3, *pf4;
46 	struct ip *p;
47 	struct udphdr *u;
48 
49 	ATF_REQUIRE(la != NULL);
50 	LibAliasSetAddress(la, masq);
51 	LibAliasSetMode(la, PKT_ALIAS_RESET_ON_ADDR_CHANGE, ~0);
52 	LibAliasSetMode(la, PKT_ALIAS_DENY_INCOMING, PKT_ALIAS_DENY_INCOMING);
53 
54 	/*
55 	 * Fully specified
56 	 */
57 	pf1 = LibAliasRedirectPort(la, prv1, ntohs(0x1234), ext, ntohs(0x5678), masq, ntohs(0xabcd), IPPROTO_UDP);
58 	ATF_REQUIRE(pf1 != NULL);
59 
60 	p = ip_packet(0, 64);
61 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv1, 0x1234);
62 	/* try again */
63 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv1, 0x1234);
64 	/* different source */
65 	UDP_UNNAT_FAIL(p, u, pub, 0x5678, masq, 0xabcd);
66 	UDP_UNNAT_FAIL(p, u, ext, 0xdead, masq, 0xabcd);
67 
68 	/* clear table by keeping the address */
69 	LibAliasSetAddress(la, ext);
70 	LibAliasSetAddress(la, masq);
71 
72 	/* delete and try again */
73 	LibAliasRedirectDelete(la, pf1);
74 	UDP_UNNAT_FAIL(p, u, ext, 0x5678, masq, 0xabcd);
75 
76 	/*
77 	 * Any external port
78 	 */
79 	pf2 = LibAliasRedirectPort(la, prv2, ntohs(0x1234), ext, ntohs(0), masq, ntohs(0xabcd), IPPROTO_UDP);
80 	ATF_REQUIRE(pf2 != NULL);
81 
82 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv2, 0x1234);
83 	/* try again */
84 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv2, 0x1234);
85 	/* different source */
86 	UDP_UNNAT_FAIL(p, u, pub, 0x5678, masq, 0xabcd);
87 	UDP_UNNAT_CHECK(p, u, ext, 0xdead, masq, 0xabcd, prv2, 0x1234);
88 
89 	/* clear table by keeping the address */
90 	LibAliasSetAddress(la, ext);
91 	LibAliasSetAddress(la, masq);
92 
93 	/* delete and try again */
94 	LibAliasRedirectDelete(la, pf2);
95 	UDP_UNNAT_FAIL(p, u, ext, 0x5678, masq, 0xabcd);
96 
97 	/*
98 	 * Any external host
99 	 */
100 	pf3 = LibAliasRedirectPort(la, prv3, ntohs(0x1234), ANY_ADDR, ntohs(0x5678), masq, ntohs(0xabcd), IPPROTO_UDP);
101 	ATF_REQUIRE(pf3 != NULL);
102 
103 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv3, 0x1234);
104 	/* try again */
105 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv3, 0x1234);
106 	/* different source */
107 	UDP_UNNAT_CHECK(p, u, pub, 0x5678, masq, 0xabcd, prv3, 0x1234);
108 	UDP_UNNAT_FAIL(p, u, ext, 0xdead, masq, 0xabcd);
109 
110 	/* clear table by keeping the address */
111 	LibAliasSetAddress(la, ext);
112 	LibAliasSetAddress(la, masq);
113 
114 	/* delete and try again */
115 	LibAliasRedirectDelete(la, pf3);
116 	UDP_UNNAT_FAIL(p, u, ext, 0x5678, masq, 0xabcd);
117 
118 	/*
119 	 * Any external host, any port
120 	 */
121 	pf4 = LibAliasRedirectPort(la, cgn, ntohs(0x1234), ANY_ADDR, ntohs(0), masq, ntohs(0xabcd), IPPROTO_UDP);
122 	ATF_REQUIRE(pf4 != NULL);
123 
124 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, cgn, 0x1234);
125 	/* try again */
126 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, cgn, 0x1234);
127 	/* different source */
128 	UDP_UNNAT_CHECK(p, u, pub, 0x5678, masq, 0xabcd, cgn, 0x1234);
129 	UDP_UNNAT_CHECK(p, u, ext, 0xdead, masq, 0xabcd, cgn, 0x1234);
130 
131 	/* clear table by keeping the address */
132 	LibAliasSetAddress(la, ext);
133 	LibAliasSetAddress(la, masq);
134 
135 	/* delete and try again */
136 	LibAliasRedirectDelete(la, pf4);
137 	UDP_UNNAT_FAIL(p, u, ext, 0x5678, masq, 0xabcd);
138 
139 	free(p);
140 	LibAliasUninit(la);
141 }
142 
143 ATF_TC_WITHOUT_HEAD(2_portoverlap);
144 ATF_TC_BODY(2_portoverlap, dummy)
145 {
146 	struct libalias *la = LibAliasInit(NULL);
147 	struct alias_link *pf1, *pf2, *pf3, *pf4;
148 	struct ip *p;
149 	struct udphdr *u;
150 
151 	ATF_REQUIRE(la != NULL);
152 	LibAliasSetAddress(la, masq);
153 	LibAliasSetMode(la, PKT_ALIAS_RESET_ON_ADDR_CHANGE, ~0);
154 	LibAliasSetMode(la, PKT_ALIAS_DENY_INCOMING, PKT_ALIAS_DENY_INCOMING);
155 
156 	/*
157 	 * Fully specified
158 	 */
159 	pf1 = LibAliasRedirectPort(la, prv2, ntohs(0x1234), ext, ntohs(0x5678), masq, ntohs(0xabcd), IPPROTO_UDP);
160 	ATF_REQUIRE(pf1 != NULL);
161 
162 	p = ip_packet(0, 64);
163 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv2, 0x1234);
164 
165 	/* clear table by keeping the address */
166 	LibAliasSetAddress(la, ext);
167 	LibAliasSetAddress(la, masq);
168 
169 	/*
170 	 * Fully specified (override)
171 	 */
172 	pf1 = LibAliasRedirectPort(la, prv1, ntohs(0x1234), ext, ntohs(0x5678), masq, ntohs(0xabcd), IPPROTO_UDP);
173 	ATF_REQUIRE(pf1 != NULL);
174 
175 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv1, 0x1234);
176 
177 	/* clear table by keeping the address */
178 	LibAliasSetAddress(la, ext);
179 	LibAliasSetAddress(la, masq);
180 
181 	/*
182 	 * Any external port
183 	 */
184 	pf2 = LibAliasRedirectPort(la, prv2, ntohs(0x1234), ext, ntohs(0), masq, ntohs(0xabcd), IPPROTO_UDP);
185 	ATF_REQUIRE(pf2 != NULL);
186 
187 	UDP_UNNAT_CHECK(p, u, ext, 0x5679, masq, 0xabcd, prv2, 0x1234);
188 	/* more specific rule wins */
189 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv1, 0x1234);
190 
191 	/* clear table by keeping the address */
192 	LibAliasSetAddress(la, ext);
193 	LibAliasSetAddress(la, masq);
194 
195 	/*
196 	 * Any external host
197 	 */
198 	pf3 = LibAliasRedirectPort(la, prv3, ntohs(0x1234), ANY_ADDR, ntohs(0x5678), masq, ntohs(0xabcd), IPPROTO_UDP);
199 	ATF_REQUIRE(pf3 != NULL);
200 
201 	UDP_UNNAT_CHECK(p, u, pub, 0x5678, masq, 0xabcd, prv3, 0x1234);
202 	/* more specific rule wins */
203 	UDP_UNNAT_CHECK(p, u, ext, 0x5679, masq, 0xabcd, prv2, 0x1234);
204 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv1, 0x1234);
205 
206 	/* clear table by keeping the address */
207 	LibAliasSetAddress(la, ext);
208 	LibAliasSetAddress(la, masq);
209 
210 	/*
211 	 * Any external host, any port
212 	 */
213 	pf4 = LibAliasRedirectPort(la, cgn, ntohs(0x1234), ANY_ADDR, ntohs(0), masq, ntohs(0xabcd), IPPROTO_UDP);
214 	ATF_REQUIRE(pf4 != NULL);
215 
216 	UDP_UNNAT_CHECK(p, u, prv1, 0x5679, masq, 0xabcd, cgn, 0x1234);
217 	/* more specific rule wins */
218 	UDP_UNNAT_CHECK(p, u, pub, 0x5678, masq, 0xabcd, prv3, 0x1234);
219 	UDP_UNNAT_CHECK(p, u, ext, 0x5679, masq, 0xabcd, prv2, 0x1234);
220 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv1, 0x1234);
221 
222 	free(p);
223 	LibAliasUninit(la);
224 }
225 
226 ATF_TC_WITHOUT_HEAD(3_redirectany);
227 ATF_TC_BODY(3_redirectany, dummy)
228 {
229 	struct libalias *la = LibAliasInit(NULL);
230 	struct alias_link *pf;
231 	struct ip *p;
232 	struct udphdr *u;
233 
234 	ATF_REQUIRE(la != NULL);
235 	LibAliasSetMode(la, PKT_ALIAS_DENY_INCOMING, ~0);
236 	p = ip_packet(0, 64);
237 
238 	pf = LibAliasRedirectPort(la, prv1, ntohs(0x1234), ANY_ADDR, 0, ANY_ADDR, ntohs(0xabcd), IPPROTO_UDP);
239 	ATF_REQUIRE(pf != NULL);
240 
241 	LibAliasSetAddress(la, masq);
242 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv1, 0x1234);
243 	UDP_UNNAT_FAIL(p, u, pub, 0x5678, pub, 0xabcd);
244 
245 	LibAliasSetAddress(la, pub);
246 	UDP_UNNAT_CHECK(p, u, pub, 0x5679, pub, 0xabcd, prv1, 0x1234);
247 	UDP_UNNAT_FAIL(p, u, ext, 0x5679, masq, 0xabcd);
248 
249 	free(p);
250 	LibAliasUninit(la);
251 }
252 
253 ATF_TC_WITHOUT_HEAD(4_redirectaddr);
254 ATF_TC_BODY(4_redirectaddr, dummy)
255 {
256 	struct libalias *la = LibAliasInit(NULL);
257 	struct alias_link *pf1, *pf2;
258 	struct ip *p;
259 
260 	ATF_REQUIRE(la != NULL);
261 	LibAliasSetAddress(la, masq);
262 	pf1 = LibAliasRedirectAddr(la, prv1, pub);
263 	ATF_REQUIRE(pf1 != NULL);
264 
265 	p = ip_packet(254, 64);
266 	UNNAT_CHECK(p, ext, pub, prv1);
267 	UNNAT_CHECK(p, ext, masq, masq);
268 
269 	pf2 = LibAliasRedirectAddr(la, prv2, pub);
270 	ATF_REQUIRE(pf2 != NULL);
271 	UNNAT_CHECK(p, ext, pub, prv1);
272 	p->ip_p = 253;		       /* new flows */
273 	UNNAT_CHECK(p, ext, pub, prv2);
274 	UNNAT_CHECK(p, ext, masq, masq);
275 
276 	p->ip_p = 252;		       /* new flows */
277 	NAT_CHECK(p, prv1, ext, pub);
278 	NAT_CHECK(p, prv2, ext, pub);
279 	NAT_CHECK(p, prv3, ext, masq);
280 
281 	LibAliasSetMode(la, PKT_ALIAS_DENY_INCOMING, ~0);
282 	p->ip_p = 251;		       /* new flows */
283 	UNNAT_FAIL(p, ext, pub);
284 	UNNAT_FAIL(p, ext, masq);
285 
286 	/* unhide older version */
287 	LibAliasRedirectDelete(la, pf2);
288 	LibAliasSetMode(la, 0, ~0);
289 	p->ip_p = 250;		       /* new flows */
290 	UNNAT_CHECK(p, ext, pub, prv1);
291 
292 	p->ip_p = 249;		       /* new flows */
293 	NAT_CHECK(p, prv1, ext, pub);
294 	NAT_CHECK(p, prv2, ext, masq);
295 	NAT_CHECK(p, prv3, ext, masq);
296 
297 	free(p);
298 	LibAliasUninit(la);
299 }
300 
301 ATF_TC_WITHOUT_HEAD(5_lsnat);
302 ATF_TC_BODY(5_lsnat, dummy)
303 {
304 	struct libalias *la = LibAliasInit(NULL);
305 	struct alias_link *pf;
306 	struct ip *p;
307 	struct udphdr *u;
308 
309 	ATF_REQUIRE(la != NULL);
310 	LibAliasSetMode(la, 0, ~0);
311 	p = ip_packet(0, 64);
312 
313 	pf = LibAliasRedirectPort(la, cgn, ntohs(0xdead), ANY_ADDR, 0, masq, ntohs(0xabcd), IPPROTO_UDP);
314 	ATF_REQUIRE(pf != NULL);
315 
316 	ATF_REQUIRE(0 == LibAliasAddServer(la, pf, prv1, ntohs(0x1234)));
317 	ATF_REQUIRE(0 == LibAliasAddServer(la, pf, prv2, ntohs(0x2345)));
318 	ATF_REQUIRE(0 == LibAliasAddServer(la, pf, prv3, ntohs(0x3456)));
319 
320 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv3, 0x3456);
321 	UDP_UNNAT_CHECK(p, u, ext, 0x5679, masq, 0xabcd, prv2, 0x2345);
322 	UDP_UNNAT_CHECK(p, u, ext, 0x567a, masq, 0xabcd, prv1, 0x1234);
323 	UDP_UNNAT_CHECK(p, u, ext, 0x567b, masq, 0xabcd, prv3, 0x3456);
324 	UDP_UNNAT_CHECK(p, u, ext, 0x567c, masq, 0xabcd, prv2, 0x2345);
325 	UDP_UNNAT_CHECK(p, u, ext, 0x567d, masq, 0xabcd, prv1, 0x1234);
326 
327 	free(p);
328 	LibAliasUninit(la);
329 }
330 
331 ATF_TC_WITHOUT_HEAD(6_oneshot);
332 ATF_TC_BODY(6_oneshot, dummy)
333 {
334 	struct libalias *la = LibAliasInit(NULL);
335 	struct alias_link *pf;
336 	struct ip *p;
337 	struct udphdr *u;
338 
339 	ATF_REQUIRE(la != NULL);
340 	LibAliasSetMode(la, 0, ~0);
341 	LibAliasSetMode(la, PKT_ALIAS_RESET_ON_ADDR_CHANGE, ~0);
342 	LibAliasSetMode(la, PKT_ALIAS_DENY_INCOMING, PKT_ALIAS_DENY_INCOMING);
343 
344 	pf = LibAliasRedirectPort(la, prv1, ntohs(0x1234), ANY_ADDR, 0, masq, ntohs(0xabcd), IPPROTO_UDP);
345 	ATF_REQUIRE(pf != NULL);
346 	/* only for fully specified links */
347 	ATF_CHECK(-1 == LibAliasRedirectDynamic(la, pf));
348 	LibAliasRedirectDelete(la, pf);
349 
350 	pf = LibAliasRedirectPort(la, prv1, ntohs(0x1234), ext, ntohs(0x5678), masq, ntohs(0xabcd), IPPROTO_UDP);
351 	ATF_REQUIRE(pf != NULL);
352 	ATF_CHECK(0 == LibAliasRedirectDynamic(la, pf));
353 
354 	p = ip_packet(0, 64);
355 	UDP_UNNAT_CHECK(p, u, ext, 0x5678, masq, 0xabcd, prv1, 0x1234);
356 
357 	/* clear table by keeping the address */
358 	LibAliasSetAddress(la, ext);
359 	LibAliasSetAddress(la, masq);
360 
361 	/* does not work anymore */
362 	UDP_UNNAT_FAIL(p, u, ext, 0x5678, masq, 0xabcd);
363 
364 	free(p);
365 	LibAliasUninit(la);
366 }
367 
368 ATF_TP_ADD_TCS(natin)
369 {
370 	/* Use "dd if=/dev/random bs=2 count=1 | od -x" to reproduce */
371 	srand(0xe859);
372 
373 	ATF_TP_ADD_TC(natin, 1_portforward);
374 	ATF_TP_ADD_TC(natin, 2_portoverlap);
375 	ATF_TP_ADD_TC(natin, 3_redirectany);
376 	ATF_TP_ADD_TC(natin, 4_redirectaddr);
377 	ATF_TP_ADD_TC(natin, 5_lsnat);
378 	ATF_TP_ADD_TC(natin, 6_oneshot);
379 
380 	return atf_no_error();
381 }
382