X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Finet_ntop.c;h=0e04d257742a2e12d27dbd5c3c31bb64cf359e9e;hb=7ef6c64e210ac0979d7e8ac69bc5b5208c2405ab;hp=752f0638745973bf4b36e42cb2fc3e4724c58df3;hpb=222b0486b7db1b09293e05512873d633440efcb3;p=gnulib.git diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c index 752f06387..0e04d2577 100644 --- a/lib/inet_ntop.c +++ b/lib/inet_ntop.c @@ -1,6 +1,22 @@ +/* inet_ntop.c -- convert IPv4 and IPv6 addresses from binary to text form + + Copyright (C) 2005-2006, 2008-2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + /* * Copyright (c) 1996-1999 by Internet Software Consortium. - * Copyright (c) 2005 Free Software Foundation, Inc. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,194 +32,229 @@ * SOFTWARE. */ -#ifdef HAVE_CONFIG_H -# include -#endif +#include /* Specification. */ -#include "inet_ntop.h" +#include + +/* Use this to suppress gcc's "...may be used before initialized" warnings. + Beware: The Code argument must not contain commas. */ +#ifndef IF_LINT +# ifdef lint +# define IF_LINT(Code) Code +# else +# define IF_LINT(Code) /* empty */ +# endif +#endif + +#if HAVE_DECL_INET_NTOP + +# undef inet_ntop + +const char * +rpl_inet_ntop (int af, const void *restrict src, + char *restrict dst, socklen_t cnt) +{ + return inet_ntop (af, src, dst, cnt); +} + +#else -#include -#include -#include +# include +# include +# include -#define NS_IN6ADDRSZ 16 -#define NS_INT16SZ 2 +# define NS_IN6ADDRSZ 16 +# define NS_INT16SZ 2 /* * WARNING: Don't even consider trying to compile this on a system where * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ -typedef int verify_int_size[2 * sizeof(int) - 7]; +typedef int verify_int_size[4 <= sizeof (int) ? 1 : -1]; -#if HAVE_IPV4 static const char *inet_ntop4 (const unsigned char *src, char *dst, socklen_t size); -#endif -#if HAVE_IPV6 +# if HAVE_IPV6 static const char *inet_ntop6 (const unsigned char *src, char *dst, socklen_t size); -#endif +# endif /* char * * inet_ntop(af, src, dst, size) - * convert a network format address to presentation format. + * convert a network format address to presentation format. * return: - * pointer to presentation format address (`dst'), or NULL (see errno). + * pointer to presentation format address ('dst'), or NULL (see errno). * author: - * Paul Vixie, 1996. + * Paul Vixie, 1996. */ const char * -inet_ntop(af, src, dst, size) - int af; - const void *src; - char *dst; - socklen_t size; +inet_ntop (int af, const void *restrict src, + char *restrict dst, socklen_t cnt) { - switch (af) { + switch (af) + { +# if HAVE_IPV4 + case AF_INET: + return (inet_ntop4 (src, dst, cnt)); +# endif -#if HAVE_IPV4 - case AF_INET: - return (inet_ntop4(src, dst, size)); -#endif +# if HAVE_IPV6 + case AF_INET6: + return (inet_ntop6 (src, dst, cnt)); +# endif -#if HAVE_IPV6 - case AF_INET6: - return (inet_ntop6(src, dst, size)); -#endif - default: - errno = EAFNOSUPPORT; - return (NULL); - } - /* NOTREACHED */ + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ } -#if HAVE_IPV4 - /* const char * * inet_ntop4(src, dst, size) - * format an IPv4 address + * format an IPv4 address * return: - * `dst' (as a const) + * 'dst' (as a const) * notes: - * (1) uses no statics - * (2) takes a u_char* not an in_addr as input + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input * author: - * Paul Vixie, 1996. + * Paul Vixie, 1996. */ static const char * -inet_ntop4(src, dst, size) - const unsigned char *src; - char *dst; - socklen_t size; +inet_ntop4 (const unsigned char *src, char *dst, socklen_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) { - errno = ENOSPC; - return (NULL); - } - return strcpy(dst, tmp); -} + char tmp[sizeof "255.255.255.255"]; + int len; -#endif + len = sprintf (tmp, "%u.%u.%u.%u", src[0], src[1], src[2], src[3]); + if (len < 0) + return NULL; -#if HAVE_IPV6 + if (len > size) + { + errno = ENOSPC; + return NULL; + } + + return strcpy (dst, tmp); +} + +# if HAVE_IPV6 /* const char * * inet_ntop6(src, dst, size) - * convert IPv6 binary address into presentation (printable) format + * convert IPv6 binary address into presentation (printable) format * author: - * Paul Vixie, 1996. + * Paul Vixie, 1996. */ static const char * -inet_ntop6(src, dst, size) - const unsigned char *src; - char *dst; - socklen_t size; +inet_ntop6 (const unsigned char *src, char *dst, socklen_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"], *tp; - struct { int base, len; } best, cur; - unsigned int 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 += 2) - words[i / 2] = (src[i] << 8) | src[i + 1]; - best.base = -1; - cur.base = -1; - 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, "%x", 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 ((socklen_t)(tp - tmp) > size) { - errno = ENOSPC; - return (NULL); - } - return strcpy(dst, tmp); + /* + * 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"], *tp; + struct + { + int base, len; + } best, cur; + unsigned int 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 += 2) + words[i / 2] = (src[i] << 8) | src[i + 1]; + best.base = -1; + cur.base = -1; + IF_LINT(best.len = 0); + IF_LINT(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; + } + { + int len = sprintf (tp, "%x", words[i]); + if (len < 0) + return NULL; + tp += len; + } + } + /* 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 ((socklen_t) (tp - tmp) > size) + { + errno = ENOSPC; + return NULL; + } + + return strcpy (dst, tmp); } +# endif + #endif