diff --git a/engine/common/ipv6text.c b/engine/common/ipv6text.c index c4062c56..edcd0937 100644 --- a/engine/common/ipv6text.c +++ b/engine/common/ipv6text.c @@ -177,7 +177,9 @@ bool ParseIPv6Addr( const char *pszText, unsigned char *pOutIP, int *pOutPort, u { // Next thing must be a quad, or end of input. Is it a quad? int quadDigit = ParseIPv6Addr_HexDigitVal( *s ); + const char *pszStartQuad; int quad; + if ( quadDigit < 0 ) { if ( bQuadMustFollow ) @@ -189,6 +191,7 @@ bool ParseIPv6Addr( const char *pszText, unsigned char *pOutIP, int *pOutPort, u if ( d >= pEndIP ) return false; + pszStartQuad = s; ++s; quad = quadDigit; @@ -214,6 +217,60 @@ bool ParseIPv6Addr( const char *pszText, unsigned char *pOutIP, int *pOutPort, u } } + // Check if we hit a period, which would happen if we + // have an IPv4 dotted decimal. For example, "::ffff:192.168.1.210" + if ( *s == '.' ) + { + // Make sure we would have room to store four more bytes. + unsigned char *pEndDottedDecimal = d+4; + if ( pEndDottedDecimal > pEndIP ) + return false; + + // Parse 4 octets + s = pszStartQuad; + for (;;) + { + + // Parse 1-3 decimal digits + int octet = ParseIPv6Addr_DecimalDigitVal( *s ); + int dig; + + if ( octet < 0 ) + return false; + ++s; + dig = ParseIPv6Addr_DecimalDigitVal( *s ); + if ( dig >= 0 ) + { + ++s; + octet = octet*10 + dig; + dig = ParseIPv6Addr_DecimalDigitVal( *s ); + if ( dig >= 0 ) + { + ++s; + octet = octet*10 + dig; + + // Make sure value is in range. + if ( octet > 255 ) + return false; + } + } + *(d++) = (unsigned char)octet; + + // All done? + if ( d >= pEndDottedDecimal ) + break; + + // Next thing must be dot dot separator + if ( *s != '.' ) + return false; + + // Eat dot + ++s; + } + + break; + } + // Stash it in the next slot, ignoring for now the issue // of compressed zeros *(d++) = (unsigned char)( quad >> 8 ); @@ -288,7 +345,7 @@ bool ParseIPv6Addr( const char *pszText, unsigned char *pOutIP, int *pOutPort, u int nScopeDigit; ++s; - + nScopeDigit = ParseIPv6Addr_DecimalDigitVal( *s ); if ( nScopeDigit < 0 ) return false; diff --git a/engine/common/ipv6text.h b/engine/common/ipv6text.h index 088f45ea..6ed0f57f 100644 --- a/engine/common/ipv6text.h +++ b/engine/common/ipv6text.h @@ -25,8 +25,10 @@ extern "C" { extern void IPv6IPToString( char *pszOutText, const unsigned char *ip ); /// Format IPv6 IP and port to string. This uses the recommended -/// bracket notation, eg [1234::1]:12345. Your buffer must be +/// bracket notation, eg [1234::1]:12345. Your buffer MUST be /// at least k_ncchMaxIPV6AddrStringWithPort bytes. +/// +/// If the scope is zero, it is not printed. extern void IPv6AddrToString( char *pszOutText, const unsigned char *ip, uint16_t port, uint32_t scope ); /// Parse IPv6 address string. Returns true if parsed OK. Returns false @@ -41,7 +43,7 @@ extern void IPv6AddrToString( char *pszOutText, const unsigned char *ip, uint16_ /// /// Leading and trailing whitespace is OK around the entire string, /// but not internal whitespace. The different methods for separating the -/// port in RFC5952 are supported section 6, except the ambiguous case +/// port in RFC5952 section 6 are supported, except the ambiguous case /// of a colon to separate the port, when the IP contains a double-colon. /// Brackets around an IP are OK, even if there is no port. ///