VirtualBox

Changeset 29834 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 27, 2010 9:03:34 AM (15 years ago)
Author:
vboxsync
Message:

Runtime: RTCidrStrToIPv4 changed to conform to rfc 4632 requirements. Test are changed accordingly. (see vbox/6797 for the issue)

Location:
trunk/src/VBox/Runtime
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/misc/cidr.cpp

    r28800 r29834  
    3737
    3838
    39 /**
    40  * Scan a digit of an IPv4 address.
    41  *
    42  * @returns IPRT status code.
    43  *
    44  * @param   iDigit     The index of the IPv4 digit to scan.
    45  * @param   psz        Pointer to the begin of the string.
    46  * @param   ppszNext   Pointer to variable that should be set pointing to the first invalid character. (output)
    47  * @param   pu8        Pointer to the digit to write (output).
    48  */
    49 static int scanIPv4Digit(int iDigit, const char *psz, char **ppszNext, uint8_t *pu8)
    50 {
    51     int rc = RTStrToUInt8Ex(psz, ppszNext, 10, pu8);
    52     if (   (   rc != VINF_SUCCESS
    53             && rc != VWRN_TRAILING_CHARS)
    54         || *pu8 > 254)
    55         return VERR_INVALID_PARAMETER;
    56 
    57     /* first digit cannot be 0 */
    58     if (   iDigit == 1
    59         && *pu8 < 1)
    60         return VERR_INVALID_PARAMETER;
    61 
    62     if (**ppszNext == '/')
    63         return VINF_SUCCESS;
    64 
    65     if (   iDigit != 4
    66         && (   **ppszNext == '\0'
    67             || **ppszNext != '.'))
    68         return VERR_INVALID_PARAMETER;
    69 
    70     return VINF_SUCCESS;
    71 }
    72 
    73 
    7439RTDECL(int) RTCidrStrToIPv4(const char *pszAddress, PRTIPV4ADDR pNetwork, PRTIPV4ADDR pNetmask)
    7540{
    7641    uint8_t cBits;
    77     uint8_t a;
    78     uint8_t b = 0;
    79     uint8_t c = 0;
    80     uint8_t d = 0;
     42    uint8_t addr[4];
     43    uint32_t u32Netmask;
     44    uint32_t u32Network;
    8145    const char *psz = pszAddress;
    8246    char *pszNext;
    83     int  rc;
    84 
    85     do
    86     {
    87         /* 1st digit */
    88         rc = scanIPv4Digit(1, psz, &pszNext, &a);
    89         if (RT_FAILURE(rc))
    90             return rc;
    91         if (*pszNext == '/')
    92             break;
    93         psz = pszNext + 1;
    94 
    95         /* 2nd digit */
    96         rc = scanIPv4Digit(2, psz, &pszNext, &b);
    97         if (RT_FAILURE(rc))
    98             return rc;
    99         if (*pszNext == '/')
    100             break;
    101         psz = pszNext + 1;
    102 
    103         /* 3rd digit */
    104         rc = scanIPv4Digit(3, psz, &pszNext, &c);
    105         if (RT_FAILURE(rc))
    106             return rc;
    107         if (*pszNext == '/')
    108             break;
    109         psz = pszNext + 1;
    110 
    111         /* 4th digit */
    112         rc = scanIPv4Digit(4, psz, &pszNext, &d);
    113         if (RT_FAILURE(rc))
    114             return rc;
    115     } while (0);
    116 
    117     if (*pszNext == '/')
    118     {
    119         psz = pszNext + 1;
    120         rc = RTStrToUInt8Ex(psz, &pszNext, 10, &cBits);
    121         if (rc != VINF_SUCCESS || cBits < 8 || cBits > 28)
     47    int  rc = VINF_SUCCESS;
     48    int cDelimiter = 0;
     49    int cDelimiterLimit = 0;
     50    if (   pszAddress == NULL
     51        || pNetwork == NULL
     52        || pNetmask == NULL)
     53        return VERR_INVALID_PARAMETER;
     54    char *pszNetmask = RTStrStr(psz, "/");
     55    *(uint32_t *)addr = 0;
     56    if (pszNetmask == NULL)
     57        cBits = 0;
     58    else
     59    {
     60        rc = RTStrToUInt8Ex(pszNetmask + 1, &pszNext, 10, &cBits);
     61        if (   RT_FAILURE(rc)
     62            || cBits > 32
     63            || rc != 0) /* No trailing symbols are accptable after the digit */
    12264            return VERR_INVALID_PARAMETER;
    12365    }
    124     else
    125         cBits = 0;
     66    u32Netmask = ~(uint32_t)((1<< (32 - cBits)) - 1);
    12667
    127     for (psz = pszNext; RT_C_IS_SPACE(*psz); psz++)
    128         /* nothing */;
    129     if (*psz != '\0')
     68    rc = RTStrToUInt8Ex(psz, &pszNext, 10, &addr[0]);
     69    if (RT_FAILURE(rc))
     70        return rc;
     71
     72    if (cBits < 9)
     73        cDelimiterLimit = 0;
     74    else if (cBits < 16)
     75        cDelimiterLimit = 1;
     76    else if (cBits < 25)
     77        cDelimiterLimit = 2;
     78    else if (cBits <= 32)
     79        cDelimiterLimit = 3;
     80
     81    rc = RTStrToUInt8Ex(psz, &pszNext, 10, &addr[cDelimiter]);
     82    while (RT_SUCCESS(rc))
     83    {
     84        if (*pszNext == '.')
     85            cDelimiter++;
     86        else if(cDelimiter >= cDelimiterLimit)
     87            break;
     88        else
     89            return VERR_INVALID_PARAMETER;
     90        rc = RTStrToUInt8Ex(pszNext + 1, &pszNext, 10, &addr[cDelimiter]);
     91        if (rc == VWRN_NUMBER_TOO_BIG)
     92            break;
     93    }
     94    if (   RT_FAILURE(rc)
     95        || rc == VWRN_NUMBER_TOO_BIG)
     96        return VERR_INVALID_PARAMETER;
     97    u32Network = RT_MAKE_U32_FROM_U8(addr[3], addr[2], addr[1], addr[0]);
     98    /* corner case: see rfc 790 page 2 and rfc 4632 page 6*/
     99    if (   addr[0] == 0
     100        && (   *(uint32_t *)addr != 0
     101            || u32Netmask == (uint32_t)~0))
    130102        return VERR_INVALID_PARAMETER;
    131103
    132     *pNetwork = RT_MAKE_U32_FROM_U8(d, c, b, a);
    133     *pNetmask = ~(((uint32_t)1 << (32 - cBits)) - 1);
     104    if ((u32Network & ~u32Netmask) != 0)
     105        return VERR_INVALID_PARAMETER;
     106   
     107    *pNetmask = u32Netmask;
     108    *pNetwork = u32Network;
    134109    return VINF_SUCCESS;
    135110}
  • trunk/src/VBox/Runtime/testcase/tstRTCidr.cpp

    r28800 r29834  
    6767    RTTestBanner(hTest);
    6868
     69    CHECKNETWORK("10.0.0/45",                VERR_INVALID_PARAMETER, 0, 0);
     70    CHECKNETWORK("10.0.0/-45",                VERR_INVALID_PARAMETER, 0, 0);
    6971    CHECKNETWORK("10.0.0/24",                VINF_SUCCESS, 0x0A000000, 0xFFFFFF00);
    7072    CHECKNETWORK("10.0.0/8",                 VINF_SUCCESS, 0x0A000000, 0xFF000000);
    7173    CHECKNETWORK("10.0.0./24",     VERR_INVALID_PARAMETER,          0,          0);
    7274    CHECKNETWORK("0.1.0/24",       VERR_INVALID_PARAMETER,          0,          0);
    73     CHECKNETWORK("10.255.0.0/24",  VERR_INVALID_PARAMETER,          0,          0);
     75    /* vvl: (changed exp to VINF_SUCCESS) according to rfc 4632 s3.1: n.n.n.0/24, where n is an 8-bit decimal octet value*/
     76    CHECKNETWORK("10.255.0.0/24",  VINF_SUCCESS,          0x0AFF0000,          0xFFFFFF00);
    7477    CHECKNETWORK("10.1234.0.0/24", VERR_INVALID_PARAMETER,          0,          0);
    7578    CHECKNETWORK("10.256.0.0/24",  VERR_INVALID_PARAMETER,          0,          0);
    7679    CHECKNETWORK("10.0.0/3",       VERR_INVALID_PARAMETER,          0,          0);
    77     CHECKNETWORK("10.1.2.3/8",               VINF_SUCCESS, 0x0A010203, 0xFF000000);
     80    /* vvl: (changed exp to VERR_INVALID_PARAMETER) according to rfc 4632 s3.1: legacy "Class A" is n.0.0.0/8 */
     81    CHECKNETWORK("10.1.2.3/8",               VERR_INVALID_PARAMETER, 0,         0);
     82    CHECKNETWORK("10.1.2.4/30",               VINF_SUCCESS, 0x0A010204, 0xFFFFFFFC);
    7883    CHECKNETWORK("10.0.0/29",      VERR_INVALID_PARAMETER,          0,          0);
    7984    CHECKNETWORK("10.0.0/240",     VERR_INVALID_PARAMETER,          0,          0);
    8085    CHECKNETWORK("10.0.0/24.",     VERR_INVALID_PARAMETER,          0,          0);
    81     CHECKNETWORK("10.1.2/16",                VINF_SUCCESS, 0x0A010200, 0xFFFF0000);
     86    /* vvl: (changed exp to VERR_INVALID_PARAMETER) according to rfc 4632 s3.1: legacy "Class B" is n.n.0.0/16 */
     87    CHECKNETWORK("10.1.2/16",      VERR_INVALID_PARAMETER,          0,          0);
    8288    CHECKNETWORK("1.2.3.4",                  VINF_SUCCESS, 0x01020304, 0xFFFFFFFF);
     89    CHECKNETWORK("10.1.255/24",            VINF_SUCCESS, 0x0A01FF00, 0xFFFFFF00);
     90    CHECKNETWORK("10.1.254/24",            VINF_SUCCESS, 0x0A01FE00, 0xFFFFFF00);
     91    CHECKNETWORK("10.255.1/24",            VINF_SUCCESS, 0x0AFF0100, 0xFFFFFF00);
    8392
    8493    return RTTestSummaryAndDestroy(hTest);
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