00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
00061
00062
00063
00064 static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
00065 #ifdef INET6
00066 static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
00067 #endif
00068
00069
00070
00071
00072
00073
00074
00075
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 INET6
00089 case AF_INET6:
00090 return (inet_ntop6(src, dst, size));
00091 #endif
00092 default:
00093 errno = EAFNOSUPPORT;
00094 return (NULL);
00095 }
00096
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
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 INET6
00128
00129
00130
00131
00132
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
00142
00143
00144
00145
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
00154
00155
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
00185
00186 tp = tmp;
00187 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
00188
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
00196 if (i != 0)
00197 *tp++ = ':';
00198
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
00209 if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
00210 *tp++ = ':';
00211 *tp++ = '\0';
00212
00213
00214
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