net-snmp
5.4.1
|
00001 /* Id: inet_ntop.c,v 1.4 2001/04/17 07:53:47 lukem Exp */ 00002 /* $NetBSD: inet_ntop.c,v 1.9 2000/01/22 22:19:16 mycroft Exp $ */ 00003 00004 /* Copyright (c) 1996 by Internet Software Consortium. 00005 * 00006 * Permission to use, copy, modify, and distribute this software for any 00007 * purpose with or without fee is hereby granted, provided that the above 00008 * copyright notice and this permission notice appear in all copies. 00009 * 00010 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 00011 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 00012 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 00013 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 00014 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 00015 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 00016 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 00017 * SOFTWARE. 00018 */ 00019 00020 #include <net-snmp/net-snmp-config.h> 00021 00022 #ifndef HAVE_INET_NTOP 00023 00024 #if HAVE_ARPA_NAMESER_H 00025 #include <arpa/nameser.h> 00026 #endif 00027 00028 /* 00029 * Net-SNMP Win32 additions 00030 */ 00031 #if defined(HAVE_WINSOCK_H) || defined(cygwin) 00032 #include <winsock2.h> 00033 #include <ws2tcpip.h> 00034 #include <errno.h> 00035 #include <stdio.h> 00036 #endif 00037 00038 #ifndef EAFNOSUPPORT 00039 #define EAFNOSUPPORT WSAEAFNOSUPPORT 00040 #endif 00041 /* 00042 * End of Net-SNMP Win32 additions 00043 */ 00044 00045 #ifndef IN6ADDRSZ 00046 #define IN6ADDRSZ 16 00047 #endif 00048 00049 #ifndef INT16SZ 00050 #define INT16SZ 2 00051 #endif 00052 00053 #ifdef SPRINTF_CHAR 00054 # define SPRINTF(x) strlen(sprintfx) 00055 #else 00056 # define SPRINTF(x) ((size_t)sprintf x) 00057 #endif 00058 00059 /* 00060 * WARNING: Don't even consider trying to compile this on a system where 00061 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 00062 */ 00063 00064 static const char *inet_ntop4(const u_char *src, char *dst, size_t size); 00065 #ifdef NETSNMP_ENABLE_IPV6 00066 static const char *inet_ntop6(const u_char *src, char *dst, size_t size); 00067 #endif /* NETSNMP_ENABLE_IPV6 */ 00068 00069 /* char * 00070 * inet_ntop(af, src, dst, size) 00071 * convert a network format address to presentation format. 00072 * return: 00073 * pointer to presentation format address (`dst'), or NULL (see errno). 00074 * author: 00075 * Paul Vixie, 1996. 00076 */ 00077 const char * 00078 inet_ntop(af, src, dst, size) 00079 int af; 00080 const void *src; 00081 char *dst; 00082 size_t size; 00083 { 00084 00085 switch (af) { 00086 case AF_INET: 00087 return (inet_ntop4(src, dst, size)); 00088 #ifdef NETSNMP_ENABLE_IPV6 00089 case AF_INET6: 00090 return (inet_ntop6(src, dst, size)); 00091 #endif 00092 default: 00093 errno = EAFNOSUPPORT; 00094 return (NULL); 00095 } 00096 /* NOTREACHED */ 00097 } 00098 00099 /* const char * 00100 * inet_ntop4(src, dst, size) 00101 * format an IPv4 address, more or less like inet_ntoa() 00102 * return: 00103 * `dst' (as a const) 00104 * notes: 00105 * (1) uses no statics 00106 * (2) takes a u_char* not an in_addr as input 00107 * author: 00108 * Paul Vixie, 1996. 00109 */ 00110 static const char * 00111 inet_ntop4(src, dst, size) 00112 const u_char *src; 00113 char *dst; 00114 size_t size; 00115 { 00116 static const char fmt[] = "%u.%u.%u.%u"; 00117 char tmp[sizeof "255.255.255.255"]; 00118 00119 if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) { 00120 errno = ENOSPC; 00121 return (NULL); 00122 } 00123 strcpy(dst, tmp); 00124 return (dst); 00125 } 00126 00127 #ifdef NETSNMP_ENABLE_IPV6 00128 /* const char * 00129 * inet_ntop6(src, dst, size) 00130 * convert IPv6 binary address into presentation (printable) format 00131 * author: 00132 * Paul Vixie, 1996. 00133 */ 00134 static const char * 00135 inet_ntop6(src, dst, size) 00136 const u_char *src; 00137 char *dst; 00138 size_t size; 00139 { 00140 /* 00141 * Note that int32_t and int16_t need only be "at least" large enough 00142 * to contain a value of the specified size. On some systems, like 00143 * Crays, there is no such thing as an integer variable with 16 bits. 00144 * Keep this in mind if you think this function should have been coded 00145 * to use pointer overlays. All the world's not a VAX. 00146 */ 00147 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; 00148 struct { int base, len; } best, cur; 00149 u_int words[IN6ADDRSZ / INT16SZ]; 00150 int i; 00151 00152 /* 00153 * Preprocess: 00154 * Copy the input (bytewise) array into a wordwise array. 00155 * Find the longest run of 0x00's in src[] for :: shorthanding. 00156 */ 00157 memset(words, '\0', sizeof words); 00158 for (i = 0; i < IN6ADDRSZ; i++) 00159 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); 00160 best.base = -1; 00161 cur.base = -1; 00162 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { 00163 if (words[i] == 0) { 00164 if (cur.base == -1) 00165 cur.base = i, cur.len = 1; 00166 else 00167 cur.len++; 00168 } else { 00169 if (cur.base != -1) { 00170 if (best.base == -1 || cur.len > best.len) 00171 best = cur; 00172 cur.base = -1; 00173 } 00174 } 00175 } 00176 if (cur.base != -1) { 00177 if (best.base == -1 || cur.len > best.len) 00178 best = cur; 00179 } 00180 if (best.base != -1 && best.len < 2) 00181 best.base = -1; 00182 00183 /* 00184 * Format the result. 00185 */ 00186 tp = tmp; 00187 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { 00188 /* Are we inside the best run of 0x00's? */ 00189 if (best.base != -1 && i >= best.base && 00190 i < (best.base + best.len)) { 00191 if (i == best.base) 00192 *tp++ = ':'; 00193 continue; 00194 } 00195 /* Are we following an initial run of 0x00s or any real hex? */ 00196 if (i != 0) 00197 *tp++ = ':'; 00198 /* Is this address an encapsulated IPv4? */ 00199 if (i == 6 && best.base == 0 && 00200 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { 00201 if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) 00202 return (NULL); 00203 tp += strlen(tp); 00204 break; 00205 } 00206 tp += SPRINTF((tp, "%x", words[i])); 00207 } 00208 /* Was it a trailing run of 0x00's? */ 00209 if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) 00210 *tp++ = ':'; 00211 *tp++ = '\0'; 00212 00213 /* 00214 * Check for overflow, copy, and we're done. 00215 */ 00216 if ((size_t)(tp - tmp) > size) { 00217 errno = ENOSPC; 00218 return (NULL); 00219 } 00220 strcpy(dst, tmp); 00221 return (dst); 00222 } 00223 #endif 00224 00225 #endif /* HAVE_INET_NTOP */