VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/string/RTStrIPv6.cpp@ 43172

Last change on this file since 43172 was 43172, checked in by vboxsync, 12 years ago

gcc build fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.2 KB
Line 
1/* $Id: RTStrIPv6.cpp 43172 2012-09-04 17:11:51Z vboxsync $ */
2/** @file
3 * IPRT - RTStrIPv6.
4 */
5
6/*
7 * Contributed by Oliver Loch.
8 *
9 * Copyright (C) 2012 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 *
19 * The contents of this file may alternatively be used under the terms
20 * of the Common Development and Distribution License Version 1.0
21 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
22 * VirtualBox OSE distribution, in which case the provisions of the
23 * CDDL are applicable instead of those of the GPL.
24 *
25 * You may elect to license modified versions of this file under the
26 * terms and conditions of either the GPL or the CDDL or both.
27 */
28
29
30/*******************************************************************************
31* Header Files *
32*******************************************************************************/
33#include <iprt/mem.h>
34#include <iprt/string.h>
35#include <iprt/stream.h>
36#include "internal/iprt.h"
37#include "internal/string.h"
38
39/**
40 * Parses any string and tests if it is an IPv6 Address
41 *
42 * This function should NOT be used directly. If you do, note
43 * that no security checks are done at the moment. This can change.
44 *
45 * @returns iprt sstatus code.
46 * @param pszAddress The strin that holds the IPv6 address
47 * @param addressLength The length of pszAddress
48 * @param pszAddressOut Returns a plain, full blown IPv6 address
49 * as a char array
50 * @param addressOutSize The size of pszAddressOut (length)
51 * @param pPortOut 32 bit unsigned integer, holding the port
52 * If pszAddress doesn't contain a port, it's 0
53 * @param pszScopeOut Returns the scope of the address, if none it's 0
54 * @param scopeOutSize sizeof(pszScopeOut)
55 * @param pBrackets returns true if the address was enclosed in brackets
56 * @param pEmbeddedV4 returns true if the address is an embedded IPv4 address
57 * @param followRfc if set to true, the function follows RFC (default)
58 */
59static int rtStrParseAddrStr6(const char *pszAddress, size_t addressLength, char *pszAddressOut, size_t addressOutSize, uint32_t *pPortOut, char *pszIfIdOut, size_t ifIdOutSize, bool *pBrackets, bool *pEmbeddedV4, bool followRfc)
60{
61 /************************\
62 * Pointer Hell Ahead *
63 \************************/
64
65 const char szIpV6AddressChars[] = "ABCDEF01234567890abcdef.:[]%"; // order IMPORTANT
66 const char szIpV4AddressChars[] = "01234567890.:[]"; // order IMPORTANT
67 const char szLinkLocalPrefix[] = "FfEe8800"; //
68 const char *pszIpV6AddressChars = NULL, *pszIpV4AddressChars = NULL, *pszLinkLocalPrefix = NULL;
69
70 char *pszSourceAddress = NULL, *pszSourceAddressStart = NULL;
71 char *pszResultAddress = NULL, *pszResultAddressStart = NULL;
72 char *pszResultAddress4 = NULL, *pszResultAddress4Start = NULL;
73 char *pszResultPort = NULL, *pszResultPortStart = NULL;
74 char *pszInternalAddress = NULL, *pszInternalAddressStart = NULL;
75 char *pszInternalPort = NULL, *pszInternalPortStart = NULL;
76
77 char *pStart = NULL, *pNow = NULL, *pNext = NULL, *pNowChar = NULL, *pIfId = NULL, *pIfIdEnd = NULL;
78 char *pNowDigit = NULL, *pFrom = NULL, *pTo = NULL, *pLast = NULL;
79 char *pGap = NULL, *pMisc = NULL, *pDotStart = NULL, *pFieldStart = NULL, *pFieldEnd = NULL;
80 char *pFieldStartLongest = NULL, *pBracketOpen = NULL, *pBracketClose = NULL;
81 char *pszRc = NULL;
82
83 bool isLinkLocal = false;
84 char szDummy[4];
85
86 uint8_t *pByte = NULL;
87 uint32_t byteOut = 0;
88 uint16_t returnValue = 0;
89 uint32_t colons = 0;
90 uint32_t colonsOverAll = 0;
91 uint32_t fieldLength = 0;
92 uint32_t dots = 0;
93 uint32_t gapSize = 0;
94 uint32_t intPortOut = 0;
95
96 pszIpV4AddressChars = &szIpV4AddressChars[0];
97 pszIpV6AddressChars = &szIpV6AddressChars[6];
98 pszLinkLocalPrefix = &szLinkLocalPrefix[6];
99
100 if (!followRfc)
101 pszIpV6AddressChars = &szIpV6AddressChars[0];
102
103 if (addressLength<2)
104 returnValue = 711;
105
106 pszResultAddressStart = (char *)RTMemTmpAlloc(34);
107 pszInternalAddressStart = (char *)RTMemTmpAlloc(34);
108 pszInternalPortStart = (char * )RTMemTmpAlloc(10);
109
110 if (! (pszResultAddressStart && pszInternalAddressStart && pszInternalPortStart))
111 {
112 if (pszResultAddressStart)
113 RTMemTmpFree(pszResultAddressStart);
114
115 if (pszInternalAddressStart)
116 RTMemTmpFree(pszInternalAddressStart);
117
118 if (pszInternalPortStart)
119 RTMemTmpFree(pszInternalPortStart);
120
121 return -701;
122 }
123
124 memset(szDummy, '\0', 4);
125
126 pszResultAddress = pszResultAddressStart;
127 memset(pszResultAddressStart, '\0', 34);
128
129 pszInternalAddress = pszInternalAddressStart;
130 memset(pszInternalAddressStart, '\0' , 34);
131
132 pszInternalPort = pszInternalPortStart;
133 memset(pszInternalPortStart, '\0', 10);
134
135 pszSourceAddress = pszSourceAddressStart = (char *)pszAddress;
136
137 pFrom = pTo = pStart = pLast = pszSourceAddressStart;
138
139 while (*pszSourceAddress != '\0' && !returnValue)
140 {
141 pNow = NULL;
142 pNext = NULL;
143 pNowChar = NULL;
144 pNowDigit = NULL;
145
146 pNow = pszSourceAddress;
147 pNext = pszSourceAddress + 1;
148
149 if (!pFrom)
150 pFrom = pTo = pNow;
151
152 pNowChar = (char *)memchr(pszIpV6AddressChars, *pNow, strlen(pszIpV6AddressChars));
153 pNowDigit = (char *)memchr(pszIpV6AddressChars, *pNow, strlen(pszIpV6AddressChars) - 5);
154
155 if (pszResultPort)
156 {
157 if (pLast && (pszResultPort == pszSourceAddressStart))
158 {
159 if (*pLast == '\0')
160 returnValue = 721;
161
162 pszResultPortStart = (char *)RTMemTmpAlloc(10);
163
164 if (!pszResultPortStart)
165 returnValue = 702;
166
167 memset(pszResultPortStart, '\0', 10);
168 pszResultPort = pszResultPortStart;
169 pszSourceAddress = pLast;
170 pMisc = pLast;
171 pLast = NULL;
172 continue;
173 }
174
175 pNowDigit = NULL;
176 pNowDigit = (char *)memchr(pszIpV4AddressChars, *pNow, strlen(pszIpV4AddressChars) - 4);
177
178 if (strlen(pszResultPortStart) == 5)
179 returnValue = 11;
180
181 if (*pNow == '0' && pszResultPort == pszResultPortStart && *pNext != '\0' && (pNow - pMisc) < 5 )
182 {
183 pszSourceAddress++;
184 continue;
185 }
186
187 if (pNowDigit)
188 {
189 *pszResultPort = *pNowDigit;
190 pszResultPort++;
191 pszSourceAddress++;
192 continue;
193 }
194 else
195 returnValue = 12;
196 }
197
198 if (pszResultAddress4)
199 {
200 if (pszResultAddress4 == pszSourceAddressStart && pLast)
201 {
202 dots = 0;
203 pszResultAddress4 = NULL;
204 pszResultAddress4Start = NULL;
205 pszResultAddress4Start = (char *)RTMemTmpAlloc(20);
206
207 if (!pszResultAddress4Start)
208 {
209 returnValue = 401;
210 break;
211 }
212
213 memset(pszResultAddress4Start, '\0', 20);
214 pszResultAddress4 = pszResultAddress4Start;
215 pszSourceAddress = pLast;
216 pFrom = pLast;
217 pTo = pLast;
218 pLast = NULL;
219 continue;
220 }
221
222 pTo = pNow;
223 pNowDigit = NULL;
224 pNowDigit = (char *)memchr(pszIpV4AddressChars, *pNow, strlen(pszIpV4AddressChars) - 4);
225
226 if (!pNowDigit && *pNow != '.' && *pNow != ']' && *pNow != ':' && *pNow != '%')
227 returnValue = 412;
228
229 if ((pNow - pFrom) > 3)
230 {
231 returnValue = 402;
232 break;
233 }
234
235 if (pNowDigit && *pNext != '\0')
236 {
237 pszSourceAddress++;
238 continue;
239 }
240
241 if (!pNowDigit && !pBracketOpen && (*pNext == '.' || *pNext == ']' || *pNext == ':'))
242 returnValue = 411;
243
244 memset(pszResultAddress4, '0', 3);
245 pMisc = pszResultAddress4 + 2;
246 pszResultAddress4 = pszResultAddress4 + 3;
247
248 if (*pNow != '.' && !pNowDigit && strlen(pszResultAddress4Start) < 9)
249 returnValue = 403;
250
251 if ((pTo - pFrom) > 0)
252 pTo--;
253
254 dots++;
255
256 while (pTo >= pFrom)
257 {
258 *pMisc = *pTo;
259 pMisc--;
260 pTo--;
261 }
262
263 if (dots == 4 && *pNow == '.')
264 {
265 if (!pBracketOpen)
266 {
267 pszResultPort = pszSourceAddressStart;
268 pLast = pNext;
269 }
270 else
271 {
272 returnValue = 409;
273 }
274 }
275
276 dots = 0;
277
278 pFrom = pNext;
279 pTo = pNext;
280
281 if (strlen(pszResultAddress4Start) > 11)
282 pszResultAddress4 = NULL;
283
284 if ((*pNow == ':' || *pNow == '.') && strlen(pszResultAddress4Start) == 12)
285 {
286 pLast = pNext;
287 pszResultPort = pszSourceAddressStart;
288 }
289
290 if (*pNow == '%')
291 {
292 pIfId = pNow;
293 pLast = pNow;
294 continue;
295 }
296 pszSourceAddress = pNext;
297
298 if (*pNow != ']')
299 continue;
300
301 pFrom = pNow;
302 pTo = pNow;
303 }
304
305 if (pIfId && (!pIfIdEnd))
306 {
307 if (*pIfId == '%' && pIfId == pLast && *pNext != '\0')
308 {
309 pFrom = pNext;
310 pIfId = pNext;
311 pLast = NULL;
312
313 pszSourceAddress++;
314 continue;
315 }
316
317 if (*pNow == '%' && pIfId <= pNow)
318 {
319 returnValue = 442;
320 break;
321 }
322
323 if (*pNow != ']' && *pNext != '\0')
324 {
325 pTo = pNow;
326 pszSourceAddress++;
327 continue;
328 }
329
330 if (*pNow == ']')
331 {
332 pIfIdEnd = pNow - 1;
333 pFrom = pNow;
334 pTo = pNow;
335 continue;
336 }
337 else
338 {
339 pIfIdEnd = pNow;
340 pFrom = NULL;
341 pTo = NULL;
342 pszSourceAddress++;
343 continue;
344 }
345 }
346
347 if (!pNowChar)
348 {
349 returnValue = 254;
350
351 if (followRfc)
352 {
353 pMisc = (char *)memchr(&szIpV6AddressChars[0], *pNow, strlen(&szIpV6AddressChars[0]));
354
355 if (pMisc)
356 returnValue = 253;
357 }
358 }
359
360 if (strlen(pszResultAddressStart) > 32 && !pszResultAddress4Start)
361 returnValue = 255;
362
363 if (pNowDigit && *pNext != '\0' && colons == 0)
364 {
365 pTo = pNow;
366 pszSourceAddress++;
367 continue;
368 }
369
370 if (*pNow == ':' && *pNext != '\0')
371 {
372 colonsOverAll++;
373 colons++;
374 pszSourceAddress++;
375 continue;
376 }
377
378 if (*pNow == ':' )
379 {
380 colons++;
381 colonsOverAll++;
382 }
383
384 if (*pNow == '.')
385 {
386 pMisc = pNow;
387
388 while (*pMisc != '\0' && *pMisc != ']')
389 {
390 if (*pMisc == '.')
391 dots++;
392
393 pMisc++;
394 }
395 }
396
397 if (*pNow == ']')
398 {
399 if (pBracketClose)
400 returnValue = 77;
401
402 if (!pBracketOpen)
403 returnValue = 22;
404
405 if (*pNext == ':' || *pNext == '.')
406 {
407 pszResultPort = pszSourceAddressStart;
408 pLast = pNext + 1;
409 }
410
411 if (pFrom == pNow)
412 pFrom = NULL;
413
414 pBracketClose = pNow;
415 }
416
417 if (*pNow == '[')
418 {
419 if (pBracketOpen)
420 returnValue = 23;
421
422 if (pStart != pNow)
423 returnValue = 24;
424
425 pBracketOpen = pNow;
426 pStart++;
427 pFrom++;
428 pszSourceAddress++;
429 continue;
430 }
431
432 if (*pNow == '%')
433 {
434 if (pIfId)
435 returnValue = 441;
436
437 pLast = pNext;
438 pIfId = pNext;
439 }
440
441 if (colons > 0)
442 {
443 if (colons == 1)
444 {
445 if (pStart + 1 == pNow )
446 returnValue = 31;
447
448 if (*pNext == '\0' && !pNowDigit)
449 returnValue = 32;
450
451 pLast = pNow;
452 }
453
454 if (colons == 2)
455 {
456 if (pGap)
457 returnValue = 33;
458
459 pGap = pszResultAddress + 4;
460
461 if (pStart + 1 == pNow || pStart + 2 == pNow)
462 {
463 pGap = pszResultAddressStart;
464 pFrom = pNow;
465 }
466
467 if (*pNext == '\0' && !pNowDigit)
468 pszSourceAddress++;
469
470 if (*pNext != ':' && *pNext != '.')
471 pLast = pNow;
472 }
473
474 if (colons == 3)
475 {
476 pFrom = pLast;
477 pLast = pNow;
478
479 if (*pNext == '\0' && !pNowDigit)
480 returnValue = 34;
481
482 if (pBracketOpen)
483 returnValue = 35;
484
485 if (pGap && followRfc)
486 returnValue = 36;
487
488 if (!pGap)
489 pGap = pszResultAddress + 4;
490
491 if (pStart + 3 == pNow)
492 {
493 pszResultPort = pszSourceAddressStart;
494 pGap = pszResultAddress;
495 pFrom = NULL;
496 }
497
498 if (pNowDigit)
499 {
500 pszResultPort = pszSourceAddressStart;
501 }
502 }
503 }
504 if (*pNext == '\0' && colons == 0 && !pIfIdEnd)
505 {
506 pFrom = pLast;
507
508 if (pNowDigit)
509 pTo = pNow;
510
511 pLast = NULL;
512 }
513
514 if (dots > 0)
515 {
516 if (dots == 1)
517 {
518 pszResultPort = pszSourceAddressStart;
519 pLast = pNext;
520 }
521
522 if (dots == 4 && pBracketOpen)
523 returnValue = 601;
524
525 if (dots == 3 || dots == 4)
526 {
527 pszResultAddress4 = pszSourceAddressStart;
528 pLast = pFrom;
529 pFrom = NULL;
530 }
531
532 if (dots > 4)
533 returnValue = 603;
534
535 dots = 0;
536 }
537
538 if (pFrom && pTo)
539 {
540 if (pTo - pFrom > 3)
541 {
542 returnValue = 51;
543 break;
544 }
545
546 if (followRfc)
547 {
548 if ((pTo - pFrom > 0) && *pFrom == '0')
549 returnValue = 101;
550
551 if ((pTo - pFrom) == 0 && *pFrom == '0' && colons == 2)
552 returnValue = 102;
553
554 if ((pTo - pFrom) == 0 && *pFrom == '0' && pszResultAddress == pGap)
555 returnValue = 103;
556
557 if ((pTo - pFrom) == 0 && *pFrom == '0')
558 {
559 if (!pFieldStart)
560 {
561 pFieldStart = pszResultAddress;
562 pFieldEnd = pszResultAddress + 4;
563 }
564 else
565 {
566 pFieldEnd = pFieldEnd + 4;
567 }
568 }
569 else
570 {
571 if ((size_t)(pFieldEnd - pFieldStart) > fieldLength)
572 {
573 fieldLength = pFieldEnd - pFieldStart;
574 pFieldStartLongest = pFieldStart;
575 }
576
577 pFieldStart = NULL;
578 pFieldEnd = NULL;
579 }
580 }
581 if (!(pGap == pszResultAddressStart && (size_t)(pNow - pStart) == colons))
582 {
583 memset(pszResultAddress, '0', 4);
584 pMisc = pszResultAddress + 3;
585 pszResultAddress = pszResultAddress + 4;
586
587 if (pFrom == pStart && (pTo - pFrom) == 3)
588 {
589 isLinkLocal = true;
590
591 while (pTo >= pFrom)
592 {
593 *pMisc = *pTo;
594
595 if (*pTo != *pszLinkLocalPrefix && *pTo != *(pszLinkLocalPrefix + 1))
596 isLinkLocal = false;
597
598 pTo--;
599 pMisc--;
600 pszLinkLocalPrefix = pszLinkLocalPrefix - 2;
601 }
602 }
603 else
604 {
605 while (pTo >= pFrom)
606 {
607 *pMisc = *pTo;
608 pMisc--;
609 pTo--;
610 }
611 }
612 }
613
614 pFrom = pNow;
615 pTo = pNow;
616
617 }
618 if (*pNext == '\0' && colons == 0)
619 pszSourceAddress++;
620
621 if (*pNext == '\0' && !pBracketClose && !pszResultPort)
622 pTo = pNext;
623
624 colons = 0;
625 } // end of loop
626
627 if (!returnValue && colonsOverAll < 2)
628 returnValue = 252;
629
630 if (!returnValue && (pBracketOpen && !pBracketClose))
631 returnValue = 25;
632
633 if (!returnValue && pGap)
634 {
635 gapSize = 32 - strlen(pszResultAddressStart);
636
637 if (followRfc)
638 {
639 if (gapSize < 5)
640 returnValue = 104;
641
642 if (fieldLength > gapSize)
643 returnValue = 105;
644
645 if (fieldLength == gapSize && pFieldStartLongest < pGap)
646 returnValue = 106;
647 }
648
649 pszResultAddress = pszResultAddressStart;
650 pszInternalAddress = pszInternalAddressStart;
651
652 if (!returnValue && pszResultAddress4Start)
653 {
654 if (strlen(pszResultAddressStart) > 4)
655 returnValue = 405;
656
657 pszResultAddress = pszResultAddressStart;
658
659 if (pGap != pszResultAddressStart)
660 returnValue = 407;
661
662 memset(pszInternalAddressStart, '0', 20);
663 pszInternalAddress = pszInternalAddressStart + 20;
664
665 for (int i = 0; i < 4; i++)
666 {
667 if (*pszResultAddress != 'f' && *pszResultAddress != 'F')
668 {
669 returnValue = 406;
670 break;
671 }
672
673 *pszInternalAddress = *pszResultAddress;
674 pszResultAddress++;
675 pszInternalAddress++;
676 }
677 pszResultAddress4 = pszResultAddress4Start;
678
679 for (int i = 0; i<4; i++)
680 {
681 memcpy(szDummy, pszResultAddress4, 3);
682
683 int rc = RTStrToUInt32Ex((const char *)&szDummy[0], NULL, 16, &byteOut);
684
685 if (rc == 0 && byteOut < 256)
686 {
687 rc = RTStrPrintf(szDummy, 3, "%02x", byteOut);
688 memcpy(pszInternalAddress, szDummy, 2);
689 pszInternalAddress = pszInternalAddress + 2;
690 pszResultAddress4 = pszResultAddress4 + 3;
691 memset(szDummy, '\0', 4);
692 }
693 else
694 {
695 returnValue = 499;
696 }
697 }
698 }
699 else
700 {
701 while (!returnValue && pszResultAddress != pGap)
702 {
703 *pszInternalAddress = *pszResultAddress;
704 pszResultAddress++;
705 pszInternalAddress++;
706 }
707
708 memset(pszInternalAddress, '0', gapSize);
709 pszInternalAddress = pszInternalAddress + gapSize;
710
711 while (!returnValue && *pszResultAddress != '\0')
712 {
713 *pszInternalAddress = *pszResultAddress;
714 pszResultAddress++;
715 pszInternalAddress++;
716 }
717 }
718 }
719 else
720 {
721 if (!returnValue)
722 {
723 if (strlen(pszResultAddressStart) != 32)
724 returnValue = 111;
725
726 if (followRfc)
727 {
728 if (fieldLength > 4)
729 returnValue = 112;
730 }
731
732 memcpy(pszInternalAddressStart, pszResultAddressStart, strlen(pszResultAddressStart));
733 }
734 }
735
736 if (pszResultPortStart)
737 {
738 if (strlen(pszResultPortStart) > 0 && strlen(pszResultPortStart) < 6)
739 {
740 memcpy(pszInternalPortStart, pszResultPortStart, strlen(pszResultPortStart));
741
742 intPortOut = 0;
743 int rc = RTStrToUInt32Ex(pszInternalPortStart, NULL, 10, &intPortOut);
744
745 if (rc == 0)
746 {
747 if (!(intPortOut > 0 && intPortOut < 65536))
748 intPortOut = 0;
749 }
750 else
751 {
752 returnValue = 888;
753 }
754 }
755 else
756 {
757 returnValue = 889;
758 }
759 }
760
761 /*
762 full blown address 32 bytes, no colons -> pszInternalAddressStart
763 port as string -> pszResultPortStart
764 port as binary integer -> intPortOut
765 interface id in pIfId and pIfIdEnd
766
767 Now fill the out parameters.
768
769 */
770
771 if (!returnValue && pszAddressOut)
772 {
773 if (strlen(pszInternalAddressStart) < addressOutSize)
774 {
775 pszRc = NULL;
776 pszRc = (char *)memset(pszAddressOut, '\0', addressOutSize);
777
778 if (!pszRc)
779 returnValue = 910;
780
781 pszRc = NULL;
782
783 pszRc = (char *)memcpy(pszAddressOut, pszInternalAddressStart, strlen(pszInternalAddressStart));
784
785 if (!pszRc)
786 returnValue = 911;
787 }
788 else
789 {
790 returnValue = 912;
791 }
792 }
793
794 if (!returnValue && pPortOut)
795 {
796 *pPortOut = intPortOut;
797 }
798
799 if (!returnValue && pszIfIdOut)
800 {
801 if (pIfIdEnd && pIfId)
802 {
803 if ((size_t)(pIfIdEnd - pIfId) + 1 < ifIdOutSize)
804 {
805 pszRc = NULL;
806 pszRc = (char *)memset(pszIfIdOut, '\0', ifIdOutSize);
807
808 if (!pszRc)
809 returnValue = 913;
810
811 pszRc = NULL;
812 pszRc = (char *)memcpy(pszIfIdOut, pIfId, (pIfIdEnd - pIfId) + 1);
813
814 if (!pszRc)
815 returnValue = 914;
816 }
817 else
818 {
819 returnValue = 915;
820 }
821 }
822 else
823 {
824 pszRc = NULL;
825 pszRc = (char *)memset(pszIfIdOut, '\0', ifIdOutSize);
826
827 if (!pszRc)
828 returnValue = 916;
829 }
830 // temporary hack
831 if (isLinkLocal && (strlen(pszIfIdOut) < 1))
832 {
833 memset(pszIfIdOut, '\0', ifIdOutSize);
834 *pszIfIdOut = '%';
835 pszIfIdOut++;
836 *pszIfIdOut = '0';
837 pszIfIdOut++;
838 }
839 }
840
841 if (pBracketOpen && pBracketClose && pBrackets)
842 *pBrackets = true;
843
844 if (pEmbeddedV4 && pszResultAddress4Start)
845 *pEmbeddedV4 = true;
846
847 if (pszResultAddressStart)
848 RTMemTmpFree(pszResultAddressStart);
849
850 if (pszResultPortStart)
851 RTMemTmpFree(pszResultPortStart);
852
853 if (pszResultAddress4Start)
854 RTMemTmpFree(pszResultAddress4Start);
855
856 if (pszInternalAddressStart)
857 RTMemTmpFree(pszInternalAddressStart);
858
859 if (pszInternalPortStart)
860 RTMemTmpFree(pszInternalPortStart);
861
862 return (uint32_t)(returnValue - (returnValue * 2)); // make it negative...
863}
864
865/**
866 * Takes a string and returns a RFC compliant string of the address
867 * This function SHOULD NOT be used directly. It expects a 33 byte
868 * char array with a full blown IPv6 address without separators.
869 *
870 * @returns iprt status code.
871 * @param psz The string to convert
872 * @param pszAddrOut The char[] that will hold the result
873 * @param addOutSize The size of the char[] from above.
874 * @param pszPortOut char[] for the text representation of the port
875 * @param portOutSize sizeof(pszPortOut);
876 */
877DECLHIDDEN(int) rtStrToIpAddr6Str(const char *psz, char *pszAddrOut, size_t addrOutSize, char *pszPortOut, size_t portOutSize, bool followRfc)
878{
879 char *pStart = NULL;
880 char *pGapStart = NULL;
881 char *pGapEnd = NULL;
882 char *pGapTStart = NULL;
883 char *pGapTEnd = NULL;
884 char *pCurrent = NULL;
885 char *pOut = NULL;
886
887 if (!psz || !pszAddrOut)
888 return VERR_NOT_SUPPORTED;
889
890 if (addrOutSize < 40)
891 return VERR_NOT_SUPPORTED;
892
893 pStart = (char *)psz;
894 pCurrent = (char *)psz;
895 pGapStart = (char *)psz;
896 pGapEnd = (char *)psz;
897
898 while (*pCurrent != '\0')
899 {
900 if (*pCurrent != '0')
901 pGapTStart = NULL;
902
903 if ((pCurrent - pStart) % 4 == 0) // ok, start of a hextet
904 {
905 if (*pCurrent == '0' && !pGapTStart)
906 pGapTStart = pCurrent;
907 }
908
909 if ((pCurrent - pStart) % 4 == 3)
910 {
911 if (*pCurrent == '0' && pGapTStart)
912 pGapTEnd = pCurrent;
913
914 if (pGapTStart && pGapTEnd)
915 {
916 pGapTEnd = pCurrent;
917
918 if ((pGapTEnd - pGapTStart) > (pGapEnd - pGapStart))
919 {
920 pGapEnd = pGapTEnd;
921 pGapStart = pGapTStart;
922 }
923 }
924 }
925
926 pCurrent++;
927 }
928
929 pCurrent = (char *)psz;
930 pStart = (char *)psz;
931 pOut = (char *)pszAddrOut;
932
933 while (*pCurrent != '\0')
934 {
935 if (*pCurrent != '0')
936 pGapTStart = NULL;
937
938 if (!pGapTStart)
939 {
940 *pOut = *pCurrent;
941 pOut++;
942 }
943
944 if ((pCurrent - pStart) % 4 == 3)
945 {
946 if (pGapTStart && *pCurrent == '0')
947 {
948 *pOut = *pCurrent;
949 pOut++;
950 }
951
952 if (*(pCurrent + 1) != '\0')
953 {
954 *pOut = ':';
955 pOut++;
956 }
957
958 pGapTStart = pCurrent + 1;
959 }
960
961 if ((pCurrent + 1) == pGapStart && (pGapEnd - pGapStart) > 3)
962 {
963 *pOut = ':';
964 pOut++;
965 pCurrent = pGapEnd;
966 }
967
968 pCurrent++;
969 }
970
971 return VINF_SUCCESS;
972}
973
974RTDECL(int) RTStrIsIpAddr6(const char *psz, char *pszResultAddress, size_t resultAddressSize, bool addressOnly, bool followRfc)
975{
976 int rc;
977 int rc2;
978 int returnValue;
979
980 char *p = NULL, *pl = NULL;
981
982 int memAllocMaxSize = RT_MAX(strlen(psz), resultAddressSize) + 40;
983
984 char *pszAddressOutLocal = (char *)RTMemTmpAlloc(memAllocMaxSize);
985 char *pszIfIdOutLocal = (char *)RTMemTmpAlloc(memAllocMaxSize);
986 char *pszAddressRfcOutLocal = (char *)RTMemTmpAlloc(memAllocMaxSize);
987
988 if (!pszAddressOutLocal || !pszIfIdOutLocal || !pszAddressRfcOutLocal)
989 return VERR_NO_TMP_MEMORY;
990
991 memset(pszAddressOutLocal, '\0', memAllocMaxSize);
992 memset(pszIfIdOutLocal, '\0', memAllocMaxSize);
993 memset(pszAddressRfcOutLocal, '\0', memAllocMaxSize);
994
995 rc = rtStrParseAddrStr6(psz, strlen(psz), pszAddressOutLocal, memAllocMaxSize, NULL, pszIfIdOutLocal, memAllocMaxSize, NULL, NULL, followRfc);
996
997 if (rc == 0)
998 returnValue = VINF_SUCCESS;
999
1000 if (rc == 0 && pszResultAddress)
1001 {
1002 // convert the 32 characters to a valid, shortened ipv6 address
1003
1004 rc2 = rtStrToIpAddr6Str((const char *)pszAddressOutLocal, pszAddressRfcOutLocal, memAllocMaxSize, NULL, 0, followRfc);
1005
1006 if (rc2 != 0)
1007 returnValue = 951;
1008
1009 // this is a temporary solution
1010 if (!returnValue && strlen(pszIfIdOutLocal) > 0) // the if identifier is copied over _ALWAYS_ && !addressOnly)
1011 {
1012 p = pszAddressRfcOutLocal + strlen(pszAddressRfcOutLocal);
1013
1014 *p = '%';
1015
1016 p++;
1017
1018 pl = (char *)memcpy(p, pszIfIdOutLocal, strlen(pszIfIdOutLocal));
1019
1020 if (!pl)
1021 returnValue = VERR_NOT_SUPPORTED;
1022 }
1023
1024 pl = NULL;
1025
1026 pl = (char *)memcpy(pszResultAddress, pszAddressRfcOutLocal, strlen(pszAddressRfcOutLocal));
1027
1028 if (!pl)
1029 returnValue = VERR_NOT_SUPPORTED;
1030 }
1031
1032 if (rc != 0)
1033 returnValue = VERR_NOT_SUPPORTED;
1034
1035 if (pszAddressOutLocal)
1036 RTMemTmpFree(pszAddressOutLocal);
1037
1038 if (pszAddressRfcOutLocal)
1039 RTMemTmpFree(pszAddressRfcOutLocal);
1040
1041 if (pszIfIdOutLocal)
1042 RTMemTmpFree(pszIfIdOutLocal);
1043
1044 return returnValue;
1045
1046}
1047RT_EXPORT_SYMBOL(RTStrIsIpAddr6);
1048
1049
1050RTDECL(int) RTStrIsIpAddr4(const char *psz)
1051{
1052 const char szIpV4Digits[] = "0123456789.";
1053 char *pStart = NULL, *pEnd = NULL, *pFrom = NULL, *pTo = NULL, *pNow = NULL, *pDigit = NULL;
1054 char *pChar = NULL, *pNext = NULL;
1055
1056 uint32_t ulDots = 0;
1057 uint32_t ulOctet = 0;
1058 int rc = VINF_SUCCESS;
1059
1060 char szDummy[4];
1061
1062 if (strlen(psz) < 7 || strlen(psz) > 15)
1063 return -1;
1064
1065 pStart = pNow = pFrom = pTo = pEnd = (char *)psz;
1066
1067 while (*pNow != '\0')
1068 {
1069 pChar = NULL;
1070 pDigit = NULL;
1071 pNext = NULL;
1072
1073 pChar = (char *)memchr(szIpV4Digits, *pNow, strlen(szIpV4Digits));
1074 pDigit = (char *)memchr(szIpV4Digits, *pNow, strlen(szIpV4Digits) - 1);
1075 pNext = pNow + 1;
1076
1077 if (!pChar)
1078 return -2;
1079
1080 if (pDigit && *pNext != '\0')
1081 {
1082 pTo = pNow;
1083 pNow++;
1084 continue;
1085 }
1086
1087 if (*pNow == '.' || *pNext == '\0')
1088 {
1089 if (*pNext == '\0')
1090 pTo = pNow;
1091
1092 if ((pTo - pFrom) > 2)
1093 return -3;
1094
1095 memset(szDummy, '\0', 4);
1096 memcpy(szDummy, pFrom, (pTo - pFrom) + 1);
1097
1098 rc = RTStrToUInt32Ex(szDummy, NULL, 10, &ulOctet);
1099
1100 if (!RT_SUCCESS(rc))
1101 return -6;
1102
1103 if (ulOctet > 255)
1104 return -4;
1105
1106 ulDots++;
1107 pFrom = pNext;
1108 }
1109 pNow++;
1110 }
1111
1112 if (ulDots != 4) // yes, it's four
1113 return -5;
1114
1115 return 0;
1116}
1117RT_EXPORT_SYMBOL(RTStrIsIpAddr4);
1118
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