00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #if defined(LIBC_SCCS) && !defined(lint)
00021 static char rcsid[] =
00022 "$Id: inet_ntop.c,v 1.21 2009/07/17 23:47:41 tbox Exp $";
00023 #endif
00024
00025 #include <config.h>
00026
00027 #include <errno.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030
00031 #include <isc/net.h>
00032 #include <isc/print.h>
00033
00034 #define NS_INT16SZ 2
00035 #define NS_IN6ADDRSZ 16
00036
00037
00038
00039
00040
00041
00042 static const char *inet_ntop4(const unsigned char *src, char *dst,
00043 size_t size);
00044
00045 #ifdef AF_INET6
00046 static const char *inet_ntop6(const unsigned char *src, char *dst,
00047 size_t size);
00048 #endif
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 const char *
00059 isc_net_ntop(int af, const void *src, char *dst, size_t size)
00060 {
00061 switch (af) {
00062 case AF_INET:
00063 return (inet_ntop4(src, dst, size));
00064 #ifdef AF_INET6
00065 case AF_INET6:
00066 return (inet_ntop6(src, dst, size));
00067 #endif
00068 default:
00069 errno = EAFNOSUPPORT;
00070 return (NULL);
00071 }
00072
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 static const char *
00088 inet_ntop4(const unsigned char *src, char *dst, size_t size)
00089 {
00090 static const char *fmt = "%u.%u.%u.%u";
00091 char tmp[sizeof("255.255.255.255")];
00092
00093 if ((size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size)
00094 {
00095 errno = ENOSPC;
00096 return (NULL);
00097 }
00098 strcpy(dst, tmp);
00099
00100 return (dst);
00101 }
00102
00103
00104
00105
00106
00107
00108
00109 #ifdef AF_INET6
00110 static const char *
00111 inet_ntop6(const unsigned char *src, char *dst, size_t size)
00112 {
00113
00114
00115
00116
00117
00118
00119
00120 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp;
00121 struct { int base, len; } best, cur;
00122 unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
00123 int i;
00124
00125
00126
00127
00128
00129
00130 memset(words, '\0', sizeof(words));
00131 for (i = 0; i < NS_IN6ADDRSZ; i++)
00132 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
00133 best.base = -1;
00134 cur.base = -1;
00135 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
00136 if (words[i] == 0) {
00137 if (cur.base == -1)
00138 cur.base = i, cur.len = 1;
00139 else
00140 cur.len++;
00141 } else {
00142 if (cur.base != -1) {
00143 if (best.base == -1 || cur.len > best.len)
00144 best = cur;
00145 cur.base = -1;
00146 }
00147 }
00148 }
00149 if (cur.base != -1) {
00150 if (best.base == -1 || cur.len > best.len)
00151 best = cur;
00152 }
00153 if (best.base != -1 && best.len < 2)
00154 best.base = -1;
00155
00156
00157
00158
00159 tp = tmp;
00160 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
00161
00162 if (best.base != -1 && i >= best.base &&
00163 i < (best.base + best.len)) {
00164 if (i == best.base)
00165 *tp++ = ':';
00166 continue;
00167 }
00168
00169 if (i != 0)
00170 *tp++ = ':';
00171
00172 if (i == 6 && best.base == 0 && (best.len == 6 ||
00173 (best.len == 7 && words[7] != 0x0001) ||
00174 (best.len == 5 && words[5] == 0xffff))) {
00175 if (!inet_ntop4(src+12, tp,
00176 sizeof(tmp) - (tp - tmp)))
00177 return (NULL);
00178 tp += strlen(tp);
00179 break;
00180 }
00181 tp += sprintf(tp, "%x", words[i]);
00182 }
00183
00184 if (best.base != -1 && (best.base + best.len) ==
00185 (NS_IN6ADDRSZ / NS_INT16SZ))
00186 *tp++ = ':';
00187 *tp++ = '\0';
00188
00189
00190
00191
00192 if ((size_t)(tp - tmp) > size) {
00193 errno = ENOSPC;
00194 return (NULL);
00195 }
00196 strcpy(dst, tmp);
00197 return (dst);
00198 }
00199 #endif