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
ATF_TP_ADD_TCS(natin)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