00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "setup.h"
00022
00023 #ifndef HAVE_INET_NTOP
00024
00025 #ifdef HAVE_SYS_PARAM_H
00026 #include <sys/param.h>
00027 #endif
00028 #ifdef HAVE_SYS_SOCKET_H
00029 #include <sys/socket.h>
00030 #endif
00031 #ifdef HAVE_NETINET_IN_H
00032 #include <netinet/in.h>
00033 #endif
00034 #ifdef HAVE_ARPA_INET_H
00035 #include <arpa/inet.h>
00036 #endif
00037 #include <string.h>
00038 #include <errno.h>
00039
00040 #define _MPRINTF_REPLACE
00041 #include <curl/mprintf.h>
00042
00043 #include "inet_ntop.h"
00044
00045 #if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
00046 NETINET_DEFINE_CONTEXT
00047 #endif
00048
00049 #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
00050
00051
00052 #include "inet_ntoa_r.h"
00053 #endif
00054
00055 #define IN6ADDRSZ 16
00056 #define INADDRSZ 4
00057 #define INT16SZ 2
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
00068 {
00069 #if defined(HAVE_INET_NTOA_R_2_ARGS)
00070 const char *ptr;
00071 DEBUGASSERT(size >= 16);
00072 ptr = inet_ntoa_r(*(struct in_addr*)src, dst);
00073 return (char *)memmove(dst, ptr, strlen(ptr)+1);
00074
00075 #elif defined(HAVE_INET_NTOA_R)
00076 return inet_ntoa_r(*(struct in_addr*)src, dst, size);
00077
00078 #else
00079 const char *addr = inet_ntoa(*(struct in_addr*)src);
00080
00081 if (strlen(addr) >= size)
00082 {
00083 SET_ERRNO(ENOSPC);
00084 return (NULL);
00085 }
00086 return strcpy(dst, addr);
00087 #endif
00088 }
00089
00090 #ifdef ENABLE_IPV6
00091
00092
00093
00094 static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
00095 {
00096
00097
00098
00099
00100
00101
00102
00103 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
00104 char *tp;
00105 struct {
00106 long base;
00107 long len;
00108 } best, cur;
00109 unsigned long words[IN6ADDRSZ / INT16SZ];
00110 int i;
00111
00112
00113
00114
00115
00116 memset(words, '\0', sizeof(words));
00117 for (i = 0; i < IN6ADDRSZ; i++)
00118 words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
00119
00120 best.base = -1;
00121 cur.base = -1;
00122 best.len = 0;
00123 cur.len = 0;
00124
00125 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
00126 {
00127 if (words[i] == 0)
00128 {
00129 if (cur.base == -1)
00130 cur.base = i, cur.len = 1;
00131 else
00132 cur.len++;
00133 }
00134 else if (cur.base != -1)
00135 {
00136 if (best.base == -1 || cur.len > best.len)
00137 best = cur;
00138 cur.base = -1;
00139 }
00140 }
00141 if ((cur.base != -1) && (best.base == -1 || cur.len > best.len))
00142 best = cur;
00143 if (best.base != -1 && best.len < 2)
00144 best.base = -1;
00145
00146
00147
00148 tp = tmp;
00149 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
00150 {
00151
00152
00153 if (best.base != -1 && i >= best.base && i < (best.base + best.len))
00154 {
00155 if (i == best.base)
00156 *tp++ = ':';
00157 continue;
00158 }
00159
00160
00161
00162 if (i != 0)
00163 *tp++ = ':';
00164
00165
00166
00167 if (i == 6 && best.base == 0 &&
00168 (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
00169 {
00170 if (!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp)))
00171 {
00172 SET_ERRNO(ENOSPC);
00173 return (NULL);
00174 }
00175 tp += strlen(tp);
00176 break;
00177 }
00178 tp += snprintf(tp, 5, "%lx", words[i]);
00179 }
00180
00181
00182
00183 if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
00184 *tp++ = ':';
00185 *tp++ = '\0';
00186
00187
00188
00189 if ((size_t)(tp - tmp) > size)
00190 {
00191 SET_ERRNO(ENOSPC);
00192 return (NULL);
00193 }
00194 return strcpy (dst, tmp);
00195 }
00196 #endif
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
00211 {
00212 switch (af) {
00213 case AF_INET:
00214 return inet_ntop4((const unsigned char*)src, buf, size);
00215 #ifdef ENABLE_IPV6
00216 case AF_INET6:
00217 return inet_ntop6((const unsigned char*)src, buf, size);
00218 #endif
00219 default:
00220 SET_ERRNO(EAFNOSUPPORT);
00221 return NULL;
00222 }
00223 }
00224 #endif