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 const char rcsid[] = "Id: inet_net_ntop.c,v 1.1.2.2 2004/03/09 09:17:27 marka Exp $";
00022 #endif
00023
00024 #ifndef FRONTEND
00025 #include "postgres.h"
00026 #else
00027 #include "postgres_fe.h"
00028 #endif
00029
00030 #include <sys/types.h>
00031 #include <sys/socket.h>
00032 #include <netinet/in.h>
00033 #include <arpa/inet.h>
00034
00035 #ifndef FRONTEND
00036 #include "utils/inet.h"
00037 #else
00038
00039
00040
00041
00042
00043 #define PGSQL_AF_INET (AF_INET + 0)
00044 #define PGSQL_AF_INET6 (AF_INET + 1)
00045 #endif
00046
00047
00048 #define NS_IN6ADDRSZ 16
00049 #define NS_INT16SZ 2
00050
00051 #ifdef SPRINTF_CHAR
00052 #define SPRINTF(x) strlen(sprintfx)
00053 #else
00054 #define SPRINTF(x) ((size_t)sprintf x)
00055 #endif
00056
00057 static char *inet_net_ntop_ipv4(const u_char *src, int bits,
00058 char *dst, size_t size);
00059 static char *inet_net_ntop_ipv6(const u_char *src, int bits,
00060 char *dst, size_t size);
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 char *
00078 inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
00079 {
00080
00081
00082
00083
00084
00085
00086
00087 switch (af)
00088 {
00089 case PGSQL_AF_INET:
00090 return (inet_net_ntop_ipv4(src, bits, dst, size));
00091 case PGSQL_AF_INET6:
00092 #if defined(AF_INET6) && AF_INET6 != PGSQL_AF_INET6
00093 case AF_INET6:
00094 #endif
00095 return (inet_net_ntop_ipv6(src, bits, dst, size));
00096 default:
00097 errno = EAFNOSUPPORT;
00098 return (NULL);
00099 }
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 static char *
00116 inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
00117 {
00118 char *odst = dst;
00119 char *t;
00120 int len = 4;
00121 int b;
00122
00123 if (bits < 0 || bits > 32)
00124 {
00125 errno = EINVAL;
00126 return (NULL);
00127 }
00128
00129
00130 for (b = len; b > 0; b--)
00131 {
00132 if (size <= sizeof ".255")
00133 goto emsgsize;
00134 t = dst;
00135 if (dst != odst)
00136 *dst++ = '.';
00137 dst += SPRINTF((dst, "%u", *src++));
00138 size -= (size_t) (dst - t);
00139 }
00140
00141
00142 if (bits != 32)
00143 {
00144 if (size <= sizeof "/32")
00145 goto emsgsize;
00146 dst += SPRINTF((dst, "/%u", bits));
00147 }
00148
00149 return (odst);
00150
00151 emsgsize:
00152 errno = EMSGSIZE;
00153 return (NULL);
00154 }
00155
00156 static int
00157 decoct(const u_char *src, int bytes, char *dst, size_t size)
00158 {
00159 char *odst = dst;
00160 char *t;
00161 int b;
00162
00163 for (b = 1; b <= bytes; b++)
00164 {
00165 if (size <= sizeof "255.")
00166 return (0);
00167 t = dst;
00168 dst += SPRINTF((dst, "%u", *src++));
00169 if (b != bytes)
00170 {
00171 *dst++ = '.';
00172 *dst = '\0';
00173 }
00174 size -= (size_t) (dst - t);
00175 }
00176 return (dst - odst);
00177 }
00178
00179 static char *
00180 inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
00181 {
00182
00183
00184
00185
00186
00187
00188
00189 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
00190 char *tp;
00191 struct
00192 {
00193 int base,
00194 len;
00195 } best, cur;
00196 u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
00197 int i;
00198
00199 if ((bits < -1) || (bits > 128))
00200 {
00201 errno = EINVAL;
00202 return (NULL);
00203 }
00204
00205
00206
00207
00208
00209 memset(words, '\0', sizeof words);
00210 for (i = 0; i < NS_IN6ADDRSZ; i++)
00211 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
00212 best.base = -1;
00213 cur.base = -1;
00214 best.len = 0;
00215 cur.len = 0;
00216 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
00217 {
00218 if (words[i] == 0)
00219 {
00220 if (cur.base == -1)
00221 cur.base = i, cur.len = 1;
00222 else
00223 cur.len++;
00224 }
00225 else
00226 {
00227 if (cur.base != -1)
00228 {
00229 if (best.base == -1 || cur.len > best.len)
00230 best = cur;
00231 cur.base = -1;
00232 }
00233 }
00234 }
00235 if (cur.base != -1)
00236 {
00237 if (best.base == -1 || cur.len > best.len)
00238 best = cur;
00239 }
00240 if (best.base != -1 && best.len < 2)
00241 best.base = -1;
00242
00243
00244
00245
00246 tp = tmp;
00247 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
00248 {
00249
00250 if (best.base != -1 && i >= best.base &&
00251 i < (best.base + best.len))
00252 {
00253 if (i == best.base)
00254 *tp++ = ':';
00255 continue;
00256 }
00257
00258 if (i != 0)
00259 *tp++ = ':';
00260
00261 if (i == 6 && best.base == 0 && (best.len == 6 ||
00262 (best.len == 7 && words[7] != 0x0001) ||
00263 (best.len == 5 && words[5] == 0xffff)))
00264 {
00265 int n;
00266
00267 n = decoct(src + 12, 4, tp, sizeof tmp - (tp - tmp));
00268 if (n == 0)
00269 {
00270 errno = EMSGSIZE;
00271 return (NULL);
00272 }
00273 tp += strlen(tp);
00274 break;
00275 }
00276 tp += SPRINTF((tp, "%x", words[i]));
00277 }
00278
00279
00280 if (best.base != -1 && (best.base + best.len) ==
00281 (NS_IN6ADDRSZ / NS_INT16SZ))
00282 *tp++ = ':';
00283 *tp = '\0';
00284
00285 if (bits != -1 && bits != 128)
00286 tp += SPRINTF((tp, "/%u", bits));
00287
00288
00289
00290
00291 if ((size_t) (tp - tmp) > size)
00292 {
00293 errno = EMSGSIZE;
00294 return (NULL);
00295 }
00296 strcpy(dst, tmp);
00297 return (dst);
00298 }