VirtualBox

Changeset 43214 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Sep 6, 2012 9:16:55 AM (12 years ago)
Author:
vboxsync
Message:

RTStrIsIpAddr[46] -> RTNetIsIpv\1AddrStr; made the buggers return bool like predicate functions shall.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/string/RTStrIPv6.cpp

    r43175 r43214  
    3636#include "internal/iprt.h"
    3737#include "internal/string.h"
     38
     39
     40/** @page pg_rtnetipv6_addr IPv6 Address Format
     41 *
     42 * IPv6 Addresses, their representation in text and other problems.
     43 *
     44 * The following is based on:
     45 *
     46 * - http://tools.ietf.org/html/rfc4291
     47 * - http://tools.ietf.org/html/rfc5952
     48 * - http://tools.ietf.org/html/rfc6052
     49 *
     50 *
     51 * Before you start using those functions, you should have an idea of
     52 * what you're dealing with, before you come and blame the functions...
     53 *
     54 * First of all, the address itself:
     55 *
     56 * An address is written like this: (READ THIS FINE MANUAL!)
     57 *
     58 * - 2001:db8:abc:def::1
     59 *
     60 * The characters between two colons are called a "hextet".
     61 * Each hextet consists of four characters and each IPv6 address
     62 * consists of a maximum of eight hextets. So a full blown address
     63 * would look like this:
     64 *
     65 * - 1111:2222:3333:4444:5555:6666:7777:8888
     66 *
     67 * The allowed characters are "0123456789abcdef". They have to be
     68 * lower case. Upper case is not allowed.
     69 *
     70 * *** Gaps and adress shortening
     71 *
     72 * If an address contains hextets that contain only "0"s, they
     73 * can be shortened, like this:
     74 *
     75 * - 1111:2222:0000:0000:0000:0000:7777:8888 -> 1111:2222::7777:8888
     76 *
     77 * The double colon represents the hextets that have been shortened "::".
     78 * The "::" will be called "gap" from now on.
     79 *
     80 * When shortening an address, there are some special rules that need to be applied:
     81 *
     82 * - Shorten always the longest group of hextets.
     83 *
     84 *   Let's say, you have this address: 2001:db8:0:0:0:1:0:0 then it has to be
     85 *   shortened to "2001:db8::1:0:0". Shortening to "2001:db8:0:0:0:1::" would
     86 *   return an error.
     87 *
     88 * - Two or more gaps the same size.
     89 *
     90 *   Let's say you have this address: 2001:db8:0:0:1:0:0:1. As you can see, there
     91 *   are two gaps, both the size of two hextets. If you shorten the last two hextets,
     92 *   you end up in pain, as the RFC forbids this, so the correct address is:
     93 *   "2001:db8::1:0:0:1"
     94 *
     95 * It's important to note that an address can only be shortened ONE TIME!
     96 * This is invalid: "2001:db8::1::1"
     97 *
     98 * *** The scope.
     99 *
     100 * Each address has a so called "scope" it is added to the end of the address,
     101 * separated by a percent sign "%". If there is no scope at the end, it defaults
     102 * to "0".
     103 *
     104 * So "2001:db8::1" is the same as "2001:db8::1%0".
     105 *
     106 * As in IPv6 all network interfaces can/should have the same address, the scope
     107 * gives you the ability to choose on which interface the system should listen.
     108 *
     109 * AFAIK, the scope can be used with unicast as well as link local addresses, but
     110 * it is mandatory with link local addresses (starting with fe80::).
     111 *
     112 * On Linux the default scope is the interface's name. On Windows it's just the index
     113 * of the interface. Run "route print -6" in the shell, to see the interface's index
     114 * on Winodows.
     115 *
     116 * All functions can deal with the scope, and DO NOT warn if you put garbage there.
     117 *
     118 * *** Port added to the IPv6 address
     119 *
     120 * There is only one way to add a port to an IPv6 address is to embed it in brackets:
     121 *
     122 * [2001:db8::1]:12345
     123 *
     124 * This gives you the address "2001:db8::1" and the port "12345".
     125 *
     126 * What also works, but is not recommended by rfc is to separate the port
     127 * by a dot:
     128 *
     129 * 2001:db8::1.12345
     130 *
     131 * It even works with embedded IPv4 addresses.
     132 *
     133 * *** Special addresses and how they are written
     134 *
     135 * The following are notations to represent "special addresses".
     136 *
     137 * "::" IN6ADDR_ANY
     138 * ":::123" IN6ADDR_ANY with port "123"
     139 * "[::]:123" IN6ADDR_ANY with port "123"
     140 * "[:::123]" -> NO. Not allowed and makes no sense
     141 * "::1" -> address of the loopback device (127.0.0.1 in v4)
     142 *
     143 * On systems with dual sockets, one can use so called embedded IPv4 addresses:
     144 *
     145 * "::ffff:192.168.1.1" results in the IPv6 address "::ffff:c0a8:0101" as two octets
     146 * of the IPv4 address will be converted to one hextet in the IPv6 address.
     147 *
     148 * The prefix of such addresses MUST BE "::ffff:", 10 bytes as zero and two bytes as 255.
     149 *
     150 * The so called IPv4-compatible IPv6 addresses are deprecated and no longer in use.
     151 *
     152 * *** Valid addresses and string
     153 *
     154 * If you use any of the IPv6 address functions, keep in mind, that those addresses
     155 * are all returning "valid" even if the underlying system (e.g. VNC) doesn't like
     156 * such strings.
     157 *
     158 * [2001:db8::1]
     159 * [2001:db8::1]:12345
     160 *
     161 * and so on. So to make sure you only pass the underlying software a pure IPv6 address
     162 * without any garbage, you should use the "outAddress" parameters to get a RFC compliant
     163 * address returned.
     164 *
     165 * So after reading the above, you'll start using the functions and see a bool called
     166 * "followRfc" which is true by default. This is what this bool does:
     167 *
     168 * The following addresses all represent the exact same address:
     169 *
     170 * 1 - 2001:db8::1
     171 * 2 - 2001:db8:0::1
     172 * 3 - 2001:0db8:0000:0000:0000:0000:0000:0001
     173 * 4 - 2001:DB8::1
     174 * 5 - [2001:db8::1]
     175 * 6 - [2001:db8:0::1]
     176 *
     177 * According to RFC 5952, number two, three, four and six are invalid.
     178 *
     179 * #2 - because there is a single hextet that hasn't been shortened
     180 *
     181 * #3 - because there has nothing been shortened (hextets 3 to 7) and
     182 *      there are leading zeros in at least one hextet ("0db8")
     183 *
     184 * #4 - all characters in an IPv6 address have to be lower case
     185 *
     186 * #6 - same as two but included in brackets
     187 *
     188 * If you follow RFC, the above addresses are not converted and an
     189 * error is returned. If you turn RFC off, you will get the expected
     190 * representation of the address.
     191 *
     192 * It's a nice way to convert "weird" addresses to rfc compliant addresses
     193 *
     194 */
     195
    38196
    39197/**
     
    9721130}
    9731131
    974 RTDECL(int) RTStrIsIpAddr6(const char *psz, char *pszResultAddress, size_t resultAddressSize, bool addressOnly, bool followRfc)
     1132
     1133/**
     1134 * Tests if the given string is a valid IPv6 address.
     1135 *
     1136 * @returns 0 if valid, some random number if not.  THIS IS NOT AN IPRT STATUS!
     1137 * @param psz                  The string to test
     1138 * @param pszResultAddress     plain address, optional read "valid addresses
     1139 *                             and strings" above.
     1140 * @param resultAddressSize    size of pszResultAddress
     1141 * @param addressOnly          return only the plain address (no scope)
     1142 *                             Ignored, and will always return the if id
     1143 */
     1144static int rtNetIpv6CheckAddrStr(const char *psz, char *pszResultAddress, size_t resultAddressSize, bool addressOnly, bool followRfc)
    9751145{
    9761146    int rc;
     
    10451215
    10461216}
    1047 RT_EXPORT_SYMBOL(RTStrIsIpAddr6);
    1048 
    1049 
    1050 RTDECL(int) RTStrIsIpAddr4(const char *psz)
     1217
     1218
     1219RTDECL(bool) RTNetIsIPv6AddrStr(const char *pszAddress)
    10511220{
    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 
     1221    return rtNetIpv6CheckAddrStr(pszAddress, NULL, 0, true, true);
     1222}
     1223RT_EXPORT_SYMBOL(RTNetIsIPv6AddrStr);
     1224
     1225
     1226RTDECL(bool) RTNetIsIPv4AddrStr(const char *pszAddress)
     1227{
     1228    static char const s_szIpV4Digits[] = "0123456789.";
     1229
     1230    size_t cchAddress = strlen(pszAddress);
     1231    if (cchAddress < 7 || cchAddress > 15)
     1232        return false;
     1233
     1234    const char *pStart, *pFrom, *pTo, *pNow;
     1235    pStart = pNow = pFrom = pTo = pszAddress;
     1236
     1237    unsigned cOctets = 0;
    10671238    while (*pNow != '\0')
    10681239    {
    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;
     1240        const char *pChar  = (const char *)memchr(s_szIpV4Digits, *pNow, sizeof(s_szIpV4Digits) - 1);
     1241        const char *pDigit = (const char *)memchr(s_szIpV4Digits, *pNow, sizeof(s_szIpV4Digits) - 2);
     1242        const char *pNext  = pNow + 1;
    10761243
    10771244        if (!pChar)
    1078             return -2;
     1245            return false;
    10791246
    10801247        if (pDigit && *pNext != '\0')
     
    10901257                pTo = pNow;
    10911258
    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++;
     1259            size_t cchSub = pTo - pFrom;
     1260            if (cchSub > 2)
     1261                return false;
     1262
     1263            char szDummy[4] = { 0, 0, 0, 0 };
     1264            memcpy(szDummy, pFrom, cchSub + 1);
     1265
     1266            int rc = RTStrToUInt8Ex(szDummy, NULL, 10, NULL);
     1267            if (rc != VINF_SUCCESS)
     1268                return false;
     1269
     1270            cOctets++;
     1271            if (cOctets > 4)
     1272                return false;
    11071273            pFrom = pNext;
    11081274        }
     
    11101276    }
    11111277
    1112     if (ulDots != 4) // yes, it's four
    1113         return -5;
    1114 
    1115     return 0;
     1278    if (cOctets != 4)
     1279        return false;
     1280
     1281    return true;
    11161282}
    1117 RT_EXPORT_SYMBOL(RTStrIsIpAddr4);
    1118 
     1283RT_EXPORT_SYMBOL(RTNetIsIPv4AddrStr);
     1284
Note: See TracChangeset for help on using the changeset viewer.

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