15ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/*
25ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Copyright (C) 1996-2001  Internet Software Consortium.
35ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
45ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Permission to use, copy, modify, and distribute this software for any
55ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * purpose with or without fee is hereby granted, provided that the above
65ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * copyright notice and this permission notice appear in all copies.
75ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
85ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
95ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
105ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
115ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
125ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
135ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
145ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
155ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
165ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen */
175ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/*
185ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Original code by Paul Vixie. "curlified" by Gisle Vanem.
195ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen */
205ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
21e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "curl_setup.h"
225ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
235ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#ifndef HAVE_INET_NTOP
245ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
255ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#ifdef HAVE_SYS_PARAM_H
265ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include <sys/param.h>
275ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif
285ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#ifdef HAVE_NETINET_IN_H
295ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include <netinet/in.h>
305ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif
315ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#ifdef HAVE_ARPA_INET_H
325ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include <arpa/inet.h>
335ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif
345ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
355ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include "inet_ntop.h"
368f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo#include "curl_printf.h"
375ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
385ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#define IN6ADDRSZ       16
395ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#define INADDRSZ         4
405ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#define INT16SZ          2
415ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
425ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/*
435ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Format an IPv4 address, more or less like inet_ntoa().
445ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
455ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Returns `dst' (as a const)
465ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Note:
475ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *  - uses no statics
485ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *  - takes a unsigned char* not an in_addr as input
495ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen */
505ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsenstatic char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
515ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen{
525ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  char tmp[sizeof "255.255.255.255"];
535ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  size_t len;
545ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
555ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  DEBUGASSERT(size >= 16);
565ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
575ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  tmp[0] = '\0';
585ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
598f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo                 ((int)((unsigned char)src[0])) & 0xff,
608f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo                 ((int)((unsigned char)src[1])) & 0xff,
618f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo                 ((int)((unsigned char)src[2])) & 0xff,
628f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo                 ((int)((unsigned char)src[3])) & 0xff);
635ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
645ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  len = strlen(tmp);
65e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(len == 0 || len >= size) {
6682be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes    errno = ENOSPC;
675ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    return (NULL);
685ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
695ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  strcpy(dst, tmp);
705ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  return dst;
715ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen}
725ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
735ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#ifdef ENABLE_IPV6
745ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/*
755ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Convert IPv6 binary address into presentation (printable) format.
765ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen */
775ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsenstatic char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
785ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen{
795ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /*
805ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   * Note that int32_t and int16_t need only be "at least" large enough
815ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   * to contain a value of the specified size.  On some systems, like
825ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   * Crays, there is no such thing as an integer variable with 16 bits.
835ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   * Keep this in mind if you think this function should have been coded
845ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   * to use pointer overlays.  All the world's not a VAX.
855ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   */
865ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
875ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  char *tp;
885ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  struct {
895ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    long base;
905ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    long len;
915ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  } best, cur;
925ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  unsigned long words[IN6ADDRSZ / INT16SZ];
935ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int i;
945ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
955ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Preprocess:
965ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   *  Copy the input (bytewise) array into a wordwise array.
975ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   *  Find the longest run of 0x00's in src[] for :: shorthanding.
985ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   */
995ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  memset(words, '\0', sizeof(words));
100e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  for(i = 0; i < IN6ADDRSZ; i++)
101e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
1025ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1035ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  best.base = -1;
1045ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  cur.base  = -1;
1055ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  best.len = 0;
1065ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  cur.len = 0;
1075ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
108e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
109e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    if(words[i] == 0) {
1105ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      if(cur.base == -1)
1115ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen        cur.base = i, cur.len = 1;
1125ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      else
1135ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen        cur.len++;
1145ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
115e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    else if(cur.base != -1) {
1165ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      if(best.base == -1 || cur.len > best.len)
117e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        best = cur;
1185ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      cur.base = -1;
1195ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
1205ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1215ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if((cur.base != -1) && (best.base == -1 || cur.len > best.len))
122e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    best = cur;
1235ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(best.base != -1 && best.len < 2)
124e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    best.base = -1;
125e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  /* Format the result. */
1265ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  tp = tmp;
127e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
128e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    /* Are we inside the best run of 0x00's? */
129e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    if(best.base != -1 && i >= best.base && i < (best.base + best.len)) {
1305ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      if(i == best.base)
131e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        *tp++ = ':';
1325ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      continue;
1335ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
1345ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1355ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    /* Are we following an initial run of 0x00s or any real hex?
1365ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen     */
1375ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(i != 0)
138e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      *tp++ = ':';
1395ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1405ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    /* Is this address an encapsulated IPv4?
1415ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen     */
1425ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(i == 6 && best.base == 0 &&
143e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
144486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo      if(!inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp))) {
14582be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes        errno = ENOSPC;
1465ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen        return (NULL);
1475ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      }
1485ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      tp += strlen(tp);
1495ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      break;
1505ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
1515ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    tp += snprintf(tp, 5, "%lx", words[i]);
1525ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1535ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1545ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Was it a trailing run of 0x00's?
1555ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   */
1565ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
1575ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen     *tp++ = ':';
1585ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  *tp++ = '\0';
1595ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1605ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Check for overflow, copy, and we're done.
1615ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   */
162e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if((size_t)(tp - tmp) > size) {
16382be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes    errno = ENOSPC;
1645ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    return (NULL);
1655ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1665ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  strcpy(dst, tmp);
1675ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  return dst;
1685ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen}
1695ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif  /* ENABLE_IPV6 */
1705ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1715ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/*
1725ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Convert a network format address to presentation format.
1735ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
1745ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Returns pointer to presentation format address (`buf').
1755ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Returns NULL on error and errno set with the specific
1765ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * error, EAFNOSUPPORT or ENOSPC.
1775ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
1785ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * On Windows we store the error in the thread errno, not
179e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * in the winsock error code. This is to avoid losing the
18082be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes * actual last winsock error. So when this function returns
18182be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes * NULL, check errno not SOCKERRNO.
1825ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen */
1835ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsenchar *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
1845ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen{
18582be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes  switch(af) {
1865ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  case AF_INET:
187cee0338be80bb81b15101686d6f60864455f1e6eElliott Hughes    return inet_ntop4((const unsigned char *)src, buf, size);
1885ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#ifdef ENABLE_IPV6
1895ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  case AF_INET6:
190cee0338be80bb81b15101686d6f60864455f1e6eElliott Hughes    return inet_ntop6((const unsigned char *)src, buf, size);
1915ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif
1925ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  default:
19382be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes    errno = EAFNOSUPPORT;
1945ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    return NULL;
1955ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1965ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen}
1975ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif  /* HAVE_INET_NTOP */
198