VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTNetIPv4.cpp@ 106579

Last change on this file since 106579 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 22.1 KB
Line 
1/* $Id: tstRTNetIPv4.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT Testcase - IPv4.
4 */
5
6/*
7 * Copyright (C) 2008-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/net.h>
42
43#include <iprt/errcore.h>
44#include <iprt/initterm.h>
45#include <iprt/test.h>
46
47
48/*********************************************************************************************************************************
49* Defined Constants And Macros *
50*********************************************************************************************************************************/
51#define CHECKADDR(String, rcExpected, ExpectedAddr) \
52 do { \
53 RTNETADDRIPV4 Addr; \
54 int rc2 = RTNetStrToIPv4Addr(String, &Addr); \
55 if ((rcExpected) && !rc2) \
56 { \
57 RTTestIFailed("at line %d: '%s': expected %Rrc got %Rrc\n", \
58 __LINE__, String, (rcExpected), rc2); \
59 } \
60 else if ( (rcExpected) != rc2 \
61 || ( rc2 == VINF_SUCCESS \
62 && RT_H2N_U32_C(ExpectedAddr) != Addr.u)) \
63 { \
64 RTTestIFailed("at line %d: '%s': expected %Rrc got %Rrc," \
65 " expected address %RTnaipv4 got %RTnaipv4\n", \
66 __LINE__, String, rcExpected, rc2, \
67 RT_H2N_U32_C(ExpectedAddr), Addr.u); \
68 } \
69 } while (0)
70
71#define GOODADDR(String, ExpectedAddr) \
72 CHECKADDR(String, VINF_SUCCESS, ExpectedAddr)
73
74#define BADADDR(String) \
75 CHECKADDR(String, VERR_INVALID_PARAMETER, 0)
76
77
78#define CHECKADDREX(String, Trailer, rcExpected, ExpectedAddr) \
79 do { \
80 RTNETADDRIPV4 Addr; \
81 const char *strAll = String /* concat */ Trailer; \
82 const char *pTrailer = strAll + sizeof(String) - 1; \
83 char *pNext = NULL; \
84 int rc2 = RTNetStrToIPv4AddrEx(strAll, &Addr, &pNext); \
85 if ((rcExpected) && !rc2) \
86 { \
87 RTTestIFailed("at line %d: '%s': expected %Rrc got %Rrc\n", \
88 __LINE__, String, (rcExpected), rc2); \
89 } \
90 else if ((rcExpected) != rc2 \
91 || (rc2 == VINF_SUCCESS \
92 && (RT_H2N_U32_C(ExpectedAddr) != Addr.u \
93 || pTrailer != pNext))) \
94 { \
95 RTTestIFailed("at line %d: '%s': expected %Rrc got %Rrc," \
96 " expected address %RTnaipv4 got %RTnaipv4" \
97 " expected trailer \"%s\" got %s%s%s" \
98 "\n", \
99 __LINE__, String, rcExpected, rc2, \
100 RT_H2N_U32_C(ExpectedAddr), Addr.u, \
101 pTrailer, \
102 pNext ? "\"" : "", \
103 pNext ? pNext : "(null)", \
104 pNext ? "\"" : ""); \
105 } \
106 } while (0)
107
108
109#define CHECKCIDR(String, rcExpected, ExpectedAddr, iExpectedPrefix) \
110 do { \
111 RTNETADDRIPV4 Addr; \
112 int iPrefix; \
113 \
114 int rc2 = RTNetStrToIPv4Cidr(String, &Addr, &iPrefix); \
115 if ((rcExpected) && !rc2) \
116 { \
117 RTTestIFailed("at line %d: '%s': expected %Rrc got %Rrc\n", \
118 __LINE__, String, (rcExpected), rc2); \
119 } \
120 else if ( (rcExpected) != rc2 \
121 || ( rc2 == VINF_SUCCESS \
122 && ( RT_H2N_U32_C(ExpectedAddr) != Addr.u \
123 || iExpectedPrefix != iPrefix))) \
124 { \
125 RTTestIFailed("at line %d: '%s': expected %Rrc got %Rrc," \
126 " expected address %RTnaipv4/%d got %RTnaipv4/%d\n", \
127 __LINE__, String, rcExpected, rc2, \
128 RT_H2N_U32_C(ExpectedAddr), (iExpectedPrefix), \
129 Addr.u, iPrefix); \
130 } \
131 } while (0)
132
133#define GOODCIDR(String, ExpectedAddr, iExpectedPrefix) \
134 CHECKCIDR(String, VINF_SUCCESS, ExpectedAddr, iExpectedPrefix)
135
136#define BADCIDR(String) \
137 CHECKCIDR(String, VERR_INVALID_PARAMETER, 0, 0)
138
139
140#define CHECKISADDR(String, fExpected) \
141 do { \
142 bool fRc = RTNetIsIPv4AddrStr(String); \
143 if (fRc != fExpected) \
144 { \
145 RTTestIFailed("at line %d: '%s':" \
146 " expected %RTbool got %RTbool\n", \
147 __LINE__, (String), fExpected, fRc); \
148 } \
149 } while (0)
150
151#define IS_ADDR(String) CHECKISADDR((String), true)
152#define NOT_ADDR(String) CHECKISADDR((String), false)
153
154
155#define CHECKANY(String, fExpected) \
156 do { \
157 bool fRc = RTNetStrIsIPv4AddrAny(String); \
158 if (fRc != fExpected) \
159 { \
160 RTTestIFailed("at line %d: '%s':" \
161 " expected %RTbool got %RTbool\n", \
162 __LINE__, (String), fExpected, fRc); \
163 } \
164 } while (0)
165
166#define IS_ANY(String) CHECKANY((String), true)
167#define NOT_ANY(String) CHECKANY((String), false)
168
169
170#define CHECKMASK(_mask, _rcExpected, _iExpectedPrefix) \
171 do { \
172 /* const */ RTNETADDRIPV4 Mask; \
173 int iExpectedPrefix = (_iExpectedPrefix); \
174 int iPrefix; \
175 const int rcExpected = (_rcExpected); \
176 int rc2; \
177 \
178 Mask.u = RT_H2N_U32_C(UINT32_C(_mask)); \
179 rc2 = RTNetMaskToPrefixIPv4(&Mask, &iPrefix); \
180 \
181 if (rcExpected == VINF_SUCCESS) \
182 { \
183 if (rc2 != rcExpected) \
184 { \
185 /* unexpected failure */ \
186 RTTestIFailed("at line %d: mask %RTnaipv4:" \
187 " expected prefix length %d got %Rrc\n", \
188 __LINE__, Mask.u, \
189 iExpectedPrefix, rc2); \
190 } \
191 else if (iPrefix != iExpectedPrefix) \
192 { \
193 /* unexpected result */ \
194 RTTestIFailed("at line %d: mask %RTnaipv4:" \
195 " expected prefix length %d got %d\n", \
196 __LINE__, Mask.u, \
197 iExpectedPrefix, iPrefix); \
198 } \
199 } \
200 else /* expect failure */ \
201 { \
202 if (rc2 == VINF_SUCCESS) \
203 { \
204 /* unexpected success */ \
205 RTTestIFailed("at line %d: mask %RTnaipv4:" \
206 " expected %Rrc got prefix length %d\n", \
207 __LINE__, Mask.u, \
208 rcExpected, iPrefix); \
209 } \
210 else if (rc2 != rcExpected) \
211 { \
212 /* unexpected error */ \
213 RTTestIFailed("at line %d: mask %RTnaipv4:" \
214 " expected %Rrc got %Rrc\n", \
215 __LINE__, Mask.u, \
216 rcExpected, rc2); \
217 } \
218 } \
219 } while (0)
220
221#define CHECKPREFIX(_prefix, _rcExpected, _mask) \
222 do { \
223 const int iPrefix = (_prefix); \
224 RTNETADDRIPV4 ExpectedMask, Mask; \
225 const int rcExpected = (_rcExpected); \
226 int rc2; \
227 \
228 ExpectedMask.u = RT_H2N_U32_C(UINT32_C(_mask)); \
229 rc2 = RTNetPrefixToMaskIPv4(iPrefix, &Mask); \
230 \
231 if (rcExpected == VINF_SUCCESS) \
232 { \
233 if (rc2 != rcExpected) \
234 { \
235 /* unexpected failure */ \
236 RTTestIFailed("at line %d: prefix %d:" \
237 " expected mask %RTnaipv4 got %Rrc\n", \
238 __LINE__, iPrefix, \
239 ExpectedMask.u, rc2); \
240 } \
241 else if (Mask.u != ExpectedMask.u) \
242 { \
243 /* unexpected result */ \
244 RTTestIFailed("at line %d: prefix %d:" \
245 " expected mask %RTnaipv4 got %RTnaipv4\n", \
246 __LINE__, iPrefix, \
247 ExpectedMask.u, Mask.u); \
248 } \
249 } \
250 else /* expect failure */ \
251 { \
252 if (rc2 == VINF_SUCCESS) \
253 { \
254 /* unexpected success */ \
255 RTTestIFailed("at line %d: prefix %d:" \
256 " expected %Rrc got mask %RTnaipv4\n", \
257 __LINE__, iPrefix, \
258 rcExpected, Mask.u); \
259 } \
260 else if (rc2 != rcExpected) \
261 { \
262 /* unexpected error */ \
263 RTTestIFailed("at line %d: prefix %d:" \
264 " expected %Rrc got %Rrc\n", \
265 __LINE__, iPrefix, \
266 rcExpected, rc2); \
267 } \
268 } \
269 } while (0)
270
271#define GOODMASK(_mask, _prefix) \
272 do { \
273 CHECKMASK(_mask, VINF_SUCCESS, _prefix); \
274 CHECKPREFIX(_prefix, VINF_SUCCESS, _mask); \
275 } while (0)
276
277#define BADMASK(_mask) \
278 CHECKMASK(_mask, VERR_INVALID_PARAMETER, -1)
279
280#define BADPREFIX(_prefix) \
281 CHECKPREFIX(_prefix, VERR_INVALID_PARAMETER, 0)
282
283
284int main()
285{
286 RTTEST hTest;
287 int rc = RTTestInitAndCreate("tstRTNetIPv4", &hTest);
288 if (rc)
289 return rc;
290 RTTestBanner(hTest);
291
292 GOODADDR("1.2.3.4", 0x01020304);
293 GOODADDR("0.0.0.0", 0x00000000);
294 GOODADDR("255.255.255.255", 0xFFFFFFFF);
295
296 /* leading and trailing whitespace is allowed */
297 GOODADDR(" 1.2.3.4 ", 0x01020304);
298 GOODADDR("\t1.2.3.4\t", 0x01020304);
299
300 BADADDR("1.2.3.4x");
301 BADADDR("1.2.3.4.");
302 BADADDR("1.2.3");
303 BADADDR("0x1.2.3.4");
304 BADADDR("666.2.3.4");
305 BADADDR("1.666.3.4");
306 BADADDR("1.2.666.4");
307 BADADDR("1.2.3.666");
308
309 /*
310 * Parsing itself is covered by the tests above, here we only
311 * check trailers
312 */
313 CHECKADDREX("1.2.3.4", "", VINF_SUCCESS, 0x01020304);
314 CHECKADDREX("1.2.3.4", " ", VWRN_TRAILING_SPACES, 0x01020304);
315 CHECKADDREX("1.2.3.4", "x", VWRN_TRAILING_CHARS, 0x01020304);
316 CHECKADDREX("1.2.3.444", "", VERR_INVALID_PARAMETER, 0);
317
318
319 GOODCIDR("1.2.3.4", 0x01020304, 32);
320 GOODCIDR("1.2.3.4/32", 0x01020304, 32);
321 GOODCIDR("1.2.3.4/24", 0x01020304, 24); /* address is not truncated to prefix */
322
323 GOODCIDR("1.2.3.0/0xffffff00", 0x01020300, 24);
324 GOODCIDR("1.2.3.4/0xffffff00", 0x01020304, 24);
325 GOODCIDR("1.2.3.4/0xffffffff", 0x01020304, 32);
326
327 GOODCIDR("1.2.3.0/255.255.255.0", 0x01020300, 24);
328 GOODCIDR("1.2.3.4/255.255.255.0", 0x01020304, 24);
329 GOODCIDR("1.2.3.4/255.255.255.255", 0x01020304, 32);
330
331 GOODCIDR("0.0.0.0/0", 0x00000000, 0);
332 GOODCIDR("0.0.0.0/0x0", 0x00000000, 0);
333 GOODCIDR("0.0.0.0/0.0.0.0", 0x00000000, 0);
334
335 /*
336 * we allow zero prefix mostly for the sake of the above
337 * "everything"/default case, but allow it on everything - a
338 * conscientious caller should be doing more checks on the result
339 * anyway.
340 */
341 GOODCIDR("1.2.3.4/0", 0x01020304, 0); /* prefix can be zero */
342
343 GOODCIDR("\t " "1.2.3.4/24", 0x01020304, 24); /* leading spaces ok */
344 GOODCIDR( "1.2.3.4/24" " \t", 0x01020304, 24); /* trailing spaces ok */
345 GOODCIDR("\t " "1.2.3.4/24" " \t", 0x01020304, 24); /* both are ok */
346
347 /* trailing space with netmask notation */
348 GOODCIDR("1.2.3.0/0xffffff00" " ", 0x01020300, 24);
349 GOODCIDR("1.2.3.0/255.255.255.0" " ", 0x01020300, 24);
350
351 BADCIDR("1.2.3.4/24.");
352 BADCIDR("1.2.3.4/24 .");
353 BADCIDR("1.2.3.4/240.");
354 BADCIDR("1.2.3.4/240.");
355
356 BADCIDR("1.2.3.4/33"); /* prefix is too big */
357 BADCIDR("1.2.3.4/256"); /* prefix is too big */
358 BADCIDR("1.2.3.4/257"); /* prefix is too big */
359 BADCIDR("1.2.3.4/-1"); /* prefix is negative */
360 BADCIDR("1.2.3.4/"); /* prefix is missing */
361 BADCIDR("1.2.3.4/a"); /* prefix is not a number */
362 BADCIDR("1.2.3.4/0xa"); /* prefix is not decimal */
363// BADCIDR("1.2.3.0/024"); /* XXX: prefix is not decimal */
364
365 BADCIDR("1.2.3.0 /24"); /* no spaces after address */
366 BADCIDR("1.2.3.0/ 24"); /* no spaces after slash */
367
368 BADCIDR("1.2.3.0/24" "x"); /* trailing chars */
369 BADCIDR("1.2.3.0/24" " x"); /* trailing chars */
370
371 BADCIDR("1.2.3.0/0xffffff01"); /* non-contiguous mask */
372 BADCIDR("1.2.3.0/255.255.255.1"); /* non-contiguous mask */
373
374 /* NB: RTNetIsIPv4AddrStr does NOT allow leading/trailing whitespace */
375 IS_ADDR("1.2.3.4");
376 NOT_ADDR(" 1.2.3.4");
377 NOT_ADDR("1.2.3.4 ");
378 NOT_ADDR("1.2.3.4x");
379
380 IS_ANY("0.0.0.0");
381 IS_ANY("\t 0.0.0.0 \t"); /* ... but RTNetStrIsIPv4AddrAny does */
382
383 NOT_ANY("1.1.1.1"); /* good address, but not INADDR_ANY */
384 NOT_ANY("0.0.0.0x"); /* bad address */
385
386
387 /*
388 * The mask <-> prefix table is small so we can test it all.
389 */
390 GOODMASK(0x00000000, 0); /* 0.0.0.0 */
391 GOODMASK(0x80000000, 1); /* 128.0.0.0 */
392 GOODMASK(0xc0000000, 2); /* 192.0.0.0 */
393 GOODMASK(0xe0000000, 3); /* 224.0.0.0 */
394 GOODMASK(0xf0000000, 4); /* 240.0.0.0 */
395 GOODMASK(0xf8000000, 5); /* 248.0.0.0 */
396 GOODMASK(0xfc000000, 6); /* 252.0.0.0 */
397 GOODMASK(0xfe000000, 7); /* 254.0.0.0 */
398 GOODMASK(0xff000000, 8); /* 255.0.0.0 */
399 GOODMASK(0xff800000, 9); /* 255.128.0.0 */
400 GOODMASK(0xffc00000, 10); /* 255.192.0.0 */
401 GOODMASK(0xffe00000, 11); /* 255.224.0.0 */
402 GOODMASK(0xfff00000, 12); /* 255.240.0.0 */
403 GOODMASK(0xfff80000, 13); /* 255.248.0.0 */
404 GOODMASK(0xfffc0000, 14); /* 255.252.0.0 */
405 GOODMASK(0xfffe0000, 15); /* 255.254.0.0 */
406 GOODMASK(0xffff0000, 16); /* 255.255.0.0 */
407 GOODMASK(0xffff8000, 17); /* 255.255.128.0 */
408 GOODMASK(0xffffc000, 18); /* 255.255.192.0 */
409 GOODMASK(0xffffe000, 19); /* 255.255.224.0 */
410 GOODMASK(0xfffff000, 20); /* 255.255.240.0 */
411 GOODMASK(0xfffff800, 21); /* 255.255.248.0 */
412 GOODMASK(0xfffffc00, 22); /* 255.255.252.0 */
413 GOODMASK(0xfffffe00, 23); /* 255.255.254.0 */
414 GOODMASK(0xffffff00, 24); /* 255.255.255.0 */
415 GOODMASK(0xffffff80, 25); /* 255.255.255.128 */
416 GOODMASK(0xffffffc0, 26); /* 255.255.255.192 */
417 GOODMASK(0xffffffe0, 27); /* 255.255.255.224 */
418 GOODMASK(0xfffffff0, 28); /* 255.255.255.240 */
419 GOODMASK(0xfffffff8, 29); /* 255.255.255.248 */
420 GOODMASK(0xfffffffc, 30); /* 255.255.255.252 */
421 GOODMASK(0xfffffffe, 31); /* 255.255.255.254 */
422 GOODMASK(0xffffffff, 32); /* 255.255.255.255 */
423
424 BADMASK(0x01020304);
425
426 BADPREFIX(-1);
427 BADPREFIX(33);
428
429 return RTTestSummaryAndDestroy(hTest);
430}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette