/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipcom_inet_ntop.c,v $ $Revision: 1.9.70.1 $ * $Source: /home/interpeak/CVSRoot/ipcom/src/ipcom_inet_ntop.c,v $ * $Author: jren $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipcom_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include "ipcom_clib.h" #include "ipcom_sock.h" #include "ipcom_sock6.h" /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* * Number of 16-bit parts in an IPv6 address */ #define IN6_16BIT_PART_CNT (sizeof (struct Ip_in6_addr) / sizeof (Ip_u16)) /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /******************************************************************************* * * ntopAfInetFmt - convert IPv4 address to string * * This routine convert a binary representation of an IPv4 address to a string * * RETURNS: pointer to the string, or IP_NULL if the buffer is too small * * ERRNO: N/A */ IP_STATIC const char * ntopAfInetFmt ( const void * addrPtr, /**< binary representation of Internet address */ char * str, /**< storage for the string representation */ Ip_size_t strLen, /**< the length of 'str' buffer */ const char * fmt /**< address format */ ) { const unsigned char * inAddr = (const unsigned char *)addrPtr; if (strLen <= (Ip_size_t)ipcom_snprintf (str, strLen, fmt, inAddr[0], inAddr[1], inAddr[2], inAddr[3])) { /* * The string buffer is not large enough */ str = IP_NULL; } return str; } /******************************************************************************* * * appendFmt - append a string generated from a format specifier * * This routine try to append a string using a format specifier as template * * RETURNS: a pointer to the first available character in the string, or IP_NULL * if the current string could not fit into the string buffer * * ERRNO: N/A */ IP_STATIC char * appendFmt ( char * str, Ip_size_t * strLen, const char * fmt, unsigned val ) { if (str != IP_NULL) { Ip_size_t charsRequired = (Ip_size_t)ipcom_snprintf (str, *strLen, fmt, val); if (*strLen > charsRequired) { *strLen -= charsRequired; str += charsRequired; } else { str = IP_NULL; } } return str; } /******************************************************************************* * * inet6ZeroRangeGet - get the longest range of zeros in an IPv6 address * * This routine get the index and length of the longest range of 16-bit zero * fields in an IPv6 address, only ranges of length two or longer may be * returned according to RFC5952. * * RETURNS: N/A * * ERRNO: N/A */ IP_STATIC void inet6ZeroRangeGet ( const Ip_u16 * in6, unsigned * zeroIdxPtr, unsigned * zeroLenPtr ) { unsigned idx; unsigned zIdx = IN6_16BIT_PART_CNT; unsigned zLen = 0; Ip_bool inZero = IP_FALSE; *zeroIdxPtr = zIdx; *zeroLenPtr = zLen; for (idx = 0; idx < IN6_16BIT_PART_CNT; idx++) { if (inZero) { if (in6[idx] == 0) { zLen++; } else { /* * According to chapter 4.2.3 in RFC5952, the first zero-range * must be selected if there are two ranges of the same * size. A zero-range field must only be replaced with a * double-colon if there is at least two consecutive zero * fields. */ if (zLen > 1 && zLen > *zeroLenPtr) { *zeroIdxPtr = zIdx; *zeroLenPtr = zLen; } inZero = IP_FALSE; } } else { if (in6[idx] == 0) { inZero = IP_TRUE; zIdx = idx; zLen = 1; } } } if (zLen > 1 && zLen > *zeroLenPtr) { /* * This case may happen when the zero-range is at the end of the * IPv6-address. */ *zeroIdxPtr = zIdx; *zeroLenPtr = zLen; } } /******************************************************************************* * * hexFmt - return the format string for a hex16 value * * This routine return the format string to use for a hex16 value at a specific * index into an IPv6 address. * * RETURNS: a string format specifier * * ERRNO: N/A */ IP_STATIC const char * hexFmt ( unsigned idx, unsigned cnt ) { const char * fmt = "%x:"; if (1 + idx == cnt) { fmt = "%x"; } return fmt; } /******************************************************************************* * * ntopAfInet6Pure - create a string representation of an IPv6 address * * This routine try to create a string representation of the binary format of * an IPv6 address. * * RETURNS: a string representation of the IPv6 address, or IP_NULL if the string * buffer is not large enough * * ERRNO: N/A */ IP_STATIC const char * ntopAfInet6Pure ( const void * addrPtr, /**< binary representation of Internet address */ char * str, /**< storage for the string representation */ Ip_size_t strLen /**< the length of 'str' buffer */ ) { const Ip_u16 * addr16Be = (const Ip_u16 *)addrPtr; unsigned zeroIdx; unsigned zeroLen; unsigned idx; const char * repr = str; inet6ZeroRangeGet (addr16Be, &zeroIdx, &zeroLen); for (idx = 0; idx < zeroIdx; idx++) { str = appendFmt (str, &strLen, hexFmt (idx, zeroIdx), ip_ntohs (addr16Be[idx])); } if (zeroIdx < IN6_16BIT_PART_CNT) { str = appendFmt (str, &strLen, "::", 0); } for (idx = zeroIdx + zeroLen; idx < IN6_16BIT_PART_CNT; idx++) { str = appendFmt (str, &strLen, hexFmt (idx, IN6_16BIT_PART_CNT), ip_htons (addr16Be[idx])); } if (str == IP_NULL) { repr = IP_NULL; } return repr; } #ifdef IPCOM_USE_INET6 /******************************************************************************* * * ntopAfInet - convert IPv6 address to string * * This routine convert a binary representation of an IPv6 address to a string * * RETURNS: pointer to the string, or IP_NULL if the buffer is too small * * ERRNO: N/A */ IP_STATIC const char * ntopAfInet6 ( const void * addrPtr, /**< binary representation of Internet address */ char * str, /**< storage for the string representation */ Ip_size_t strLen /**< the length of 'str' buffer */ ) { struct Ip_in6_addr in6; const Ip_u16 * addr16Be = (const Ip_u16 *)&in6; const char * repr = IP_NULL; (void)ipcom_memcpy (&in6, addrPtr, sizeof in6); if (IP_IN6_IS_ADDR_V4COMPAT (&in6)) { /* * IPv4-compatible-IPv6 addresses has the format '::x.y.z.w' where the * dotted quad is the last 4 octets of the IPv6 address. */ repr = ntopAfInetFmt (addr16Be + 6, str, strLen, "::%u.%u.%u.%u"); } else if (IP_IN6_IS_ADDR_V4MAPPED (&in6)) { /* * IPv4-mapped-IPv6 addresses has the format '::ffff:x.y.z.w' where * the dotted quad is the last 4 octets of the IPv6 address. * * RFC5952 chapter 4.3 state that lowercase letters must be used when * representing hexadecimal numbers. */ repr = ntopAfInetFmt (addr16Be + 6, str, strLen, "::ffff:%u.%u.%u.%u"); } else { /* * IPv6 address without embedded IPv4 */ repr = ntopAfInet6Pure (&in6, str, strLen); } return repr; } #endif /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipcom_inet_ntop *=========================================================================== * Description: Converts the network address into a character string. * Parameters: family - The address family for the address to convert. * strptr - A pointer to the buffer that will receive the * string representation of the address. * len - The length of the strptr buffer. * Returns: The strptr value if the call was successful or IP_NULL * if failed (get error code from ipcom_errno). * */ IP_PUBLIC IP_CONST char * ipcom_inet_ntop(int family, IP_CONST void *addrptr, char *strptr, Ip_size_t len) { const char * repr = IP_NULL; Ip_bool afNoSupp = IP_FALSE; if (addrptr == IP_NULL || strptr == IP_NULL) return IP_NULL; switch (family) { #ifdef IPCOM_USE_INET case IP_AF_INET: repr = ntopAfInetFmt (addrptr, strptr, len, "%u.%u.%u.%u"); break; #endif #ifdef IPCOM_USE_INET6 case IP_AF_INET6: repr = ntopAfInet6 (addrptr, strptr, len); break; #endif default: afNoSupp = IP_TRUE; break; } if (repr == IP_NULL) { if (afNoSupp) { (void)ipcom_errno_set (IP_ERRNO_EAFNOSUPPORT); } else { (void)ipcom_errno_set (IP_ERRNO_ENOSPC); } } return repr; } /* **************************************************************************** * END OF FILE **************************************************************************** */