00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "postgres.h"
00010
00011 #include <sys/socket.h>
00012 #include <netinet/in.h>
00013 #include <arpa/inet.h>
00014
00015 #include "access/hash.h"
00016 #include "catalog/pg_type.h"
00017 #include "libpq/ip.h"
00018 #include "libpq/libpq-be.h"
00019 #include "libpq/pqformat.h"
00020 #include "miscadmin.h"
00021 #include "utils/builtins.h"
00022 #include "utils/inet.h"
00023
00024
00025 static int32 network_cmp_internal(inet *a1, inet *a2);
00026 static int bitncmp(void *l, void *r, int n);
00027 static bool addressOK(unsigned char *a, int bits, int family);
00028 static int ip_addrsize(inet *inetptr);
00029 static inet *internal_inetpl(inet *ip, int64 addend);
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #define ip_family(inetptr) \
00046 (((inet_struct *) VARDATA_ANY(inetptr))->family)
00047
00048 #define ip_bits(inetptr) \
00049 (((inet_struct *) VARDATA_ANY(inetptr))->bits)
00050
00051 #define ip_addr(inetptr) \
00052 (((inet_struct *) VARDATA_ANY(inetptr))->ipaddr)
00053
00054 #define ip_maxbits(inetptr) \
00055 (ip_family(inetptr) == PGSQL_AF_INET ? 32 : 128)
00056
00057 #define SET_INET_VARSIZE(dst) \
00058 SET_VARSIZE(dst, VARHDRSZ + offsetof(inet_struct, ipaddr) + \
00059 ip_addrsize(dst))
00060
00061
00062
00063
00064
00065 static int
00066 ip_addrsize(inet *inetptr)
00067 {
00068 switch (ip_family(inetptr))
00069 {
00070 case PGSQL_AF_INET:
00071 return 4;
00072 case PGSQL_AF_INET6:
00073 return 16;
00074 default:
00075 return 0;
00076 }
00077 }
00078
00079
00080
00081
00082 static inet *
00083 network_in(char *src, bool is_cidr)
00084 {
00085 int bits;
00086 inet *dst;
00087
00088 dst = (inet *) palloc0(sizeof(inet));
00089
00090
00091
00092
00093
00094
00095
00096 if (strchr(src, ':') != NULL)
00097 ip_family(dst) = PGSQL_AF_INET6;
00098 else
00099 ip_family(dst) = PGSQL_AF_INET;
00100
00101 bits = inet_net_pton(ip_family(dst), src, ip_addr(dst),
00102 is_cidr ? ip_addrsize(dst) : -1);
00103 if ((bits < 0) || (bits > ip_maxbits(dst)))
00104 ereport(ERROR,
00105 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00106
00107 errmsg("invalid input syntax for type %s: \"%s\"",
00108 is_cidr ? "cidr" : "inet", src)));
00109
00110
00111
00112
00113 if (is_cidr)
00114 {
00115 if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
00116 ereport(ERROR,
00117 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00118 errmsg("invalid cidr value: \"%s\"", src),
00119 errdetail("Value has bits set to right of mask.")));
00120 }
00121
00122 ip_bits(dst) = bits;
00123 SET_INET_VARSIZE(dst);
00124
00125 return dst;
00126 }
00127
00128 Datum
00129 inet_in(PG_FUNCTION_ARGS)
00130 {
00131 char *src = PG_GETARG_CSTRING(0);
00132
00133 PG_RETURN_INET_P(network_in(src, false));
00134 }
00135
00136 Datum
00137 cidr_in(PG_FUNCTION_ARGS)
00138 {
00139 char *src = PG_GETARG_CSTRING(0);
00140
00141 PG_RETURN_INET_P(network_in(src, true));
00142 }
00143
00144
00145
00146
00147
00148 static char *
00149 network_out(inet *src, bool is_cidr)
00150 {
00151 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
00152 char *dst;
00153 int len;
00154
00155 dst = inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),
00156 tmp, sizeof(tmp));
00157 if (dst == NULL)
00158 ereport(ERROR,
00159 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
00160 errmsg("could not format inet value: %m")));
00161
00162
00163 if (is_cidr && strchr(tmp, '/') == NULL)
00164 {
00165 len = strlen(tmp);
00166 snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
00167 }
00168
00169 return pstrdup(tmp);
00170 }
00171
00172 Datum
00173 inet_out(PG_FUNCTION_ARGS)
00174 {
00175 inet *src = PG_GETARG_INET_PP(0);
00176
00177 PG_RETURN_CSTRING(network_out(src, false));
00178 }
00179
00180 Datum
00181 cidr_out(PG_FUNCTION_ARGS)
00182 {
00183 inet *src = PG_GETARG_INET_PP(0);
00184
00185 PG_RETURN_CSTRING(network_out(src, true));
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 static inet *
00200 network_recv(StringInfo buf, bool is_cidr)
00201 {
00202 inet *addr;
00203 char *addrptr;
00204 int bits;
00205 int nb,
00206 i;
00207
00208
00209 addr = (inet *) palloc0(sizeof(inet));
00210
00211 ip_family(addr) = pq_getmsgbyte(buf);
00212 if (ip_family(addr) != PGSQL_AF_INET &&
00213 ip_family(addr) != PGSQL_AF_INET6)
00214 ereport(ERROR,
00215 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
00216
00217 errmsg("invalid address family in external \"%s\" value",
00218 is_cidr ? "cidr" : "inet")));
00219 bits = pq_getmsgbyte(buf);
00220 if (bits < 0 || bits > ip_maxbits(addr))
00221 ereport(ERROR,
00222 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
00223
00224 errmsg("invalid bits in external \"%s\" value",
00225 is_cidr ? "cidr" : "inet")));
00226 ip_bits(addr) = bits;
00227 i = pq_getmsgbyte(buf);
00228 nb = pq_getmsgbyte(buf);
00229 if (nb != ip_addrsize(addr))
00230 ereport(ERROR,
00231 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
00232
00233 errmsg("invalid length in external \"%s\" value",
00234 is_cidr ? "cidr" : "inet")));
00235
00236 addrptr = (char *) ip_addr(addr);
00237 for (i = 0; i < nb; i++)
00238 addrptr[i] = pq_getmsgbyte(buf);
00239
00240
00241
00242
00243 if (is_cidr)
00244 {
00245 if (!addressOK(ip_addr(addr), bits, ip_family(addr)))
00246 ereport(ERROR,
00247 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
00248 errmsg("invalid external \"cidr\" value"),
00249 errdetail("Value has bits set to right of mask.")));
00250 }
00251
00252 SET_INET_VARSIZE(addr);
00253
00254 return addr;
00255 }
00256
00257 Datum
00258 inet_recv(PG_FUNCTION_ARGS)
00259 {
00260 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
00261
00262 PG_RETURN_INET_P(network_recv(buf, false));
00263 }
00264
00265 Datum
00266 cidr_recv(PG_FUNCTION_ARGS)
00267 {
00268 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
00269
00270 PG_RETURN_INET_P(network_recv(buf, true));
00271 }
00272
00273
00274
00275
00276
00277 static bytea *
00278 network_send(inet *addr, bool is_cidr)
00279 {
00280 StringInfoData buf;
00281 char *addrptr;
00282 int nb,
00283 i;
00284
00285 pq_begintypsend(&buf);
00286 pq_sendbyte(&buf, ip_family(addr));
00287 pq_sendbyte(&buf, ip_bits(addr));
00288 pq_sendbyte(&buf, is_cidr);
00289 nb = ip_addrsize(addr);
00290 if (nb < 0)
00291 nb = 0;
00292 pq_sendbyte(&buf, nb);
00293 addrptr = (char *) ip_addr(addr);
00294 for (i = 0; i < nb; i++)
00295 pq_sendbyte(&buf, addrptr[i]);
00296 return pq_endtypsend(&buf);
00297 }
00298
00299 Datum
00300 inet_send(PG_FUNCTION_ARGS)
00301 {
00302 inet *addr = PG_GETARG_INET_PP(0);
00303
00304 PG_RETURN_BYTEA_P(network_send(addr, false));
00305 }
00306
00307 Datum
00308 cidr_send(PG_FUNCTION_ARGS)
00309 {
00310 inet *addr = PG_GETARG_INET_PP(0);
00311
00312 PG_RETURN_BYTEA_P(network_send(addr, true));
00313 }
00314
00315
00316 Datum
00317 inet_to_cidr(PG_FUNCTION_ARGS)
00318 {
00319 inet *src = PG_GETARG_INET_PP(0);
00320 inet *dst;
00321 int bits;
00322 int byte;
00323 int nbits;
00324 int maxbytes;
00325
00326 bits = ip_bits(src);
00327
00328
00329 if ((bits < 0) || (bits > ip_maxbits(src)))
00330 elog(ERROR, "invalid inet bit length: %d", bits);
00331
00332
00333 dst = (inet *) palloc(VARSIZE_ANY(src));
00334 memcpy(dst, src, VARSIZE_ANY(src));
00335
00336
00337 byte = bits / 8;
00338
00339 nbits = bits % 8;
00340
00341 if (nbits != 0)
00342 {
00343 ip_addr(dst)[byte] &= ~(0xFF >> nbits);
00344 byte++;
00345 }
00346
00347 maxbytes = ip_addrsize(dst);
00348 while (byte < maxbytes)
00349 {
00350 ip_addr(dst)[byte] = 0;
00351 byte++;
00352 }
00353
00354 PG_RETURN_INET_P(dst);
00355 }
00356
00357 Datum
00358 inet_set_masklen(PG_FUNCTION_ARGS)
00359 {
00360 inet *src = PG_GETARG_INET_PP(0);
00361 int bits = PG_GETARG_INT32(1);
00362 inet *dst;
00363
00364 if (bits == -1)
00365 bits = ip_maxbits(src);
00366
00367 if ((bits < 0) || (bits > ip_maxbits(src)))
00368 ereport(ERROR,
00369 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00370 errmsg("invalid mask length: %d", bits)));
00371
00372
00373 dst = (inet *) palloc(VARSIZE_ANY(src));
00374 memcpy(dst, src, VARSIZE_ANY(src));
00375
00376 ip_bits(dst) = bits;
00377
00378 PG_RETURN_INET_P(dst);
00379 }
00380
00381 Datum
00382 cidr_set_masklen(PG_FUNCTION_ARGS)
00383 {
00384 inet *src = PG_GETARG_INET_PP(0);
00385 int bits = PG_GETARG_INT32(1);
00386 inet *dst;
00387 int byte;
00388 int nbits;
00389 int maxbytes;
00390
00391 if (bits == -1)
00392 bits = ip_maxbits(src);
00393
00394 if ((bits < 0) || (bits > ip_maxbits(src)))
00395 ereport(ERROR,
00396 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00397 errmsg("invalid mask length: %d", bits)));
00398
00399
00400 dst = (inet *) palloc(VARSIZE_ANY(src));
00401 memcpy(dst, src, VARSIZE_ANY(src));
00402
00403 ip_bits(dst) = bits;
00404
00405
00406 byte = bits / 8;
00407
00408 nbits = bits % 8;
00409
00410 if (nbits != 0)
00411 {
00412 ip_addr(dst)[byte] &= ~(0xFF >> nbits);
00413 byte++;
00414 }
00415
00416 maxbytes = ip_addrsize(dst);
00417 while (byte < maxbytes)
00418 {
00419 ip_addr(dst)[byte] = 0;
00420 byte++;
00421 }
00422
00423 PG_RETURN_INET_P(dst);
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 static int32
00438 network_cmp_internal(inet *a1, inet *a2)
00439 {
00440 if (ip_family(a1) == ip_family(a2))
00441 {
00442 int order;
00443
00444 order = bitncmp(ip_addr(a1), ip_addr(a2),
00445 Min(ip_bits(a1), ip_bits(a2)));
00446 if (order != 0)
00447 return order;
00448 order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
00449 if (order != 0)
00450 return order;
00451 return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));
00452 }
00453
00454 return ip_family(a1) - ip_family(a2);
00455 }
00456
00457 Datum
00458 network_cmp(PG_FUNCTION_ARGS)
00459 {
00460 inet *a1 = PG_GETARG_INET_PP(0);
00461 inet *a2 = PG_GETARG_INET_PP(1);
00462
00463 PG_RETURN_INT32(network_cmp_internal(a1, a2));
00464 }
00465
00466
00467
00468
00469 Datum
00470 network_lt(PG_FUNCTION_ARGS)
00471 {
00472 inet *a1 = PG_GETARG_INET_PP(0);
00473 inet *a2 = PG_GETARG_INET_PP(1);
00474
00475 PG_RETURN_BOOL(network_cmp_internal(a1, a2) < 0);
00476 }
00477
00478 Datum
00479 network_le(PG_FUNCTION_ARGS)
00480 {
00481 inet *a1 = PG_GETARG_INET_PP(0);
00482 inet *a2 = PG_GETARG_INET_PP(1);
00483
00484 PG_RETURN_BOOL(network_cmp_internal(a1, a2) <= 0);
00485 }
00486
00487 Datum
00488 network_eq(PG_FUNCTION_ARGS)
00489 {
00490 inet *a1 = PG_GETARG_INET_PP(0);
00491 inet *a2 = PG_GETARG_INET_PP(1);
00492
00493 PG_RETURN_BOOL(network_cmp_internal(a1, a2) == 0);
00494 }
00495
00496 Datum
00497 network_ge(PG_FUNCTION_ARGS)
00498 {
00499 inet *a1 = PG_GETARG_INET_PP(0);
00500 inet *a2 = PG_GETARG_INET_PP(1);
00501
00502 PG_RETURN_BOOL(network_cmp_internal(a1, a2) >= 0);
00503 }
00504
00505 Datum
00506 network_gt(PG_FUNCTION_ARGS)
00507 {
00508 inet *a1 = PG_GETARG_INET_PP(0);
00509 inet *a2 = PG_GETARG_INET_PP(1);
00510
00511 PG_RETURN_BOOL(network_cmp_internal(a1, a2) > 0);
00512 }
00513
00514 Datum
00515 network_ne(PG_FUNCTION_ARGS)
00516 {
00517 inet *a1 = PG_GETARG_INET_PP(0);
00518 inet *a2 = PG_GETARG_INET_PP(1);
00519
00520 PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
00521 }
00522
00523
00524
00525
00526 Datum
00527 hashinet(PG_FUNCTION_ARGS)
00528 {
00529 inet *addr = PG_GETARG_INET_PP(0);
00530 int addrsize = ip_addrsize(addr);
00531
00532
00533 return hash_any((unsigned char *) VARDATA_ANY(addr), addrsize + 2);
00534 }
00535
00536
00537
00538
00539 Datum
00540 network_sub(PG_FUNCTION_ARGS)
00541 {
00542 inet *a1 = PG_GETARG_INET_PP(0);
00543 inet *a2 = PG_GETARG_INET_PP(1);
00544
00545 if (ip_family(a1) == ip_family(a2))
00546 {
00547 PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2)
00548 && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
00549 }
00550
00551 PG_RETURN_BOOL(false);
00552 }
00553
00554 Datum
00555 network_subeq(PG_FUNCTION_ARGS)
00556 {
00557 inet *a1 = PG_GETARG_INET_PP(0);
00558 inet *a2 = PG_GETARG_INET_PP(1);
00559
00560 if (ip_family(a1) == ip_family(a2))
00561 {
00562 PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2)
00563 && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
00564 }
00565
00566 PG_RETURN_BOOL(false);
00567 }
00568
00569 Datum
00570 network_sup(PG_FUNCTION_ARGS)
00571 {
00572 inet *a1 = PG_GETARG_INET_PP(0);
00573 inet *a2 = PG_GETARG_INET_PP(1);
00574
00575 if (ip_family(a1) == ip_family(a2))
00576 {
00577 PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2)
00578 && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
00579 }
00580
00581 PG_RETURN_BOOL(false);
00582 }
00583
00584 Datum
00585 network_supeq(PG_FUNCTION_ARGS)
00586 {
00587 inet *a1 = PG_GETARG_INET_PP(0);
00588 inet *a2 = PG_GETARG_INET_PP(1);
00589
00590 if (ip_family(a1) == ip_family(a2))
00591 {
00592 PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2)
00593 && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
00594 }
00595
00596 PG_RETURN_BOOL(false);
00597 }
00598
00599
00600
00601
00602 Datum
00603 network_host(PG_FUNCTION_ARGS)
00604 {
00605 inet *ip = PG_GETARG_INET_PP(0);
00606 char *ptr;
00607 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
00608
00609
00610 if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
00611 tmp, sizeof(tmp)) == NULL)
00612 ereport(ERROR,
00613 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
00614 errmsg("could not format inet value: %m")));
00615
00616
00617 if ((ptr = strchr(tmp, '/')) != NULL)
00618 *ptr = '\0';
00619
00620 PG_RETURN_TEXT_P(cstring_to_text(tmp));
00621 }
00622
00623
00624
00625
00626
00627
00628 Datum
00629 network_show(PG_FUNCTION_ARGS)
00630 {
00631 inet *ip = PG_GETARG_INET_PP(0);
00632 int len;
00633 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
00634
00635 if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
00636 tmp, sizeof(tmp)) == NULL)
00637 ereport(ERROR,
00638 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
00639 errmsg("could not format inet value: %m")));
00640
00641
00642 if (strchr(tmp, '/') == NULL)
00643 {
00644 len = strlen(tmp);
00645 snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
00646 }
00647
00648 PG_RETURN_TEXT_P(cstring_to_text(tmp));
00649 }
00650
00651 Datum
00652 inet_abbrev(PG_FUNCTION_ARGS)
00653 {
00654 inet *ip = PG_GETARG_INET_PP(0);
00655 char *dst;
00656 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
00657
00658 dst = inet_net_ntop(ip_family(ip), ip_addr(ip),
00659 ip_bits(ip), tmp, sizeof(tmp));
00660
00661 if (dst == NULL)
00662 ereport(ERROR,
00663 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
00664 errmsg("could not format inet value: %m")));
00665
00666 PG_RETURN_TEXT_P(cstring_to_text(tmp));
00667 }
00668
00669 Datum
00670 cidr_abbrev(PG_FUNCTION_ARGS)
00671 {
00672 inet *ip = PG_GETARG_INET_PP(0);
00673 char *dst;
00674 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
00675
00676 dst = inet_cidr_ntop(ip_family(ip), ip_addr(ip),
00677 ip_bits(ip), tmp, sizeof(tmp));
00678
00679 if (dst == NULL)
00680 ereport(ERROR,
00681 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
00682 errmsg("could not format cidr value: %m")));
00683
00684 PG_RETURN_TEXT_P(cstring_to_text(tmp));
00685 }
00686
00687 Datum
00688 network_masklen(PG_FUNCTION_ARGS)
00689 {
00690 inet *ip = PG_GETARG_INET_PP(0);
00691
00692 PG_RETURN_INT32(ip_bits(ip));
00693 }
00694
00695 Datum
00696 network_family(PG_FUNCTION_ARGS)
00697 {
00698 inet *ip = PG_GETARG_INET_PP(0);
00699
00700 switch (ip_family(ip))
00701 {
00702 case PGSQL_AF_INET:
00703 PG_RETURN_INT32(4);
00704 break;
00705 case PGSQL_AF_INET6:
00706 PG_RETURN_INT32(6);
00707 break;
00708 default:
00709 PG_RETURN_INT32(0);
00710 break;
00711 }
00712 }
00713
00714 Datum
00715 network_broadcast(PG_FUNCTION_ARGS)
00716 {
00717 inet *ip = PG_GETARG_INET_PP(0);
00718 inet *dst;
00719 int byte;
00720 int bits;
00721 int maxbytes;
00722 unsigned char mask;
00723 unsigned char *a,
00724 *b;
00725
00726
00727 dst = (inet *) palloc0(sizeof(inet));
00728
00729 if (ip_family(ip) == PGSQL_AF_INET)
00730 maxbytes = 4;
00731 else
00732 maxbytes = 16;
00733
00734 bits = ip_bits(ip);
00735 a = ip_addr(ip);
00736 b = ip_addr(dst);
00737
00738 for (byte = 0; byte < maxbytes; byte++)
00739 {
00740 if (bits >= 8)
00741 {
00742 mask = 0x00;
00743 bits -= 8;
00744 }
00745 else if (bits == 0)
00746 mask = 0xff;
00747 else
00748 {
00749 mask = 0xff >> bits;
00750 bits = 0;
00751 }
00752
00753 b[byte] = a[byte] | mask;
00754 }
00755
00756 ip_family(dst) = ip_family(ip);
00757 ip_bits(dst) = ip_bits(ip);
00758 SET_INET_VARSIZE(dst);
00759
00760 PG_RETURN_INET_P(dst);
00761 }
00762
00763 Datum
00764 network_network(PG_FUNCTION_ARGS)
00765 {
00766 inet *ip = PG_GETARG_INET_PP(0);
00767 inet *dst;
00768 int byte;
00769 int bits;
00770 unsigned char mask;
00771 unsigned char *a,
00772 *b;
00773
00774
00775 dst = (inet *) palloc0(sizeof(inet));
00776
00777 bits = ip_bits(ip);
00778 a = ip_addr(ip);
00779 b = ip_addr(dst);
00780
00781 byte = 0;
00782
00783 while (bits)
00784 {
00785 if (bits >= 8)
00786 {
00787 mask = 0xff;
00788 bits -= 8;
00789 }
00790 else
00791 {
00792 mask = 0xff << (8 - bits);
00793 bits = 0;
00794 }
00795
00796 b[byte] = a[byte] & mask;
00797 byte++;
00798 }
00799
00800 ip_family(dst) = ip_family(ip);
00801 ip_bits(dst) = ip_bits(ip);
00802 SET_INET_VARSIZE(dst);
00803
00804 PG_RETURN_INET_P(dst);
00805 }
00806
00807 Datum
00808 network_netmask(PG_FUNCTION_ARGS)
00809 {
00810 inet *ip = PG_GETARG_INET_PP(0);
00811 inet *dst;
00812 int byte;
00813 int bits;
00814 unsigned char mask;
00815 unsigned char *b;
00816
00817
00818 dst = (inet *) palloc0(sizeof(inet));
00819
00820 bits = ip_bits(ip);
00821 b = ip_addr(dst);
00822
00823 byte = 0;
00824
00825 while (bits)
00826 {
00827 if (bits >= 8)
00828 {
00829 mask = 0xff;
00830 bits -= 8;
00831 }
00832 else
00833 {
00834 mask = 0xff << (8 - bits);
00835 bits = 0;
00836 }
00837
00838 b[byte] = mask;
00839 byte++;
00840 }
00841
00842 ip_family(dst) = ip_family(ip);
00843 ip_bits(dst) = ip_maxbits(ip);
00844 SET_INET_VARSIZE(dst);
00845
00846 PG_RETURN_INET_P(dst);
00847 }
00848
00849 Datum
00850 network_hostmask(PG_FUNCTION_ARGS)
00851 {
00852 inet *ip = PG_GETARG_INET_PP(0);
00853 inet *dst;
00854 int byte;
00855 int bits;
00856 int maxbytes;
00857 unsigned char mask;
00858 unsigned char *b;
00859
00860
00861 dst = (inet *) palloc0(sizeof(inet));
00862
00863 if (ip_family(ip) == PGSQL_AF_INET)
00864 maxbytes = 4;
00865 else
00866 maxbytes = 16;
00867
00868 bits = ip_maxbits(ip) - ip_bits(ip);
00869 b = ip_addr(dst);
00870
00871 byte = maxbytes - 1;
00872
00873 while (bits)
00874 {
00875 if (bits >= 8)
00876 {
00877 mask = 0xff;
00878 bits -= 8;
00879 }
00880 else
00881 {
00882 mask = 0xff >> (8 - bits);
00883 bits = 0;
00884 }
00885
00886 b[byte] = mask;
00887 byte--;
00888 }
00889
00890 ip_family(dst) = ip_family(ip);
00891 ip_bits(dst) = ip_maxbits(ip);
00892 SET_INET_VARSIZE(dst);
00893
00894 PG_RETURN_INET_P(dst);
00895 }
00896
00897
00898
00899
00900
00901
00902 double
00903 convert_network_to_scalar(Datum value, Oid typid)
00904 {
00905 switch (typid)
00906 {
00907 case INETOID:
00908 case CIDROID:
00909 {
00910 inet *ip = DatumGetInetPP(value);
00911 int len;
00912 double res;
00913 int i;
00914
00915
00916
00917
00918 if (ip_family(ip) == PGSQL_AF_INET)
00919 len = 4;
00920 else
00921 len = 5;
00922
00923 res = ip_family(ip);
00924 for (i = 0; i < len; i++)
00925 {
00926 res *= 256;
00927 res += ip_addr(ip)[i];
00928 }
00929 return res;
00930
00931 break;
00932 }
00933 case MACADDROID:
00934 {
00935 macaddr *mac = DatumGetMacaddrP(value);
00936 double res;
00937
00938 res = (mac->a << 16) | (mac->b << 8) | (mac->c);
00939 res *= 256 * 256 * 256;
00940 res += (mac->d << 16) | (mac->e << 8) | (mac->f);
00941 return res;
00942 }
00943 }
00944
00945
00946
00947
00948
00949 elog(ERROR, "unsupported type: %u", typid);
00950 return 0;
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965 static int
00966 bitncmp(void *l, void *r, int n)
00967 {
00968 u_int lb,
00969 rb;
00970 int x,
00971 b;
00972
00973 b = n / 8;
00974 x = memcmp(l, r, b);
00975 if (x || (n % 8) == 0)
00976 return x;
00977
00978 lb = ((const u_char *) l)[b];
00979 rb = ((const u_char *) r)[b];
00980 for (b = n % 8; b > 0; b--)
00981 {
00982 if (IS_HIGHBIT_SET(lb) != IS_HIGHBIT_SET(rb))
00983 {
00984 if (IS_HIGHBIT_SET(lb))
00985 return 1;
00986 return -1;
00987 }
00988 lb <<= 1;
00989 rb <<= 1;
00990 }
00991 return 0;
00992 }
00993
00994 static bool
00995 addressOK(unsigned char *a, int bits, int family)
00996 {
00997 int byte;
00998 int nbits;
00999 int maxbits;
01000 int maxbytes;
01001 unsigned char mask;
01002
01003 if (family == PGSQL_AF_INET)
01004 {
01005 maxbits = 32;
01006 maxbytes = 4;
01007 }
01008 else
01009 {
01010 maxbits = 128;
01011 maxbytes = 16;
01012 }
01013 Assert(bits <= maxbits);
01014
01015 if (bits == maxbits)
01016 return true;
01017
01018 byte = bits / 8;
01019
01020 nbits = bits % 8;
01021 mask = 0xff;
01022 if (bits != 0)
01023 mask >>= nbits;
01024
01025 while (byte < maxbytes)
01026 {
01027 if ((a[byte] & mask) != 0)
01028 return false;
01029 mask = 0xff;
01030 byte++;
01031 }
01032
01033 return true;
01034 }
01035
01036
01037
01038
01039
01040
01041
01042
01043 Datum
01044 network_scan_first(Datum in)
01045 {
01046 return DirectFunctionCall1(network_network, in);
01047 }
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057 Datum
01058 network_scan_last(Datum in)
01059 {
01060 return DirectFunctionCall2(inet_set_masklen,
01061 DirectFunctionCall1(network_broadcast, in),
01062 Int32GetDatum(-1));
01063 }
01064
01065
01066
01067
01068
01069 Datum
01070 inet_client_addr(PG_FUNCTION_ARGS)
01071 {
01072 Port *port = MyProcPort;
01073 char remote_host[NI_MAXHOST];
01074 int ret;
01075
01076 if (port == NULL)
01077 PG_RETURN_NULL();
01078
01079 switch (port->raddr.addr.ss_family)
01080 {
01081 case AF_INET:
01082 #ifdef HAVE_IPV6
01083 case AF_INET6:
01084 #endif
01085 break;
01086 default:
01087 PG_RETURN_NULL();
01088 }
01089
01090 remote_host[0] = '\0';
01091
01092 ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
01093 remote_host, sizeof(remote_host),
01094 NULL, 0,
01095 NI_NUMERICHOST | NI_NUMERICSERV);
01096 if (ret != 0)
01097 PG_RETURN_NULL();
01098
01099 clean_ipv6_addr(port->raddr.addr.ss_family, remote_host);
01100
01101 PG_RETURN_INET_P(network_in(remote_host, false));
01102 }
01103
01104
01105
01106
01107
01108 Datum
01109 inet_client_port(PG_FUNCTION_ARGS)
01110 {
01111 Port *port = MyProcPort;
01112 char remote_port[NI_MAXSERV];
01113 int ret;
01114
01115 if (port == NULL)
01116 PG_RETURN_NULL();
01117
01118 switch (port->raddr.addr.ss_family)
01119 {
01120 case AF_INET:
01121 #ifdef HAVE_IPV6
01122 case AF_INET6:
01123 #endif
01124 break;
01125 default:
01126 PG_RETURN_NULL();
01127 }
01128
01129 remote_port[0] = '\0';
01130
01131 ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
01132 NULL, 0,
01133 remote_port, sizeof(remote_port),
01134 NI_NUMERICHOST | NI_NUMERICSERV);
01135 if (ret != 0)
01136 PG_RETURN_NULL();
01137
01138 PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
01139 }
01140
01141
01142
01143
01144
01145 Datum
01146 inet_server_addr(PG_FUNCTION_ARGS)
01147 {
01148 Port *port = MyProcPort;
01149 char local_host[NI_MAXHOST];
01150 int ret;
01151
01152 if (port == NULL)
01153 PG_RETURN_NULL();
01154
01155 switch (port->laddr.addr.ss_family)
01156 {
01157 case AF_INET:
01158 #ifdef HAVE_IPV6
01159 case AF_INET6:
01160 #endif
01161 break;
01162 default:
01163 PG_RETURN_NULL();
01164 }
01165
01166 local_host[0] = '\0';
01167
01168 ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
01169 local_host, sizeof(local_host),
01170 NULL, 0,
01171 NI_NUMERICHOST | NI_NUMERICSERV);
01172 if (ret != 0)
01173 PG_RETURN_NULL();
01174
01175 clean_ipv6_addr(port->laddr.addr.ss_family, local_host);
01176
01177 PG_RETURN_INET_P(network_in(local_host, false));
01178 }
01179
01180
01181
01182
01183
01184 Datum
01185 inet_server_port(PG_FUNCTION_ARGS)
01186 {
01187 Port *port = MyProcPort;
01188 char local_port[NI_MAXSERV];
01189 int ret;
01190
01191 if (port == NULL)
01192 PG_RETURN_NULL();
01193
01194 switch (port->laddr.addr.ss_family)
01195 {
01196 case AF_INET:
01197 #ifdef HAVE_IPV6
01198 case AF_INET6:
01199 #endif
01200 break;
01201 default:
01202 PG_RETURN_NULL();
01203 }
01204
01205 local_port[0] = '\0';
01206
01207 ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
01208 NULL, 0,
01209 local_port, sizeof(local_port),
01210 NI_NUMERICHOST | NI_NUMERICSERV);
01211 if (ret != 0)
01212 PG_RETURN_NULL();
01213
01214 PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
01215 }
01216
01217
01218 Datum
01219 inetnot(PG_FUNCTION_ARGS)
01220 {
01221 inet *ip = PG_GETARG_INET_PP(0);
01222 inet *dst;
01223
01224 dst = (inet *) palloc0(sizeof(inet));
01225
01226 {
01227 int nb = ip_addrsize(ip);
01228 unsigned char *pip = ip_addr(ip);
01229 unsigned char *pdst = ip_addr(dst);
01230
01231 while (nb-- > 0)
01232 pdst[nb] = ~pip[nb];
01233 }
01234 ip_bits(dst) = ip_bits(ip);
01235
01236 ip_family(dst) = ip_family(ip);
01237 SET_INET_VARSIZE(dst);
01238
01239 PG_RETURN_INET_P(dst);
01240 }
01241
01242
01243 Datum
01244 inetand(PG_FUNCTION_ARGS)
01245 {
01246 inet *ip = PG_GETARG_INET_PP(0);
01247 inet *ip2 = PG_GETARG_INET_PP(1);
01248 inet *dst;
01249
01250 dst = (inet *) palloc0(sizeof(inet));
01251
01252 if (ip_family(ip) != ip_family(ip2))
01253 ereport(ERROR,
01254 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01255 errmsg("cannot AND inet values of different sizes")));
01256 else
01257 {
01258 int nb = ip_addrsize(ip);
01259 unsigned char *pip = ip_addr(ip);
01260 unsigned char *pip2 = ip_addr(ip2);
01261 unsigned char *pdst = ip_addr(dst);
01262
01263 while (nb-- > 0)
01264 pdst[nb] = pip[nb] & pip2[nb];
01265 }
01266 ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
01267
01268 ip_family(dst) = ip_family(ip);
01269 SET_INET_VARSIZE(dst);
01270
01271 PG_RETURN_INET_P(dst);
01272 }
01273
01274
01275 Datum
01276 inetor(PG_FUNCTION_ARGS)
01277 {
01278 inet *ip = PG_GETARG_INET_PP(0);
01279 inet *ip2 = PG_GETARG_INET_PP(1);
01280 inet *dst;
01281
01282 dst = (inet *) palloc0(sizeof(inet));
01283
01284 if (ip_family(ip) != ip_family(ip2))
01285 ereport(ERROR,
01286 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01287 errmsg("cannot OR inet values of different sizes")));
01288 else
01289 {
01290 int nb = ip_addrsize(ip);
01291 unsigned char *pip = ip_addr(ip);
01292 unsigned char *pip2 = ip_addr(ip2);
01293 unsigned char *pdst = ip_addr(dst);
01294
01295 while (nb-- > 0)
01296 pdst[nb] = pip[nb] | pip2[nb];
01297 }
01298 ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
01299
01300 ip_family(dst) = ip_family(ip);
01301 SET_INET_VARSIZE(dst);
01302
01303 PG_RETURN_INET_P(dst);
01304 }
01305
01306
01307 static inet *
01308 internal_inetpl(inet *ip, int64 addend)
01309 {
01310 inet *dst;
01311
01312 dst = (inet *) palloc0(sizeof(inet));
01313
01314 {
01315 int nb = ip_addrsize(ip);
01316 unsigned char *pip = ip_addr(ip);
01317 unsigned char *pdst = ip_addr(dst);
01318 int carry = 0;
01319
01320 while (nb-- > 0)
01321 {
01322 carry = pip[nb] + (int) (addend & 0xFF) + carry;
01323 pdst[nb] = (unsigned char) (carry & 0xFF);
01324 carry >>= 8;
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335 addend &= ~((int64) 0xFF);
01336 addend /= 0x100;
01337 }
01338
01339
01340
01341
01342
01343
01344 if (!((addend == 0 && carry == 0) ||
01345 (addend == -1 && carry == 1)))
01346 ereport(ERROR,
01347 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01348 errmsg("result is out of range")));
01349 }
01350
01351 ip_bits(dst) = ip_bits(ip);
01352 ip_family(dst) = ip_family(ip);
01353 SET_INET_VARSIZE(dst);
01354
01355 return dst;
01356 }
01357
01358
01359 Datum
01360 inetpl(PG_FUNCTION_ARGS)
01361 {
01362 inet *ip = PG_GETARG_INET_PP(0);
01363 int64 addend = PG_GETARG_INT64(1);
01364
01365 PG_RETURN_INET_P(internal_inetpl(ip, addend));
01366 }
01367
01368
01369 Datum
01370 inetmi_int8(PG_FUNCTION_ARGS)
01371 {
01372 inet *ip = PG_GETARG_INET_PP(0);
01373 int64 addend = PG_GETARG_INT64(1);
01374
01375 PG_RETURN_INET_P(internal_inetpl(ip, -addend));
01376 }
01377
01378
01379 Datum
01380 inetmi(PG_FUNCTION_ARGS)
01381 {
01382 inet *ip = PG_GETARG_INET_PP(0);
01383 inet *ip2 = PG_GETARG_INET_PP(1);
01384 int64 res = 0;
01385
01386 if (ip_family(ip) != ip_family(ip2))
01387 ereport(ERROR,
01388 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01389 errmsg("cannot subtract inet values of different sizes")));
01390 else
01391 {
01392
01393
01394
01395
01396
01397
01398 int nb = ip_addrsize(ip);
01399 int byte = 0;
01400 unsigned char *pip = ip_addr(ip);
01401 unsigned char *pip2 = ip_addr(ip2);
01402 int carry = 1;
01403
01404 while (nb-- > 0)
01405 {
01406 int lobyte;
01407
01408 carry = pip[nb] + (~pip2[nb] & 0xFF) + carry;
01409 lobyte = carry & 0xFF;
01410 if (byte < sizeof(int64))
01411 {
01412 res |= ((int64) lobyte) << (byte * 8);
01413 }
01414 else
01415 {
01416
01417
01418
01419
01420
01421 if ((res < 0) ? (lobyte != 0xFF) : (lobyte != 0))
01422 ereport(ERROR,
01423 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01424 errmsg("result is out of range")));
01425 }
01426 carry >>= 8;
01427 byte++;
01428 }
01429
01430
01431
01432
01433
01434 if (carry == 0 && byte < sizeof(int64))
01435 res |= ((int64) -1) << (byte * 8);
01436 }
01437
01438 PG_RETURN_INT64(res);
01439 }
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456 void
01457 clean_ipv6_addr(int addr_family, char *addr)
01458 {
01459 #ifdef HAVE_IPV6
01460 if (addr_family == AF_INET6)
01461 {
01462 char *pct = strchr(addr, '%');
01463
01464 if (pct)
01465 *pct = '\0';
01466 }
01467 #endif
01468 }