RTStrIPv6.cpp revision 2911253f827c3ce1e5438e8b518c4c7f5368fbca
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * IPRT - RTStrIPv6.
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * Contributed by Oliver Loch.
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * Copyright (C) 2012 Oracle Corporation
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * This file is part of VirtualBox Open Source Edition (OSE), as
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * available from http://www.virtualbox.org. This file is free software;
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * you can redistribute it and/or modify it under the terms of the GNU
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * General Public License (GPL) as published by the Free Software
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * Foundation, in version 2 as it comes in the "COPYING" file of the
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * The contents of this file may alternatively be used under the terms
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * of the Common Development and Distribution License Version 1.0
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * VirtualBox OSE distribution, in which case the provisions of the
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * CDDL are applicable instead of those of the GPL.
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * You may elect to license modified versions of this file under the
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * terms and conditions of either the GPL or the CDDL or both.
9d3653fc5cdbbc8eefa2a4ee76dffcce5af8e164matthew/*******************************************************************************
9d3653fc5cdbbc8eefa2a4ee76dffcce5af8e164matthew* Header Files *
9d3653fc5cdbbc8eefa2a4ee76dffcce5af8e164matthew*******************************************************************************/
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac/** @page pg_rtnetipv6_addr IPv6 Address Format
c7fef36838657b602d29098075e95b4b26e0e9d0JnRouvignac * IPv6 Addresses, their representation in text and other problems.
9d3653fc5cdbbc8eefa2a4ee76dffcce5af8e164matthew * The following is based on:
c7fef36838657b602d29098075e95b4b26e0e9d0JnRouvignac * Before you start using those functions, you should have an idea of
c7fef36838657b602d29098075e95b4b26e0e9d0JnRouvignac * what you're dealing with, before you come and blame the functions...
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac * First of all, the address itself:
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac * An address is written like this: (READ THIS FINE MANUAL!)
4a7f0ad21d4c6a48235ffd7f7f4610315212d0e6JnRouvignac * - 2001:db8:abc:def::1
e6cea1f0fa0588db783bc3da75e156e1e83d0e1cJnRouvignac * The characters between two colons are called a "hextet".
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac * Each hextet consists of four characters and each IPv6 address
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac * consists of a maximum of eight hextets. So a full blown address
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac * would look like this:
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac * - 1111:2222:3333:4444:5555:6666:7777:8888
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac * The allowed characters are "0123456789abcdef". They have to be
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac * lower case. Upper case is not allowed.
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac * *** Gaps and adress shortening
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac * If an address contains hextets that contain only "0"s, they
f1a8b8986de97939dbfcbdfc23ee9e66d5faadb2JnRouvignac * can be shortened, like this:
e6cea1f0fa0588db783bc3da75e156e1e83d0e1cJnRouvignac * - 1111:2222:0000:0000:0000:0000:7777:8888 -> 1111:2222::7777:8888
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * The double colon represents the hextets that have been shortened "::".
bc3fd4bc72c31421ca9cccc6e50f92f0fa841a5bJnRouvignac * The "::" will be called "gap" from now on.
static 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)
char *pStart = NULL, *pNow = NULL, *pNext = NULL, *pNowChar = NULL, *pIfId = NULL, *pIfIdEnd = NULL;
bool isLinkLocal = false;
if (!followRfc)
if (pszInternalPortStart)
if (!pFrom)
if (pszResultPort)
if (!pszResultPortStart)
if (pNowDigit)
if (pszResultAddress4)
dots = 0;
if (!pszResultAddress4Start)
pTo--;
dots++;
pMisc--;
pTo--;
if (!pBracketOpen)
dots = 0;
if (!pNowChar)
if (followRfc)
if (pMisc)
colons++;
colons++;
dots++;
pMisc++;
if (pBracketClose)
if (!pBracketOpen)
if (pBracketOpen)
pStart++;
pFrom++;
if (pIfId)
if (colons > 0)
if (pGap)
if (pBracketOpen)
if (!pGap)
if (pNowDigit)
if (pNowDigit)
if (dots > 0)
dots = 0;
if (followRfc)
if (!pFieldStart)
isLinkLocal = true;
isLinkLocal = false;
pTo--;
pMisc--;
pMisc--;
pTo--;
colons = 0;
if (followRfc)
if (!returnValue)
if (followRfc)
if (pszResultPortStart)
intPortOut = 0;
if (rc == 0)
intPortOut = 0;
if (!pszRc)
if (!pszRc)
if (!pszRc)
if (!pszRc)
if (!pszRc)
pszIfIdOut++;
pszIfIdOut++;
*pBrackets = true;
*pEmbeddedV4 = true;
if (pszResultPortStart)
if (pszInternalPortStart)
DECLHIDDEN(int) rtStrToIpAddr6Str(const char *psz, char *pszAddrOut, size_t addrOutSize, char *pszPortOut, size_t portOutSize, bool followRfc)
return VERR_NOT_SUPPORTED;
return VERR_NOT_SUPPORTED;
pCurrent++;
if (!pGapTStart)
pOut++;
pOut++;
pOut++;
pOut++;
pCurrent++;
return VINF_SUCCESS;
static int rtNetIpv6CheckAddrStr(const char *psz, char *pszResultAddress, size_t resultAddressSize, bool addressOnly, bool followRfc)
int rc;
int rc2;
int returnValue;
return VERR_NO_TMP_MEMORY;
rc = rtStrParseAddrStr6(psz, strlen(psz), pszAddressOutLocal, memAllocMaxSize, NULL, pszIfIdOutLocal, memAllocMaxSize, NULL, NULL, followRfc);
if (rc == 0)
rc2 = rtStrToIpAddr6Str((const char *)pszAddressOutLocal, pszAddressRfcOutLocal, memAllocMaxSize, NULL, 0, followRfc);
if (rc2 != 0)
if (!returnValue && strlen(pszIfIdOutLocal) > 0) // the if identifier is copied over _ALWAYS_ && !addressOnly)
if (!pl)
if (!pl)
if (rc != 0)
if (pszAddressOutLocal)
if (pszIfIdOutLocal)
return returnValue;
unsigned cOctets = 0;
if (!pChar)
pNow++;
cOctets++;
pNow++;