inet_ntop.c revision b586eb44084ba19b82d26ce20b7d741ac19d5331
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson/*
ff2d95be3d5e0350c5b457582cdb08869fc17789Tinderbox User * Copyright (C) 1996-2001 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Permission to use, copy, modify, and distribute this software for any
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * purpose with or without fee is hereby granted, provided that the above
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * copyright notice and this permission notice appear in all copies.
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson *
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
135bcc2e42a94543f11af2a4196b13552ab46d89Automatic Updater * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#if defined(LIBC_SCCS) && !defined(lint)
f44202ab640d22e17b4c74bdad7817622918bd27Mark Andrewsstatic char rcsid[] =
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson "$Id: inet_ntop.c,v 1.12 2001/01/25 20:10:01 gson Exp $";
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington#endif /* LIBC_SCCS and not lint */
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <config.h>
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson#include <errno.h>
7dde2780aeae0da4e965d823578a604d8ce1215fAndreas Gustafsson#include <stdio.h>
7dde2780aeae0da4e965d823578a604d8ce1215fAndreas Gustafsson#include <string.h>
f5862b6f22761d83c230e17f7d443211df19e52cBrian Wellington
9259fed3d8ac5d1efa9b5a647969e40c9c934484Andreas Gustafsson#include <isc/net.h>
9259fed3d8ac5d1efa9b5a647969e40c9c934484Andreas Gustafsson
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson#define NS_INT16SZ 2
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews#define NS_IN6ADDRSZ 16
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews/*
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews * WARNING: Don't even consider trying to compile this on a system where
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews */
4e1d3e67cdc76609bad5f0310ac48de10b442b9fMark Andrews
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafssonstatic const char *inet_ntop4(const unsigned char *src, char *dst,
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson size_t size);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson#ifdef AF_INET6
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellingtonstatic const char *inet_ntop6(const unsigned char *src, char *dst,
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews size_t size);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson#endif
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington/* char *
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington * isc_net_ntop(af, src, dst, size)
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington * convert a network format address to presentation format.
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews * return:
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews * pointer to presentation format address (`dst'), or NULL (see errno).
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * author:
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington * Paul Vixie, 1996.
4e1d3e67cdc76609bad5f0310ac48de10b442b9fMark Andrews */
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellingtonconst char *
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellingtonisc_net_ntop(int af, const void *src, char *dst, size_t size)
4e1d3e67cdc76609bad5f0310ac48de10b442b9fMark Andrews{
9df7d74e421cf715c6e3cbbad2aba6d33a5d1c9bBrian Wellington switch (af) {
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson case AF_INET:
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington return (inet_ntop4(src, dst, size));
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington#ifdef AF_INET6
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington case AF_INET6:
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington return (inet_ntop6(src, dst, size));
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington#endif
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington default:
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington errno = EAFNOSUPPORT;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington return (NULL);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson }
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence /* NOTREACHED */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence}
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington/* const char *
6f7abb89ec22aef5eda40ed60fcf605a42b78d4dMark Andrews * inet_ntop4(src, dst, size)
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington * format an IPv4 address
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence * return:
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * `dst' (as a const)
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉 * notes:
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * (1) uses no statics
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * (2) takes a unsigned char* not an in_addr as input
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * author:
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Paul Vixie, 1996.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencestatic const char *
fb64c9cf757422c5473764521ffc7c6111b8c821Brian Wellingtoninet_ntop4(const unsigned char *src, char *dst, size_t size)
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews{
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews static const char *fmt = "%u.%u.%u.%u";
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington char tmp[sizeof "255.255.255.255"];
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews if ((size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size)
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington {
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington errno = ENOSPC;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson return (NULL);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson }
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington strcpy(dst, tmp);
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson return (dst);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson}
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson/* const char *
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * isc_inet_ntop6(src, dst, size)
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence * convert IPv6 binary address into presentation (printable) format
734ae1f7c6abafe1f1ca164aad7a3dd01ee82cbdBrian Wellington * author:
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * Paul Vixie, 1996.
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence#ifdef AF_INET6
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafssonstatic const char *
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellingtoninet_ntop6(const unsigned char *src, char *dst, size_t size)
7a184cd4e5a54a4e530f9bff8a4e46be392d0b52Brian Wellington{
fb01226bcd598c36b5edc566489c890c39f03ed3Brian Wellington /*
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews * Note that int32_t and int16_t need only be "at least" large enough
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * to contain a value of the specified size. On some systems, like
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * Crays, there is no such thing as an integer variable with 16 bits.
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * Keep this in mind if you think this function should have been coded
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * to use pointer overlays. All the world's not a VAX.
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews */
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews struct { int base, len; } best, cur;
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
c6d4f781529d2f28693546b25b2967d44ec89e60Mark Andrews int i;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington /*
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * Preprocess:
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * Copy the input (bytewise) array into a wordwise array.
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington * Find the longest run of 0x00's in src[] for :: shorthanding.
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington */
26a5f97dd8770ced729025488091b77d8beb0ab6Brian Wellington memset(words, '\0', sizeof words);
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington for (i = 0; i < NS_IN6ADDRSZ; i++)
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson best.base = -1;
9df7d74e421cf715c6e3cbbad2aba6d33a5d1c9bBrian Wellington cur.base = -1;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson if (words[i] == 0) {
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson if (cur.base == -1)
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson cur.base = i, cur.len = 1;
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews else
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington cur.len++;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson } else {
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews if (cur.base != -1) {
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews if (best.base == -1 || cur.len > best.len)
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson best = cur;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson cur.base = -1;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington }
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington }
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt }
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (cur.base != -1) {
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington if (best.base == -1 || cur.len > best.len)
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington best = cur;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington }
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington if (best.base != -1 && best.len < 2)
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington best.base = -1;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson /*
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson * Format the result.
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson */
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson tp = tmp;
c885fad9b8bf204ae9e62c9acb0321e2bcca30a4Andreas Gustafsson for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington /* Are we inside the best run of 0x00's? */
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington if (best.base != -1 && i >= best.base &&
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington i < (best.base + best.len)) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (i == best.base)
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington *tp++ = ':';
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington continue;
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington }
90c099e88e9f16bfee9edee3ac1a51fc98843772Brian Wellington /* Are we following an initial run of 0x00s or any real hex? */
8c7eaac6bbcc9746afe8f57b60bb964745c01eafAndreas Gustafsson if (i != 0)
8c7eaac6bbcc9746afe8f57b60bb964745c01eafAndreas Gustafsson *tp++ = ':';
8c7eaac6bbcc9746afe8f57b60bb964745c01eafAndreas Gustafsson /* Is this address an encapsulated IPv4? */
c885fad9b8bf204ae9e62c9acb0321e2bcca30a4Andreas Gustafsson if (i == 6 && best.base == 0 &&
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson if (!inet_ntop4(src+12, tp,
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson sizeof tmp - (tp - tmp)))
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson return (NULL);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews tp += strlen(tp);
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson break;
f93d33e24fdf76eb2558168f018b8992bcfc5681Andreas Gustafsson }
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 ((size_t)(tp - tmp) > size) {
errno = ENOSPC;
return (NULL);
}
strcpy(dst, tmp);
return (dst);
}
#endif /* AF_INET6 */