1 /* 2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (c) 1996-1999 by Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #if defined(LIBC_SCCS) && !defined(lint) 19 static const char rcsid[] = "$Id: inet_ntop.c,v 1.5 2005/11/03 22:59:52 marka Exp $"; 20 #endif /* LIBC_SCCS and not lint */ 21 22 #include "port_before.h" 23 24 #include <sys/param.h> 25 #include <sys/types.h> 26 #include <sys/socket.h> 27 28 #include <netinet/in.h> 29 #include "arpa/inet.h" 30 #include <arpa/nameser.h> 31 32 #include <errno.h> 33 #include <stdio.h> 34 #include <string.h> 35 36 #include "port_after.h" 37 38 #ifdef SPRINTF_CHAR 39 # define SPRINTF(x) strlen(sprintf/**/x) 40 #else 41 # define SPRINTF(x) ((size_t)sprintf x) 42 #endif 43 44 /*% 45 * WARNING: Don't even consider trying to compile this on a system where 46 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 47 */ 48 49 static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size)); 50 static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size)); 51 52 /* char * 53 * inet_ntop(af, src, dst, size) 54 * convert a network format address to presentation format. 55 * return: 56 * pointer to presentation format address (`dst'), or NULL (see errno). 57 * author: 58 * Paul Vixie, 1996. 59 */ 60 const char * 61 inet_ntop(af, src, dst, size) 62 int af; 63 const void *src; 64 char *dst; 65 socklen_t size; 66 { 67 switch (af) { 68 case AF_INET: 69 return (inet_ntop4(src, dst, size)); 70 case AF_INET6: 71 return (inet_ntop6(src, dst, size)); 72 default: 73 errno = EAFNOSUPPORT; 74 return (NULL); 75 } 76 /* NOTREACHED */ 77 } 78 79 /* const char * 80 * inet_ntop4(src, dst, size) 81 * format an IPv4 address 82 * return: 83 * `dst' (as a const) 84 * notes: 85 * (1) uses no statics 86 * (2) takes a u_char* not an in_addr as input 87 * author: 88 * Paul Vixie, 1996. 89 */ 90 static const char * 91 inet_ntop4(src, dst, size) 92 const u_char *src; 93 char *dst; 94 size_t size; 95 { 96 static const char fmt[] = "%u.%u.%u.%u"; 97 char tmp[sizeof "255.255.255.255"]; 98 99 if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) { 100 errno = ENOSPC; 101 return (NULL); 102 } 103 strcpy(dst, tmp); 104 return (dst); 105 } 106 107 /* const char * 108 * inet_ntop6(src, dst, size) 109 * convert IPv6 binary address into presentation (printable) format 110 * author: 111 * Paul Vixie, 1996. 112 */ 113 static const char * 114 inet_ntop6(src, dst, size) 115 const u_char *src; 116 char *dst; 117 size_t size; 118 { 119 /* 120 * Note that int32_t and int16_t need only be "at least" large enough 121 * to contain a value of the specified size. On some systems, like 122 * Crays, there is no such thing as an integer variable with 16 bits. 123 * Keep this in mind if you think this function should have been coded 124 * to use pointer overlays. All the world's not a VAX. 125 */ 126 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; 127 struct { int base, len; } best, cur; 128 u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; 129 int i; 130 131 /* 132 * Preprocess: 133 * Copy the input (bytewise) array into a wordwise array. 134 * Find the longest run of 0x00's in src[] for :: shorthanding. 135 */ 136 memset(words, '\0', sizeof words); 137 for (i = 0; i < NS_IN6ADDRSZ; i++) 138 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); 139 best.base = -1; 140 best.len = 0; 141 cur.base = -1; 142 cur.len = 0; 143 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { 144 if (words[i] == 0) { 145 if (cur.base == -1) 146 cur.base = i, cur.len = 1; 147 else 148 cur.len++; 149 } else { 150 if (cur.base != -1) { 151 if (best.base == -1 || cur.len > best.len) 152 best = cur; 153 cur.base = -1; 154 } 155 } 156 } 157 if (cur.base != -1) { 158 if (best.base == -1 || cur.len > best.len) 159 best = cur; 160 } 161 if (best.base != -1 && best.len < 2) 162 best.base = -1; 163 164 /* 165 * Format the result. 166 */ 167 tp = tmp; 168 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { 169 /* Are we inside the best run of 0x00's? */ 170 if (best.base != -1 && i >= best.base && 171 i < (best.base + best.len)) { 172 if (i == best.base) 173 *tp++ = ':'; 174 continue; 175 } 176 /* Are we following an initial run of 0x00s or any real hex? */ 177 if (i != 0) 178 *tp++ = ':'; 179 /* Is this address an encapsulated IPv4? */ 180 if (i == 6 && best.base == 0 && (best.len == 6 || 181 (best.len == 7 && words[7] != 0x0001) || 182 (best.len == 5 && words[5] == 0xffff))) { 183 if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) 184 return (NULL); 185 tp += strlen(tp); 186 break; 187 } 188 tp += SPRINTF((tp, "%x", words[i])); 189 } 190 /* Was it a trailing run of 0x00's? */ 191 if (best.base != -1 && (best.base + best.len) == 192 (NS_IN6ADDRSZ / NS_INT16SZ)) 193 *tp++ = ':'; 194 *tp++ = '\0'; 195 196 /* 197 * Check for overflow, copy, and we're done. 198 */ 199 if ((size_t)(tp - tmp) > size) { 200 errno = ENOSPC; 201 return (NULL); 202 } 203 strcpy(dst, tmp); 204 return (dst); 205 } 206 207 #ifdef _LIBC 208 /* 209 * Weak aliases for applications that use certain private entry points, 210 * and fail to include <arpa/inet.h>. 211 */ 212 #undef inet_ntop 213 __weak_reference(__inet_ntop, inet_ntop); 214 #endif 215 /*! \file */ 216