Annotation of embedaddon/curl/lib/inet_ntop.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 1996-2019 Internet Software Consortium.
! 3: *
! 4: * Permission to use, copy, modify, and distribute this software for any
! 5: * purpose with or without fee is hereby granted, provided that the above
! 6: * copyright notice and this permission notice appear in all copies.
! 7: *
! 8: * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
! 9: * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
! 10: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
! 11: * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
! 12: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
! 13: * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
! 14: * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
! 15: * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17: /*
! 18: * Original code by Paul Vixie. "curlified" by Gisle Vanem.
! 19: */
! 20:
! 21: #include "curl_setup.h"
! 22:
! 23: #ifndef HAVE_INET_NTOP
! 24:
! 25: #ifdef HAVE_SYS_PARAM_H
! 26: #include <sys/param.h>
! 27: #endif
! 28: #ifdef HAVE_NETINET_IN_H
! 29: #include <netinet/in.h>
! 30: #endif
! 31: #ifdef HAVE_ARPA_INET_H
! 32: #include <arpa/inet.h>
! 33: #endif
! 34:
! 35: #include "inet_ntop.h"
! 36: #include "curl_printf.h"
! 37:
! 38: #define IN6ADDRSZ 16
! 39: #define INADDRSZ 4
! 40: #define INT16SZ 2
! 41:
! 42: /*
! 43: * Format an IPv4 address, more or less like inet_ntoa().
! 44: *
! 45: * Returns `dst' (as a const)
! 46: * Note:
! 47: * - uses no statics
! 48: * - takes a unsigned char* not an in_addr as input
! 49: */
! 50: static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
! 51: {
! 52: char tmp[sizeof("255.255.255.255")];
! 53: size_t len;
! 54:
! 55: DEBUGASSERT(size >= 16);
! 56:
! 57: tmp[0] = '\0';
! 58: (void)msnprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
! 59: ((int)((unsigned char)src[0])) & 0xff,
! 60: ((int)((unsigned char)src[1])) & 0xff,
! 61: ((int)((unsigned char)src[2])) & 0xff,
! 62: ((int)((unsigned char)src[3])) & 0xff);
! 63:
! 64: len = strlen(tmp);
! 65: if(len == 0 || len >= size) {
! 66: errno = ENOSPC;
! 67: return (NULL);
! 68: }
! 69: strcpy(dst, tmp);
! 70: return dst;
! 71: }
! 72:
! 73: #ifdef ENABLE_IPV6
! 74: /*
! 75: * Convert IPv6 binary address into presentation (printable) format.
! 76: */
! 77: static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
! 78: {
! 79: /*
! 80: * Note that int32_t and int16_t need only be "at least" large enough
! 81: * to contain a value of the specified size. On some systems, like
! 82: * Crays, there is no such thing as an integer variable with 16 bits.
! 83: * Keep this in mind if you think this function should have been coded
! 84: * to use pointer overlays. All the world's not a VAX.
! 85: */
! 86: char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
! 87: char *tp;
! 88: struct {
! 89: long base;
! 90: long len;
! 91: } best, cur;
! 92: unsigned long words[IN6ADDRSZ / INT16SZ];
! 93: int i;
! 94:
! 95: /* Preprocess:
! 96: * Copy the input (bytewise) array into a wordwise array.
! 97: * Find the longest run of 0x00's in src[] for :: shorthanding.
! 98: */
! 99: memset(words, '\0', sizeof(words));
! 100: for(i = 0; i < IN6ADDRSZ; i++)
! 101: words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
! 102:
! 103: best.base = -1;
! 104: cur.base = -1;
! 105: best.len = 0;
! 106: cur.len = 0;
! 107:
! 108: for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
! 109: if(words[i] == 0) {
! 110: if(cur.base == -1)
! 111: cur.base = i, cur.len = 1;
! 112: else
! 113: cur.len++;
! 114: }
! 115: else if(cur.base != -1) {
! 116: if(best.base == -1 || cur.len > best.len)
! 117: best = cur;
! 118: cur.base = -1;
! 119: }
! 120: }
! 121: if((cur.base != -1) && (best.base == -1 || cur.len > best.len))
! 122: best = cur;
! 123: if(best.base != -1 && best.len < 2)
! 124: best.base = -1;
! 125: /* Format the result. */
! 126: tp = tmp;
! 127: for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
! 128: /* Are we inside the best run of 0x00's? */
! 129: if(best.base != -1 && i >= best.base && i < (best.base + best.len)) {
! 130: if(i == best.base)
! 131: *tp++ = ':';
! 132: continue;
! 133: }
! 134:
! 135: /* Are we following an initial run of 0x00s or any real hex?
! 136: */
! 137: if(i != 0)
! 138: *tp++ = ':';
! 139:
! 140: /* Is this address an encapsulated IPv4?
! 141: */
! 142: if(i == 6 && best.base == 0 &&
! 143: (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
! 144: if(!inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp))) {
! 145: errno = ENOSPC;
! 146: return (NULL);
! 147: }
! 148: tp += strlen(tp);
! 149: break;
! 150: }
! 151: tp += msnprintf(tp, 5, "%lx", words[i]);
! 152: }
! 153:
! 154: /* Was it a trailing run of 0x00's?
! 155: */
! 156: if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
! 157: *tp++ = ':';
! 158: *tp++ = '\0';
! 159:
! 160: /* Check for overflow, copy, and we're done.
! 161: */
! 162: if((size_t)(tp - tmp) > size) {
! 163: errno = ENOSPC;
! 164: return (NULL);
! 165: }
! 166: strcpy(dst, tmp);
! 167: return dst;
! 168: }
! 169: #endif /* ENABLE_IPV6 */
! 170:
! 171: /*
! 172: * Convert a network format address to presentation format.
! 173: *
! 174: * Returns pointer to presentation format address (`buf').
! 175: * Returns NULL on error and errno set with the specific
! 176: * error, EAFNOSUPPORT or ENOSPC.
! 177: *
! 178: * On Windows we store the error in the thread errno, not
! 179: * in the winsock error code. This is to avoid losing the
! 180: * actual last winsock error. So when this function returns
! 181: * NULL, check errno not SOCKERRNO.
! 182: */
! 183: char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
! 184: {
! 185: switch(af) {
! 186: case AF_INET:
! 187: return inet_ntop4((const unsigned char *)src, buf, size);
! 188: #ifdef ENABLE_IPV6
! 189: case AF_INET6:
! 190: return inet_ntop6((const unsigned char *)src, buf, size);
! 191: #endif
! 192: default:
! 193: errno = EAFNOSUPPORT;
! 194: return NULL;
! 195: }
! 196: }
! 197: #endif /* HAVE_INET_NTOP */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>