diff --git a/legacy/evil/AUTHORS b/legacy/evil/AUTHORS index 125597df1f..e73fed1fdf 100644 --- a/legacy/evil/AUTHORS +++ b/legacy/evil/AUTHORS @@ -3,5 +3,5 @@ Main Authors: Tor Lillqvist (pipe function) Lance Fetters Vincent Richomme - Paul Vixie (ISC) (inet_pton function) - Daniel Stenberg (inet_pton function) + Paul Vixie (ISC) (inet_pton and inet_ntop functions) + Daniel Stenberg (inet_pton and inet_ntop functions) diff --git a/legacy/evil/ChangeLog b/legacy/evil/ChangeLog index 4dce120be6..632eb44f86 100644 --- a/legacy/evil/ChangeLog +++ b/legacy/evil/ChangeLog @@ -1,3 +1,11 @@ +2011-10-05 Vincent Torri + + * src/lib/evil_inet.c: + * src/lib/evil_inet.h: + * AUTHORS: + add inet_ntop() function. Implementation from c-ares library. + See AUTHORS. + 2011-09-14 Vincent Torri * src/lib/dlfcn/dlfcn.c: @@ -13,7 +21,7 @@ * src/lib/Evil.h: * src/lib/Makefile.am: * AUTHORS: - add inet_pton() function. Implementation from curl library. + add inet_pton() function. Implementation from c-ares library. See AUTHORS. 2011-02-27 Vincent Torri diff --git a/legacy/evil/src/lib/evil_inet.c b/legacy/evil/src/lib/evil_inet.c index fa3732a72f..46a0f6afb3 100644 --- a/legacy/evil/src/lib/evil_inet.c +++ b/legacy/evil/src/lib/evil_inet.c @@ -39,6 +39,8 @@ #include "evil_private.h" +# define SPRINTF(x) ((size_t)sprintf x) + #define ERRNO ((int)GetLastError()) #define SET_ERRNO(x) (SetLastError((DWORD)(x))) @@ -433,7 +435,8 @@ ares_inet_net_pton(int af, const char *src, void *dst, size_t size) } } -int evil_inet_pton(int af, const char *src, void *dst) +int +evil_inet_pton(int af, const char *src, void *dst) { int result; size_t size; @@ -448,7 +451,195 @@ int evil_inet_pton(int af, const char *src, void *dst) return -1; } result = ares_inet_net_pton(af, src, dst, size); - if (result == -1 && ERRNO == ENOENT) + if ((result == -1) && (ERRNO == ENOENT)) return 0; return (result > -1 ? 1 : -1); } + + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a unsigned char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const unsigned char *src, char *dst, size_t size) +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + + if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) + { + SET_ERRNO(ENOSPC); + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(const unsigned char *src, char *dst, size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; + char *tp; + struct { + long base; + long len; + } best, cur; + unsigned long words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof(words)); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + + best.base = -1; + cur.base = -1; + best.len = 0; + cur.len = 0; + + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) + { + if (words[i] == 0) + { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } + else + { + if (cur.base != -1) + { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) + { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) + { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) + { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) + { + if (!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + tp += SPRINTF((tp, "%lx", words[i])); + } + + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) + { + SET_ERRNO(ENOSPC); + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * note: + * On Windows we store the error in the thread errno, not + * in the winsock error code. This is to avoid loosing the + * actual last winsock error. So use macro ERRNO to fetch the + * errno this funtion sets when returning NULL, not SOCKERRNO. + * author: + * Paul Vixie, 1996. + */ +static const char * +ares_inet_ntop(int af, const void *src, char *dst, size_t size) +{ + switch (af) + { + case AF_INET: + return (inet_ntop4(src, dst, size)); + case AF_INET6: + return (inet_ntop6(src, dst, size)); + default: + SET_ERRNO(EAFNOSUPPORT); + return (NULL); + } + /* NOTREACHED */ +} + +const char *evil_inet_ntop(int af, const char *src, void *dst) +{ + const char *result; + size_t size; + + if (af == AF_INET) + size = sizeof(struct in_addr); + else if (af == AF_INET6) + size = sizeof(struct ares_in6_addr); + else + { + SET_ERRNO(EAFNOSUPPORT); + return NULL; + } + result = ares_inet_ntop(af, src, dst, size); + if ((result == NULL) && (ERRNO == ENOSPC)) + return NULL; + return result; +} diff --git a/legacy/evil/src/lib/evil_inet.h b/legacy/evil/src/lib/evil_inet.h index abc59478c1..46e0c8be90 100644 --- a/legacy/evil/src/lib/evil_inet.h +++ b/legacy/evil/src/lib/evil_inet.h @@ -32,6 +32,11 @@ EAPI int evil_inet_pton(int af, const char *src, void *dst); #define inet_pton(x,y,z) evil_inet_pton(x,y,z) +EAPI const char *evil_inet_ntop(int af, const char *src, void *dst); + +#define inet_ntop(x,y,z) evil_inet_ntop(x,y,z) + + /** * @}