VirtualBox

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

Last change on this file since 92124 was 91919, checked in by vboxsync, 3 years ago

IPRT: Make RTNetStrToIPv4Cidr() and RTNetStrToIPv4Cidr() accept zero
prefix, mostly for the benefit of 0.0.0.0/0 and ::/0 respectively.

While here fix RTNetStrToIPv6Cidr to do stricter checks on the prefix.
When the number is too big RTStrToUInt8Ex returns a warning, not an
error. bugref:9330.

(should have been part of r147723).

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