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_pton.c,v 1.4.2.3 2004/03/17 00:40:11 marka Exp $";
00022 #endif
00023
00024 #include "postgres.h"
00025
00026 #include <sys/types.h>
00027 #include <sys/socket.h>
00028 #include <netinet/in.h>
00029 #include <arpa/inet.h>
00030 #include <assert.h>
00031 #include <ctype.h>
00032
00033 #include "utils/builtins.h"
00034
00035 #include "utils/inet.h"
00036
00037
00038 static int inet_net_pton_ipv4(const char *src, u_char *dst);
00039 static int inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size);
00040 static int inet_net_pton_ipv6(const char *src, u_char *dst);
00041 static int inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size);
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 int
00063 inet_net_pton(int af, const char *src, void *dst, size_t size)
00064 {
00065 switch (af)
00066 {
00067 case PGSQL_AF_INET:
00068 return size == -1 ?
00069 inet_net_pton_ipv4(src, dst) :
00070 inet_cidr_pton_ipv4(src, dst, size);
00071 case PGSQL_AF_INET6:
00072 return size == -1 ?
00073 inet_net_pton_ipv6(src, dst) :
00074 inet_cidr_pton_ipv6(src, dst, size);
00075 default:
00076 errno = EAFNOSUPPORT;
00077 return (-1);
00078 }
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 static int
00098 inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size)
00099 {
00100 static const char xdigits[] = "0123456789abcdef";
00101 static const char digits[] = "0123456789";
00102 int n,
00103 ch,
00104 tmp = 0,
00105 dirty,
00106 bits;
00107 const u_char *odst = dst;
00108
00109 ch = *src++;
00110 if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
00111 && isxdigit((unsigned char) src[1]))
00112 {
00113
00114 if (size <= 0U)
00115 goto emsgsize;
00116 dirty = 0;
00117 src++;
00118 while ((ch = *src++) != '\0' && isxdigit((unsigned char) ch))
00119 {
00120 if (isupper((unsigned char) ch))
00121 ch = tolower((unsigned char) ch);
00122 n = strchr(xdigits, ch) - xdigits;
00123 assert(n >= 0 && n <= 15);
00124 if (dirty == 0)
00125 tmp = n;
00126 else
00127 tmp = (tmp << 4) | n;
00128 if (++dirty == 2)
00129 {
00130 if (size-- <= 0U)
00131 goto emsgsize;
00132 *dst++ = (u_char) tmp;
00133 dirty = 0;
00134 }
00135 }
00136 if (dirty)
00137 {
00138 if (size-- <= 0U)
00139 goto emsgsize;
00140 *dst++ = (u_char) (tmp << 4);
00141 }
00142 }
00143 else if (isdigit((unsigned char) ch))
00144 {
00145
00146 for (;;)
00147 {
00148 tmp = 0;
00149 do
00150 {
00151 n = strchr(digits, ch) - digits;
00152 assert(n >= 0 && n <= 9);
00153 tmp *= 10;
00154 tmp += n;
00155 if (tmp > 255)
00156 goto enoent;
00157 } while ((ch = *src++) != '\0' &&
00158 isdigit((unsigned char) ch));
00159 if (size-- <= 0U)
00160 goto emsgsize;
00161 *dst++ = (u_char) tmp;
00162 if (ch == '\0' || ch == '/')
00163 break;
00164 if (ch != '.')
00165 goto enoent;
00166 ch = *src++;
00167 if (!isdigit((unsigned char) ch))
00168 goto enoent;
00169 }
00170 }
00171 else
00172 goto enoent;
00173
00174 bits = -1;
00175 if (ch == '/' && isdigit((unsigned char) src[0]) && dst > odst)
00176 {
00177
00178 ch = *src++;
00179 bits = 0;
00180 do
00181 {
00182 n = strchr(digits, ch) - digits;
00183 assert(n >= 0 && n <= 9);
00184 bits *= 10;
00185 bits += n;
00186 } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
00187 if (ch != '\0')
00188 goto enoent;
00189 if (bits > 32)
00190 goto emsgsize;
00191 }
00192
00193
00194 if (ch != '\0')
00195 goto enoent;
00196
00197
00198 if (dst == odst)
00199 goto enoent;
00200
00201 if (bits == -1)
00202 {
00203 if (*odst >= 240)
00204 bits = 32;
00205 else if (*odst >= 224)
00206 bits = 8;
00207 else if (*odst >= 192)
00208 bits = 24;
00209 else if (*odst >= 128)
00210 bits = 16;
00211 else
00212
00213 bits = 8;
00214
00215 if (bits < ((dst - odst) * 8))
00216 bits = (dst - odst) * 8;
00217
00218
00219
00220
00221
00222 if (bits == 8 && *odst == 224)
00223 bits = 4;
00224 }
00225
00226 while (bits > ((dst - odst) * 8))
00227 {
00228 if (size-- <= 0U)
00229 goto emsgsize;
00230 *dst++ = '\0';
00231 }
00232 return (bits);
00233
00234 enoent:
00235 errno = ENOENT;
00236 return (-1);
00237
00238 emsgsize:
00239 errno = EMSGSIZE;
00240 return (-1);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 static int
00261 inet_net_pton_ipv4(const char *src, u_char *dst)
00262 {
00263 static const char digits[] = "0123456789";
00264 const u_char *odst = dst;
00265 int n,
00266 ch,
00267 tmp,
00268 bits;
00269 size_t size = 4;
00270
00271
00272 while (ch = *src++, isdigit((unsigned char) ch))
00273 {
00274 tmp = 0;
00275 do
00276 {
00277 n = strchr(digits, ch) - digits;
00278 assert(n >= 0 && n <= 9);
00279 tmp *= 10;
00280 tmp += n;
00281 if (tmp > 255)
00282 goto enoent;
00283 } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
00284 if (size-- == 0)
00285 goto emsgsize;
00286 *dst++ = (u_char) tmp;
00287 if (ch == '\0' || ch == '/')
00288 break;
00289 if (ch != '.')
00290 goto enoent;
00291 }
00292
00293
00294 bits = -1;
00295 if (ch == '/' && isdigit((unsigned char) src[0]) && dst > odst)
00296 {
00297
00298 ch = *src++;
00299 bits = 0;
00300 do
00301 {
00302 n = strchr(digits, ch) - digits;
00303 assert(n >= 0 && n <= 9);
00304 bits *= 10;
00305 bits += n;
00306 } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
00307 if (ch != '\0')
00308 goto enoent;
00309 if (bits > 32)
00310 goto emsgsize;
00311 }
00312
00313
00314 if (ch != '\0')
00315 goto enoent;
00316
00317
00318 if (bits == -1)
00319 {
00320 if (dst - odst == 4)
00321 bits = 32;
00322 else
00323 goto enoent;
00324 }
00325
00326
00327 if (dst == odst)
00328 goto enoent;
00329
00330
00331 if ((bits / 8) > (dst - odst))
00332 goto enoent;
00333
00334
00335 while (size-- > 0)
00336 *dst++ = 0;
00337
00338 return bits;
00339
00340 enoent:
00341 errno = ENOENT;
00342 return (-1);
00343
00344 emsgsize:
00345 errno = EMSGSIZE;
00346 return (-1);
00347 }
00348
00349 static int
00350 getbits(const char *src, int *bitsp)
00351 {
00352 static const char digits[] = "0123456789";
00353 int n;
00354 int val;
00355 char ch;
00356
00357 val = 0;
00358 n = 0;
00359 while ((ch = *src++) != '\0')
00360 {
00361 const char *pch;
00362
00363 pch = strchr(digits, ch);
00364 if (pch != NULL)
00365 {
00366 if (n++ != 0 && val == 0)
00367 return (0);
00368 val *= 10;
00369 val += (pch - digits);
00370 if (val > 128)
00371 return (0);
00372 continue;
00373 }
00374 return (0);
00375 }
00376 if (n == 0)
00377 return (0);
00378 *bitsp = val;
00379 return (1);
00380 }
00381
00382 static int
00383 getv4(const char *src, u_char *dst, int *bitsp)
00384 {
00385 static const char digits[] = "0123456789";
00386 u_char *odst = dst;
00387 int n;
00388 u_int val;
00389 char ch;
00390
00391 val = 0;
00392 n = 0;
00393 while ((ch = *src++) != '\0')
00394 {
00395 const char *pch;
00396
00397 pch = strchr(digits, ch);
00398 if (pch != NULL)
00399 {
00400 if (n++ != 0 && val == 0)
00401 return (0);
00402 val *= 10;
00403 val += (pch - digits);
00404 if (val > 255)
00405 return (0);
00406 continue;
00407 }
00408 if (ch == '.' || ch == '/')
00409 {
00410 if (dst - odst > 3)
00411 return (0);
00412 *dst++ = val;
00413 if (ch == '/')
00414 return (getbits(src, bitsp));
00415 val = 0;
00416 n = 0;
00417 continue;
00418 }
00419 return (0);
00420 }
00421 if (n == 0)
00422 return (0);
00423 if (dst - odst > 3)
00424 return (0);
00425 *dst++ = val;
00426 return (1);
00427 }
00428
00429 static int
00430 inet_net_pton_ipv6(const char *src, u_char *dst)
00431 {
00432 return inet_cidr_pton_ipv6(src, dst, 16);
00433 }
00434
00435 #define NS_IN6ADDRSZ 16
00436 #define NS_INT16SZ 2
00437 #define NS_INADDRSZ 4
00438
00439 static int
00440 inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size)
00441 {
00442 static const char xdigits_l[] = "0123456789abcdef",
00443 xdigits_u[] = "0123456789ABCDEF";
00444 u_char tmp[NS_IN6ADDRSZ],
00445 *tp,
00446 *endp,
00447 *colonp;
00448 const char *xdigits,
00449 *curtok;
00450 int ch,
00451 saw_xdigit;
00452 u_int val;
00453 int digits;
00454 int bits;
00455
00456 if (size < NS_IN6ADDRSZ)
00457 goto emsgsize;
00458
00459 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
00460 endp = tp + NS_IN6ADDRSZ;
00461 colonp = NULL;
00462
00463 if (*src == ':')
00464 if (*++src != ':')
00465 goto enoent;
00466 curtok = src;
00467 saw_xdigit = 0;
00468 val = 0;
00469 digits = 0;
00470 bits = -1;
00471 while ((ch = *src++) != '\0')
00472 {
00473 const char *pch;
00474
00475 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
00476 pch = strchr((xdigits = xdigits_u), ch);
00477 if (pch != NULL)
00478 {
00479 val <<= 4;
00480 val |= (pch - xdigits);
00481 if (++digits > 4)
00482 goto enoent;
00483 saw_xdigit = 1;
00484 continue;
00485 }
00486 if (ch == ':')
00487 {
00488 curtok = src;
00489 if (!saw_xdigit)
00490 {
00491 if (colonp)
00492 goto enoent;
00493 colonp = tp;
00494 continue;
00495 }
00496 else if (*src == '\0')
00497 goto enoent;
00498 if (tp + NS_INT16SZ > endp)
00499 return (0);
00500 *tp++ = (u_char) (val >> 8) & 0xff;
00501 *tp++ = (u_char) val & 0xff;
00502 saw_xdigit = 0;
00503 digits = 0;
00504 val = 0;
00505 continue;
00506 }
00507 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
00508 getv4(curtok, tp, &bits) > 0)
00509 {
00510 tp += NS_INADDRSZ;
00511 saw_xdigit = 0;
00512 break;
00513 }
00514 if (ch == '/' && getbits(src, &bits) > 0)
00515 break;
00516 goto enoent;
00517 }
00518 if (saw_xdigit)
00519 {
00520 if (tp + NS_INT16SZ > endp)
00521 goto enoent;
00522 *tp++ = (u_char) (val >> 8) & 0xff;
00523 *tp++ = (u_char) val & 0xff;
00524 }
00525 if (bits == -1)
00526 bits = 128;
00527
00528 endp = tmp + 16;
00529
00530 if (colonp != NULL)
00531 {
00532
00533
00534
00535
00536 const int n = tp - colonp;
00537 int i;
00538
00539 if (tp == endp)
00540 goto enoent;
00541 for (i = 1; i <= n; i++)
00542 {
00543 endp[-i] = colonp[n - i];
00544 colonp[n - i] = 0;
00545 }
00546 tp = endp;
00547 }
00548 if (tp != endp)
00549 goto enoent;
00550
00551
00552
00553
00554 memcpy(dst, tmp, NS_IN6ADDRSZ);
00555
00556 return (bits);
00557
00558 enoent:
00559 errno = ENOENT;
00560 return (-1);
00561
00562 emsgsize:
00563 errno = EMSGSIZE;
00564 return (-1);
00565 }