Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "curl_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_NETINET_IN_H
00029 #include <netinet/in.h>
00030 #endif
00031 #ifdef HAVE_ARPA_INET_H
00032 #include <arpa/inet.h>
00033 #endif
00034
00035 #include "inet_ntop.h"
00036 #include "curl_printf.h"
00037
00038 #define IN6ADDRSZ 16
00039 #define INADDRSZ 4
00040 #define INT16SZ 2
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
00051 {
00052 char tmp[sizeof "255.255.255.255"];
00053 size_t len;
00054
00055 DEBUGASSERT(size >= 16);
00056
00057 tmp[0] = '\0';
00058 (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
00059 ((int)((unsigned char)src[0])) & 0xff,
00060 ((int)((unsigned char)src[1])) & 0xff,
00061 ((int)((unsigned char)src[2])) & 0xff,
00062 ((int)((unsigned char)src[3])) & 0xff);
00063
00064 len = strlen(tmp);
00065 if(len == 0 || len >= size) {
00066 SET_ERRNO(ENOSPC);
00067 return (NULL);
00068 }
00069 strcpy(dst, tmp);
00070 return dst;
00071 }
00072
00073 #ifdef ENABLE_IPV6
00074
00075
00076
00077 static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
00078 {
00079
00080
00081
00082
00083
00084
00085
00086 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
00087 char *tp;
00088 struct {
00089 long base;
00090 long len;
00091 } best, cur;
00092 unsigned long words[IN6ADDRSZ / INT16SZ];
00093 int i;
00094
00095
00096
00097
00098
00099 memset(words, '\0', sizeof(words));
00100 for(i = 0; i < IN6ADDRSZ; i++)
00101 words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
00102
00103 best.base = -1;
00104 cur.base = -1;
00105 best.len = 0;
00106 cur.len = 0;
00107
00108 for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
00109 if(words[i] == 0) {
00110 if(cur.base == -1)
00111 cur.base = i, cur.len = 1;
00112 else
00113 cur.len++;
00114 }
00115 else if(cur.base != -1) {
00116 if(best.base == -1 || cur.len > best.len)
00117 best = cur;
00118 cur.base = -1;
00119 }
00120 }
00121 if((cur.base != -1) && (best.base == -1 || cur.len > best.len))
00122 best = cur;
00123 if(best.base != -1 && best.len < 2)
00124 best.base = -1;
00125
00126 tp = tmp;
00127 for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
00128
00129 if(best.base != -1 && i >= best.base && i < (best.base + best.len)) {
00130 if(i == best.base)
00131 *tp++ = ':';
00132 continue;
00133 }
00134
00135
00136
00137 if(i != 0)
00138 *tp++ = ':';
00139
00140
00141
00142 if(i == 6 && best.base == 0 &&
00143 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
00144 if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) {
00145 SET_ERRNO(ENOSPC);
00146 return (NULL);
00147 }
00148 tp += strlen(tp);
00149 break;
00150 }
00151 tp += snprintf(tp, 5, "%lx", words[i]);
00152 }
00153
00154
00155
00156 if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
00157 *tp++ = ':';
00158 *tp++ = '\0';
00159
00160
00161
00162 if((size_t)(tp - tmp) > size) {
00163 SET_ERRNO(ENOSPC);
00164 return (NULL);
00165 }
00166 strcpy(dst, tmp);
00167 return dst;
00168 }
00169 #endif
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
00184 {
00185 switch(af) {
00186 case AF_INET:
00187 return inet_ntop4((const unsigned char *)src, buf, size);
00188 #ifdef ENABLE_IPV6
00189 case AF_INET6:
00190 return inet_ntop6((const unsigned char *)src, buf, size);
00191 #endif
00192 default:
00193 SET_ERRNO(EAFNOSUPPORT);
00194 return NULL;
00195 }
00196 }
00197 #endif