LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - network.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 69.8 % 708 494 2 3 32 177 52 5 437 32 49 5 5
Current Date: 2023-04-08 17:13:01 Functions: 80.0 % 70 56 1 3 10 8 3 45 3 8 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 100.0 % 5 5 1 4
Legend: Lines: hit not hit (60,120] days: 71.4 % 7 5 2 5
(240..) days: 69.5 % 696 484 3 32 177 51 433 32 49
Function coverage date bins:
(60,120] days: 100.0 % 1 1 1
(240..) days: 68.8 % 80 55 1 3 10 8 2 45 3 8

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  *  PostgreSQL type definitions for the INET and CIDR types.
                                  3                 :  *
                                  4                 :  *  src/backend/utils/adt/network.c
                                  5                 :  *
                                  6                 :  *  Jon Postel RIP 16 Oct 1998
                                  7                 :  */
                                  8                 : 
                                  9                 : #include "postgres.h"
                                 10                 : 
                                 11                 : #include <sys/socket.h>
                                 12                 : #include <netinet/in.h>
                                 13                 : #include <arpa/inet.h>
                                 14                 : 
                                 15                 : #include "access/stratnum.h"
                                 16                 : #include "catalog/pg_opfamily.h"
                                 17                 : #include "catalog/pg_type.h"
                                 18                 : #include "common/hashfn.h"
                                 19                 : #include "common/ip.h"
                                 20                 : #include "lib/hyperloglog.h"
                                 21                 : #include "libpq/libpq-be.h"
                                 22                 : #include "libpq/pqformat.h"
                                 23                 : #include "miscadmin.h"
                                 24                 : #include "nodes/makefuncs.h"
                                 25                 : #include "nodes/nodeFuncs.h"
                                 26                 : #include "nodes/supportnodes.h"
                                 27                 : #include "utils/builtins.h"
                                 28                 : #include "utils/fmgroids.h"
                                 29                 : #include "utils/guc.h"
                                 30                 : #include "utils/inet.h"
                                 31                 : #include "utils/lsyscache.h"
                                 32                 : #include "utils/sortsupport.h"
                                 33                 : 
                                 34                 : 
                                 35                 : /*
                                 36                 :  * An IPv4 netmask size is a value in the range of 0 - 32, which is
                                 37                 :  * represented with 6 bits in inet/cidr abbreviated keys where possible.
                                 38                 :  *
                                 39                 :  * An IPv4 inet/cidr abbreviated key can use up to 25 bits for subnet
                                 40                 :  * component.
                                 41                 :  */
                                 42                 : #define ABBREV_BITS_INET4_NETMASK_SIZE  6
                                 43                 : #define ABBREV_BITS_INET4_SUBNET        25
                                 44                 : 
                                 45                 : /* sortsupport for inet/cidr */
                                 46                 : typedef struct
                                 47                 : {
                                 48                 :     int64       input_count;    /* number of non-null values seen */
                                 49                 :     bool        estimating;     /* true if estimating cardinality */
                                 50                 : 
                                 51                 :     hyperLogLogState abbr_card; /* cardinality estimator */
                                 52                 : } network_sortsupport_state;
                                 53                 : 
                                 54                 : static int32 network_cmp_internal(inet *a1, inet *a2);
                                 55                 : static int  network_fast_cmp(Datum x, Datum y, SortSupport ssup);
                                 56                 : static bool network_abbrev_abort(int memtupcount, SortSupport ssup);
                                 57                 : static Datum network_abbrev_convert(Datum original, SortSupport ssup);
                                 58                 : static List *match_network_function(Node *leftop,
                                 59                 :                                     Node *rightop,
                                 60                 :                                     int indexarg,
                                 61                 :                                     Oid funcid,
                                 62                 :                                     Oid opfamily);
                                 63                 : static List *match_network_subset(Node *leftop,
                                 64                 :                                   Node *rightop,
                                 65                 :                                   bool is_eq,
                                 66                 :                                   Oid opfamily);
                                 67                 : static bool addressOK(unsigned char *a, int bits, int family);
                                 68                 : static inet *internal_inetpl(inet *ip, int64 addend);
                                 69                 : 
                                 70                 : 
                                 71                 : /*
                                 72                 :  * Common INET/CIDR input routine
                                 73                 :  */
                                 74                 : static inet *
  116 tgl                        75 GNC        2348 : network_in(char *src, bool is_cidr, Node *escontext)
                                 76                 : {
                                 77                 :     int         bits;
                                 78                 :     inet       *dst;
                                 79                 : 
 5847 tgl                        80 CBC        2348 :     dst = (inet *) palloc0(sizeof(inet));
                                 81                 : 
                                 82                 :     /*
                                 83                 :      * First, check to see if this is an IPv6 or IPv4 address.  IPv6 addresses
                                 84                 :      * will have a : somewhere in them (several, in fact) so if there is one
                                 85                 :      * present, assume it's V6, otherwise assume it's V4.
                                 86                 :      */
                                 87                 : 
 7191                            88            2348 :     if (strchr(src, ':') != NULL)
 7229 bruce                      89             448 :         ip_family(dst) = PGSQL_AF_INET6;
                                 90                 :     else
                                 91            1900 :         ip_family(dst) = PGSQL_AF_INET;
                                 92                 : 
 1330 tgl                        93            3047 :     bits = pg_inet_net_pton(ip_family(dst), src, ip_addr(dst),
                                 94             699 :                             is_cidr ? ip_addrsize(dst) : -1);
 7229 bruce                      95            2348 :     if ((bits < 0) || (bits > ip_maxbits(dst)))
  116 tgl                        96 GNC          15 :         ereturn(escontext, NULL,
                                 97                 :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                                 98                 :         /* translator: first %s is inet or cidr */
                                 99                 :                  errmsg("invalid input syntax for type %s: \"%s\"",
                                100                 :                         is_cidr ? "cidr" : "inet", src)));
                                101                 : 
                                102                 :     /*
                                103                 :      * Error check: CIDR values must not have any bits set beyond the masklen.
                                104                 :      */
 6285 bruce                     105 CBC        2333 :     if (is_cidr)
                                106                 :     {
 7229                           107             690 :         if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
  116 tgl                       108 GNC          15 :             ereturn(escontext, NULL,
                                109                 :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                                110                 :                      errmsg("invalid cidr value: \"%s\"", src),
                                111                 :                      errdetail("Value has bits set to right of mask.")));
                                112                 :     }
                                113                 : 
 8935 bruce                     114 CBC        2318 :     ip_bits(dst) = bits;
 5847 tgl                       115            2318 :     SET_INET_VARSIZE(dst);
                                116                 : 
 8935 bruce                     117            2318 :     return dst;
                                118                 : }
                                119                 : 
                                120                 : Datum
 8284 tgl                       121            1649 : inet_in(PG_FUNCTION_ARGS)
                                122                 : {
                                123            1649 :     char       *src = PG_GETARG_CSTRING(0);
                                124                 : 
  116 tgl                       125 GNC        1649 :     PG_RETURN_INET_P(network_in(src, false, fcinfo->context));
                                126                 : }
                                127                 : 
                                128                 : Datum
 8284 tgl                       129 CBC         699 : cidr_in(PG_FUNCTION_ARGS)
                                130                 : {
                                131             699 :     char       *src = PG_GETARG_CSTRING(0);
                                132                 : 
  116 tgl                       133 GNC         699 :     PG_RETURN_INET_P(network_in(src, true, fcinfo->context));
                                134                 : }
                                135                 : 
                                136                 : 
                                137                 : /*
                                138                 :  * Common INET/CIDR output routine
                                139                 :  */
                                140                 : static char *
 6282 tgl                       141 CBC        7038 : network_out(inet *src, bool is_cidr)
                                142                 : {
                                143                 :     char        tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
                                144                 :     char       *dst;
                                145                 :     int         len;
                                146                 : 
 1330                           147            7038 :     dst = pg_inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),
                                148                 :                            tmp, sizeof(tmp));
 7229 bruce                     149            7038 :     if (dst == NULL)
 7196 tgl                       150 UBC           0 :         ereport(ERROR,
                                151                 :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                                152                 :                  errmsg("could not format inet value: %m")));
                                153                 : 
                                154                 :     /* For CIDR, add /n if not present */
 6282 tgl                       155 CBC        7038 :     if (is_cidr && strchr(tmp, '/') == NULL)
                                156                 :     {
 7229 bruce                     157             539 :         len = strlen(tmp);
                                158             539 :         snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
                                159                 :     }
                                160                 : 
 6282 tgl                       161            7038 :     return pstrdup(tmp);
                                162                 : }
                                163                 : 
                                164                 : Datum
                                165            4238 : inet_out(PG_FUNCTION_ARGS)
                                166                 : {
 4136 heikki.linnakangas        167            4238 :     inet       *src = PG_GETARG_INET_PP(0);
                                168                 : 
 6282 tgl                       169            4238 :     PG_RETURN_CSTRING(network_out(src, false));
                                170                 : }
                                171                 : 
                                172                 : Datum
 8284                           173            2800 : cidr_out(PG_FUNCTION_ARGS)
                                174                 : {
 4136 heikki.linnakangas        175            2800 :     inet       *src = PG_GETARG_INET_PP(0);
                                176                 : 
 6282 tgl                       177            2800 :     PG_RETURN_CSTRING(network_out(src, true));
                                178                 : }
                                179                 : 
                                180                 : 
                                181                 : /*
                                182                 :  *      network_recv        - converts external binary format to inet
                                183                 :  *
                                184                 :  * The external representation is (one byte apiece for)
                                185                 :  * family, bits, is_cidr, address length, address in network byte order.
                                186                 :  *
                                187                 :  * Presence of is_cidr is largely for historical reasons, though it might
                                188                 :  * allow some code-sharing on the client side.  We send it correctly on
                                189                 :  * output, but ignore the value on input.
                                190                 :  */
                                191                 : static inet *
 6282 tgl                       192 UBC           0 : network_recv(StringInfo buf, bool is_cidr)
                                193                 : {
                                194                 :     inet       *addr;
                                195                 :     char       *addrptr;
                                196                 :     int         bits;
                                197                 :     int         nb,
                                198                 :                 i;
                                199                 : 
                                200                 :     /* make sure any unused bits in a CIDR value are zeroed */
 5847                           201               0 :     addr = (inet *) palloc0(sizeof(inet));
                                202                 : 
 7271                           203               0 :     ip_family(addr) = pq_getmsgbyte(buf);
 7191                           204               0 :     if (ip_family(addr) != PGSQL_AF_INET &&
                                205               0 :         ip_family(addr) != PGSQL_AF_INET6)
 7196                           206               0 :         ereport(ERROR,
                                207                 :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                                208                 :         /* translator: %s is inet or cidr */
                                209                 :                  errmsg("invalid address family in external \"%s\" value",
                                210                 :                         is_cidr ? "cidr" : "inet")));
 7271                           211               0 :     bits = pq_getmsgbyte(buf);
 7229 bruce                     212               0 :     if (bits < 0 || bits > ip_maxbits(addr))
 7196 tgl                       213               0 :         ereport(ERROR,
                                214                 :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                                215                 :         /* translator: %s is inet or cidr */
                                216                 :                  errmsg("invalid bits in external \"%s\" value",
                                217                 :                         is_cidr ? "cidr" : "inet")));
 7271                           218               0 :     ip_bits(addr) = bits;
 6282                           219               0 :     i = pq_getmsgbyte(buf);     /* ignore is_cidr */
 7271                           220               0 :     nb = pq_getmsgbyte(buf);
                                221               0 :     if (nb != ip_addrsize(addr))
 7196                           222               0 :         ereport(ERROR,
                                223                 :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                                224                 :         /* translator: %s is inet or cidr */
                                225                 :                  errmsg("invalid length in external \"%s\" value",
                                226                 :                         is_cidr ? "cidr" : "inet")));
                                227                 : 
 7188 bruce                     228               0 :     addrptr = (char *) ip_addr(addr);
 7271 tgl                       229               0 :     for (i = 0; i < nb; i++)
                                230               0 :         addrptr[i] = pq_getmsgbyte(buf);
                                231                 : 
                                232                 :     /*
                                233                 :      * Error check: CIDR values must not have any bits set beyond the masklen.
                                234                 :      */
 6282                           235               0 :     if (is_cidr)
                                236                 :     {
 7229 bruce                     237               0 :         if (!addressOK(ip_addr(addr), bits, ip_family(addr)))
 7196 tgl                       238               0 :             ereport(ERROR,
                                239                 :                     (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                                240                 :                      errmsg("invalid external \"cidr\" value"),
                                241                 :                      errdetail("Value has bits set to right of mask.")));
                                242                 :     }
                                243                 : 
 5847                           244               0 :     SET_INET_VARSIZE(addr);
                                245                 : 
 6282                           246               0 :     return addr;
                                247                 : }
                                248                 : 
                                249                 : Datum
                                250               0 : inet_recv(PG_FUNCTION_ARGS)
                                251                 : {
                                252               0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
                                253                 : 
                                254               0 :     PG_RETURN_INET_P(network_recv(buf, false));
                                255                 : }
                                256                 : 
                                257                 : Datum
 7271                           258               0 : cidr_recv(PG_FUNCTION_ARGS)
                                259                 : {
 6282                           260               0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
                                261                 : 
                                262               0 :     PG_RETURN_INET_P(network_recv(buf, true));
                                263                 : }
                                264                 : 
                                265                 : 
                                266                 : /*
                                267                 :  *      network_send        - converts inet to binary format
                                268                 :  */
                                269                 : static bytea *
                                270               0 : network_send(inet *addr, bool is_cidr)
                                271                 : {
                                272                 :     StringInfoData buf;
                                273                 :     char       *addrptr;
                                274                 :     int         nb,
                                275                 :                 i;
                                276                 : 
 7271                           277               0 :     pq_begintypsend(&buf);
                                278               0 :     pq_sendbyte(&buf, ip_family(addr));
                                279               0 :     pq_sendbyte(&buf, ip_bits(addr));
 6282                           280               0 :     pq_sendbyte(&buf, is_cidr);
 7271                           281               0 :     nb = ip_addrsize(addr);
                                282               0 :     if (nb < 0)
                                283               0 :         nb = 0;
                                284               0 :     pq_sendbyte(&buf, nb);
 7188 bruce                     285               0 :     addrptr = (char *) ip_addr(addr);
 7271 tgl                       286               0 :     for (i = 0; i < nb; i++)
                                287               0 :         pq_sendbyte(&buf, addrptr[i]);
 6282                           288               0 :     return pq_endtypsend(&buf);
                                289                 : }
                                290                 : 
                                291                 : Datum
                                292               0 : inet_send(PG_FUNCTION_ARGS)
                                293                 : {
 4136 heikki.linnakangas        294               0 :     inet       *addr = PG_GETARG_INET_PP(0);
                                295                 : 
 6282 tgl                       296               0 :     PG_RETURN_BYTEA_P(network_send(addr, false));
                                297                 : }
                                298                 : 
                                299                 : Datum
 7271                           300               0 : cidr_send(PG_FUNCTION_ARGS)
                                301                 : {
 4136 heikki.linnakangas        302               0 :     inet       *addr = PG_GETARG_INET_PP(0);
                                303                 : 
 6282 tgl                       304               0 :     PG_RETURN_BYTEA_P(network_send(addr, true));
                                305                 : }
                                306                 : 
                                307                 : 
                                308                 : Datum
 6282 tgl                       309 CBC        1770 : inet_to_cidr(PG_FUNCTION_ARGS)
                                310                 : {
 4136 heikki.linnakangas        311            1770 :     inet       *src = PG_GETARG_INET_PP(0);
                                312                 :     int         bits;
                                313                 : 
 6282 tgl                       314            1770 :     bits = ip_bits(src);
                                315                 : 
                                316                 :     /* safety check */
                                317            1770 :     if ((bits < 0) || (bits > ip_maxbits(src)))
 6282 tgl                       318 UBC           0 :         elog(ERROR, "invalid inet bit length: %d", bits);
                                319                 : 
 2420 tgl                       320 CBC        1770 :     PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
                                321                 : }
                                322                 : 
                                323                 : Datum
 7970 bruce                     324              75 : inet_set_masklen(PG_FUNCTION_ARGS)
                                325                 : {
 4136 heikki.linnakangas        326              75 :     inet       *src = PG_GETARG_INET_PP(0);
 7836 bruce                     327              75 :     int         bits = PG_GETARG_INT32(1);
                                328                 :     inet       *dst;
                                329                 : 
 7188                           330              75 :     if (bits == -1)
                                331              24 :         bits = ip_maxbits(src);
                                332                 : 
 7229                           333              75 :     if ((bits < 0) || (bits > ip_maxbits(src)))
 7196 tgl                       334 UBC           0 :         ereport(ERROR,
                                335                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                336                 :                  errmsg("invalid mask length: %d", bits)));
                                337                 : 
                                338                 :     /* clone the original data */
 5847 tgl                       339 CBC          75 :     dst = (inet *) palloc(VARSIZE_ANY(src));
                                340              75 :     memcpy(dst, src, VARSIZE_ANY(src));
                                341                 : 
 7836 bruce                     342              75 :     ip_bits(dst) = bits;
                                343                 : 
 7970                           344              75 :     PG_RETURN_INET_P(dst);
                                345                 : }
                                346                 : 
                                347                 : Datum
 6282 tgl                       348 UBC           0 : cidr_set_masklen(PG_FUNCTION_ARGS)
                                349                 : {
 4136 heikki.linnakangas        350               0 :     inet       *src = PG_GETARG_INET_PP(0);
 6282 tgl                       351               0 :     int         bits = PG_GETARG_INT32(1);
                                352                 : 
                                353               0 :     if (bits == -1)
                                354               0 :         bits = ip_maxbits(src);
                                355                 : 
                                356               0 :     if ((bits < 0) || (bits > ip_maxbits(src)))
                                357               0 :         ereport(ERROR,
                                358                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                359                 :                  errmsg("invalid mask length: %d", bits)));
                                360                 : 
 2420                           361               0 :     PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
                                362                 : }
                                363                 : 
                                364                 : /*
                                365                 :  * Copy src and set mask length to 'bits' (which must be valid for the family)
                                366                 :  */
                                367                 : inet *
 2420 tgl                       368 CBC        1884 : cidr_set_masklen_internal(const inet *src, int bits)
                                369                 : {
                                370            1884 :     inet       *dst = (inet *) palloc0(sizeof(inet));
                                371                 : 
                                372            1884 :     ip_family(dst) = ip_family(src);
                                373            1884 :     ip_bits(dst) = bits;
                                374                 : 
                                375            1884 :     if (bits > 0)
                                376                 :     {
                                377            1884 :         Assert(bits <= ip_maxbits(dst));
                                378                 : 
                                379                 :         /* Clone appropriate bytes of the address, leaving the rest 0 */
                                380            1884 :         memcpy(ip_addr(dst), ip_addr(src), (bits + 7) / 8);
                                381                 : 
                                382                 :         /* Clear any unwanted bits in the last partial byte */
                                383            1884 :         if (bits % 8)
                                384              30 :             ip_addr(dst)[bits / 8] &= ~(0xFF >> (bits % 8));
                                385                 :     }
                                386                 : 
                                387                 :     /* Set varlena header correctly */
                                388            1884 :     SET_INET_VARSIZE(dst);
                                389                 : 
                                390            1884 :     return dst;
                                391                 : }
                                392                 : 
                                393                 : /*
                                394                 :  *  Basic comparison function for sorting and inet/cidr comparisons.
                                395                 :  *
                                396                 :  * Comparison is first on the common bits of the network part, then on
                                397                 :  * the length of the network part, and then on the whole unmasked address.
                                398                 :  * The effect is that the network part is the major sort key, and for
                                399                 :  * equal network parts we sort on the host part.  Note this is only sane
                                400                 :  * for CIDR if address bits to the right of the mask are guaranteed zero;
                                401                 :  * otherwise logically-equal CIDRs might compare different.
                                402                 :  */
                                403                 : 
                                404                 : static int32
 8284                           405          238810 : network_cmp_internal(inet *a1, inet *a2)
                                406                 : {
 7229 bruce                     407          238810 :     if (ip_family(a1) == ip_family(a2))
                                408                 :     {
                                409                 :         int         order;
                                410                 : 
                                411          163042 :         order = bitncmp(ip_addr(a1), ip_addr(a2),
 7188                           412          163042 :                         Min(ip_bits(a1), ip_bits(a2)));
 8199 tgl                       413          163042 :         if (order != 0)
                                414          152703 :             return order;
                                415           10339 :         order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
 8284                           416           10339 :         if (order != 0)
                                417             438 :             return order;
 7229 bruce                     418            9901 :         return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));
                                419                 :     }
                                420                 : 
                                421           75768 :     return ip_family(a1) - ip_family(a2);
                                422                 : }
                                423                 : 
                                424                 : Datum
 8284 tgl                       425             134 : network_cmp(PG_FUNCTION_ARGS)
                                426                 : {
 4136 heikki.linnakangas        427             134 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                428             134 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                429                 : 
 8284 tgl                       430             134 :     PG_RETURN_INT32(network_cmp_internal(a1, a2));
                                431                 : }
                                432                 : 
                                433                 : /*
                                434                 :  * SortSupport strategy routine
                                435                 :  */
                                436                 : Datum
 1347 pg                        437             153 : network_sortsupport(PG_FUNCTION_ARGS)
                                438                 : {
                                439             153 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
                                440                 : 
                                441             153 :     ssup->comparator = network_fast_cmp;
                                442             153 :     ssup->ssup_extra = NULL;
                                443                 : 
                                444             153 :     if (ssup->abbreviate)
                                445                 :     {
                                446                 :         network_sortsupport_state *uss;
                                447                 :         MemoryContext oldcontext;
                                448                 : 
                                449              80 :         oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
                                450                 : 
                                451              80 :         uss = palloc(sizeof(network_sortsupport_state));
                                452              80 :         uss->input_count = 0;
                                453              80 :         uss->estimating = true;
                                454              80 :         initHyperLogLog(&uss->abbr_card, 10);
                                455                 : 
                                456              80 :         ssup->ssup_extra = uss;
                                457                 : 
  372 john.naylor               458              80 :         ssup->comparator = ssup_datum_unsigned_cmp;
 1347 pg                        459              80 :         ssup->abbrev_converter = network_abbrev_convert;
                                460              80 :         ssup->abbrev_abort = network_abbrev_abort;
                                461              80 :         ssup->abbrev_full_comparator = network_fast_cmp;
                                462                 : 
                                463              80 :         MemoryContextSwitchTo(oldcontext);
                                464                 :     }
                                465                 : 
                                466             153 :     PG_RETURN_VOID();
                                467                 : }
                                468                 : 
                                469                 : /*
                                470                 :  * SortSupport comparison func
                                471                 :  */
                                472                 : static int
                                473            5978 : network_fast_cmp(Datum x, Datum y, SortSupport ssup)
                                474                 : {
                                475            5978 :     inet       *arg1 = DatumGetInetPP(x);
                                476            5978 :     inet       *arg2 = DatumGetInetPP(y);
                                477                 : 
                                478            5978 :     return network_cmp_internal(arg1, arg2);
                                479                 : }
                                480                 : 
                                481                 : /*
                                482                 :  * Callback for estimating effectiveness of abbreviated key optimization.
                                483                 :  *
                                484                 :  * We pay no attention to the cardinality of the non-abbreviated data, because
                                485                 :  * there is no equality fast-path within authoritative inet comparator.
                                486                 :  */
                                487                 : static bool
                                488              21 : network_abbrev_abort(int memtupcount, SortSupport ssup)
                                489                 : {
                                490              21 :     network_sortsupport_state *uss = ssup->ssup_extra;
                                491                 :     double      abbr_card;
                                492                 : 
                                493              21 :     if (memtupcount < 10000 || uss->input_count < 10000 || !uss->estimating)
                                494              21 :         return false;
                                495                 : 
 1347 pg                        496 UBC           0 :     abbr_card = estimateHyperLogLog(&uss->abbr_card);
                                497                 : 
                                498                 :     /*
                                499                 :      * If we have >100k distinct values, then even if we were sorting many
                                500                 :      * billion rows we'd likely still break even, and the penalty of undoing
                                501                 :      * that many rows of abbrevs would probably not be worth it. At this point
                                502                 :      * we stop counting because we know that we're now fully committed.
                                503                 :      */
                                504               0 :     if (abbr_card > 100000.0)
                                505                 :     {
                                506                 : #ifdef TRACE_SORT
                                507               0 :         if (trace_sort)
                                508               0 :             elog(LOG,
                                509                 :                  "network_abbrev: estimation ends at cardinality %f"
                                510                 :                  " after " INT64_FORMAT " values (%d rows)",
                                511                 :                  abbr_card, uss->input_count, memtupcount);
                                512                 : #endif
                                513               0 :         uss->estimating = false;
                                514               0 :         return false;
                                515                 :     }
                                516                 : 
                                517                 :     /*
                                518                 :      * Target minimum cardinality is 1 per ~2k of non-null inputs. 0.5 row
                                519                 :      * fudge factor allows us to abort earlier on genuinely pathological data
                                520                 :      * where we've had exactly one abbreviated value in the first 2k
                                521                 :      * (non-null) rows.
                                522                 :      */
                                523               0 :     if (abbr_card < uss->input_count / 2000.0 + 0.5)
                                524                 :     {
                                525                 : #ifdef TRACE_SORT
                                526               0 :         if (trace_sort)
                                527               0 :             elog(LOG,
                                528                 :                  "network_abbrev: aborting abbreviation at cardinality %f"
                                529                 :                  " below threshold %f after " INT64_FORMAT " values (%d rows)",
                                530                 :                  abbr_card, uss->input_count / 2000.0 + 0.5, uss->input_count,
                                531                 :                  memtupcount);
                                532                 : #endif
                                533               0 :         return true;
                                534                 :     }
                                535                 : 
                                536                 : #ifdef TRACE_SORT
                                537               0 :     if (trace_sort)
                                538               0 :         elog(LOG,
                                539                 :              "network_abbrev: cardinality %f after " INT64_FORMAT
                                540                 :              " values (%d rows)", abbr_card, uss->input_count, memtupcount);
                                541                 : #endif
                                542                 : 
                                543               0 :     return false;
                                544                 : }
                                545                 : 
                                546                 : /*
                                547                 :  * SortSupport conversion routine. Converts original inet/cidr representation
                                548                 :  * to abbreviated key representation that works with simple 3-way unsigned int
                                549                 :  * comparisons. The network_cmp_internal() rules for sorting inet/cidr datums
                                550                 :  * are followed by abbreviated comparisons by an encoding scheme that
                                551                 :  * conditions keys through careful use of padding.
                                552                 :  *
                                553                 :  * Some background: inet values have three major components (take for example
                                554                 :  * the address 1.2.3.4/24):
                                555                 :  *
                                556                 :  *     * A network, or netmasked bits (1.2.3.0).
                                557                 :  *     * A netmask size (/24).
                                558                 :  *     * A subnet, or bits outside of the netmask (0.0.0.4).
                                559                 :  *
                                560                 :  * cidr values are the same except that with only the first two components --
                                561                 :  * all their subnet bits *must* be zero (1.2.3.0/24).
                                562                 :  *
                                563                 :  * IPv4 and IPv6 are identical in this makeup, with the difference being that
                                564                 :  * IPv4 addresses have a maximum of 32 bits compared to IPv6's 64 bits, so in
                                565                 :  * IPv6 each part may be larger.
                                566                 :  *
                                567                 :  * inet/cidr types compare using these sorting rules. If inequality is detected
                                568                 :  * at any step, comparison is finished. If any rule is a tie, the algorithm
                                569                 :  * drops through to the next to break it:
                                570                 :  *
                                571                 :  *     1. IPv4 always appears before IPv6.
                                572                 :  *     2. Network bits are compared.
                                573                 :  *     3. Netmask size is compared.
                                574                 :  *     4. All bits are compared (having made it here, we know that both
                                575                 :  *        netmasked bits and netmask size are equal, so we're in effect only
                                576                 :  *        comparing subnet bits).
                                577                 :  *
                                578                 :  * When generating abbreviated keys for SortSupport, we pack as much as we can
                                579                 :  * into a datum while ensuring that when comparing those keys as integers,
                                580                 :  * these rules will be respected. Exact contents depend on IP family and datum
                                581                 :  * size.
                                582                 :  *
                                583                 :  * IPv4
                                584                 :  * ----
                                585                 :  *
                                586                 :  * 4 byte datums:
                                587                 :  *
                                588                 :  * Start with 1 bit for the IP family (IPv4 or IPv6; this bit is present in
                                589                 :  * every case below) followed by all but 1 of the netmasked bits.
                                590                 :  *
                                591                 :  * +----------+---------------------+
                                592                 :  * | 1 bit IP |   31 bits network   |     (1 bit network
                                593                 :  * |  family  |     (truncated)     |      omitted)
                                594                 :  * +----------+---------------------+
                                595                 :  *
                                596                 :  * 8 byte datums:
                                597                 :  *
                                598                 :  * We have space to store all netmasked bits, followed by the netmask size,
                                599                 :  * followed by 25 bits of the subnet (25 bits is usually more than enough in
                                600                 :  * practice). cidr datums always have all-zero subnet bits.
                                601                 :  *
                                602                 :  * +----------+-----------------------+--------------+--------------------+
                                603                 :  * | 1 bit IP |    32 bits network    |    6 bits    |   25 bits subnet   |
                                604                 :  * |  family  |        (full)         | network size |    (truncated)     |
                                605                 :  * +----------+-----------------------+--------------+--------------------+
                                606                 :  *
                                607                 :  * IPv6
                                608                 :  * ----
                                609                 :  *
                                610                 :  * 4 byte datums:
                                611                 :  *
                                612                 :  * +----------+---------------------+
                                613                 :  * | 1 bit IP |   31 bits network   |    (up to 97 bits
                                614                 :  * |  family  |     (truncated)     |   network omitted)
                                615                 :  * +----------+---------------------+
                                616                 :  *
                                617                 :  * 8 byte datums:
                                618                 :  *
                                619                 :  * +----------+---------------------------------+
                                620                 :  * | 1 bit IP |         63 bits network         |    (up to 65 bits
                                621                 :  * |  family  |           (truncated)           |   network omitted)
                                622                 :  * +----------+---------------------------------+
                                623                 :  */
                                624                 : static Datum
 1347 pg                        625 CBC         774 : network_abbrev_convert(Datum original, SortSupport ssup)
                                626                 : {
                                627             774 :     network_sortsupport_state *uss = ssup->ssup_extra;
                                628             774 :     inet       *authoritative = DatumGetInetPP(original);
                                629                 :     Datum       res,
                                630                 :                 ipaddr_datum,
                                631                 :                 subnet_bitmask,
                                632                 :                 network;
                                633                 :     int         subnet_size;
                                634                 : 
                                635             774 :     Assert(ip_family(authoritative) == PGSQL_AF_INET ||
                                636                 :            ip_family(authoritative) == PGSQL_AF_INET6);
                                637                 : 
                                638                 :     /*
                                639                 :      * Get an unsigned integer representation of the IP address by taking its
                                640                 :      * first 4 or 8 bytes. Always take all 4 bytes of an IPv4 address. Take
                                641                 :      * the first 8 bytes of an IPv6 address with an 8 byte datum and 4 bytes
                                642                 :      * otherwise.
                                643                 :      *
                                644                 :      * We're consuming an array of unsigned char, so byteswap on little endian
                                645                 :      * systems (an inet's ipaddr field stores the most significant byte
                                646                 :      * first).
                                647                 :      */
                                648             774 :     if (ip_family(authoritative) == PGSQL_AF_INET)
                                649                 :     {
                                650                 :         uint32      ipaddr_datum32;
                                651                 : 
                                652             585 :         memcpy(&ipaddr_datum32, ip_addr(authoritative), sizeof(uint32));
                                653                 : 
                                654                 :         /* Must byteswap on little-endian machines */
                                655                 : #ifndef WORDS_BIGENDIAN
                                656             585 :         ipaddr_datum = pg_bswap32(ipaddr_datum32);
                                657                 : #else
                                658                 :         ipaddr_datum = ipaddr_datum32;
                                659                 : #endif
                                660                 : 
                                661                 :         /* Initialize result without setting ipfamily bit */
                                662             585 :         res = (Datum) 0;
                                663                 :     }
                                664                 :     else
                                665                 :     {
                                666             189 :         memcpy(&ipaddr_datum, ip_addr(authoritative), sizeof(Datum));
                                667                 : 
                                668                 :         /* Must byteswap on little-endian machines */
                                669             189 :         ipaddr_datum = DatumBigEndianToNative(ipaddr_datum);
                                670                 : 
                                671                 :         /* Initialize result with ipfamily (most significant) bit set */
                                672             189 :         res = ((Datum) 1) << (SIZEOF_DATUM * BITS_PER_BYTE - 1);
                                673                 :     }
                                674                 : 
                                675                 :     /*
                                676                 :      * ipaddr_datum must be "split": high order bits go in "network" component
                                677                 :      * of abbreviated key (often with zeroed bits at the end due to masking),
                                678                 :      * while low order bits go in "subnet" component when there is space for
                                679                 :      * one. This is often accomplished by generating a temp datum subnet
                                680                 :      * bitmask, which we may reuse later when generating the subnet bits
                                681                 :      * themselves.  (Note that subnet bits are only used with IPv4 datums on
                                682                 :      * platforms where datum is 8 bytes.)
                                683                 :      *
                                684                 :      * The number of bits in subnet is used to generate a datum subnet
                                685                 :      * bitmask. For example, with a /24 IPv4 datum there are 8 subnet bits
                                686                 :      * (since 32 - 24 is 8), so the final subnet bitmask is B'1111 1111'. We
                                687                 :      * need explicit handling for cases where the ipaddr bits cannot all fit
                                688                 :      * in a datum, though (otherwise we'd incorrectly mask the network
                                689                 :      * component with IPv6 values).
                                690                 :      */
                                691             774 :     subnet_size = ip_maxbits(authoritative) - ip_bits(authoritative);
                                692             774 :     Assert(subnet_size >= 0);
                                693                 :     /* subnet size must work with prefix ipaddr cases */
                                694             774 :     subnet_size %= SIZEOF_DATUM * BITS_PER_BYTE;
                                695             774 :     if (ip_bits(authoritative) == 0)
                                696                 :     {
                                697                 :         /* Fit as many ipaddr bits as possible into subnet */
                                698              84 :         subnet_bitmask = ((Datum) 0) - 1;
                                699              84 :         network = 0;
                                700                 :     }
                                701             690 :     else if (ip_bits(authoritative) < SIZEOF_DATUM * BITS_PER_BYTE)
                                702                 :     {
                                703                 :         /* Split ipaddr bits between network and subnet */
                                704             585 :         subnet_bitmask = (((Datum) 1) << subnet_size) - 1;
                                705             585 :         network = ipaddr_datum & ~subnet_bitmask;
                                706                 :     }
                                707                 :     else
                                708                 :     {
                                709                 :         /* Fit as many ipaddr bits as possible into network */
                                710             105 :         subnet_bitmask = 0;
                                711             105 :         network = ipaddr_datum;
                                712                 :     }
                                713                 : 
                                714                 : #if SIZEOF_DATUM == 8
                                715             774 :     if (ip_family(authoritative) == PGSQL_AF_INET)
                                716                 :     {
                                717                 :         /*
                                718                 :          * IPv4 with 8 byte datums: keep all 32 netmasked bits, netmask size,
                                719                 :          * and most significant 25 subnet bits
                                720                 :          */
                                721             585 :         Datum       netmask_size = (Datum) ip_bits(authoritative);
                                722                 :         Datum       subnet;
                                723                 : 
                                724                 :         /*
                                725                 :          * Shift left 31 bits: 6 bits netmask size + 25 subnet bits.
                                726                 :          *
                                727                 :          * We don't make any distinction between network bits that are zero
                                728                 :          * due to masking and "true"/non-masked zero bits.  An abbreviated
                                729                 :          * comparison that is resolved by comparing a non-masked and non-zero
                                730                 :          * bit to a masked/zeroed bit is effectively resolved based on
                                731                 :          * ip_bits(), even though the comparison won't reach the netmask_size
                                732                 :          * bits.
                                733                 :          */
                                734             585 :         network <<= (ABBREV_BITS_INET4_NETMASK_SIZE +
                                735                 :                      ABBREV_BITS_INET4_SUBNET);
                                736                 : 
                                737                 :         /* Shift size to make room for subnet bits at the end */
                                738             585 :         netmask_size <<= ABBREV_BITS_INET4_SUBNET;
                                739                 : 
                                740                 :         /* Extract subnet bits without shifting them */
                                741             585 :         subnet = ipaddr_datum & subnet_bitmask;
                                742                 : 
                                743                 :         /*
                                744                 :          * If we have more than 25 subnet bits, we can't fit everything. Shift
                                745                 :          * subnet down to avoid clobbering bits that are only supposed to be
                                746                 :          * used for netmask_size.
                                747                 :          *
                                748                 :          * Discarding the least significant subnet bits like this is correct
                                749                 :          * because abbreviated comparisons that are resolved at the subnet
                                750                 :          * level must have had equal netmask_size/ip_bits() values in order to
                                751                 :          * get that far.
                                752                 :          */
                                753             585 :         if (subnet_size > ABBREV_BITS_INET4_SUBNET)
                                754              72 :             subnet >>= subnet_size - ABBREV_BITS_INET4_SUBNET;
                                755                 : 
                                756                 :         /*
                                757                 :          * Assemble the final abbreviated key without clobbering the ipfamily
                                758                 :          * bit that must remain a zero.
                                759                 :          */
                                760             585 :         res |= network | netmask_size | subnet;
                                761                 :     }
                                762                 :     else
                                763                 : #endif
                                764                 :     {
                                765                 :         /*
                                766                 :          * 4 byte datums, or IPv6 with 8 byte datums: Use as many of the
                                767                 :          * netmasked bits as will fit in final abbreviated key. Avoid
                                768                 :          * clobbering the ipfamily bit that was set earlier.
                                769                 :          */
                                770             189 :         res |= network >> 1;
                                771                 :     }
                                772                 : 
                                773             774 :     uss->input_count += 1;
                                774                 : 
                                775                 :     /* Hash abbreviated key */
                                776             774 :     if (uss->estimating)
                                777                 :     {
                                778                 :         uint32      tmp;
                                779                 : 
                                780                 : #if SIZEOF_DATUM == 8
                                781             774 :         tmp = (uint32) res ^ (uint32) ((uint64) res >> 32);
                                782                 : #else                           /* SIZEOF_DATUM != 8 */
                                783                 :         tmp = (uint32) res;
                                784                 : #endif
                                785                 : 
                                786             774 :         addHyperLogLog(&uss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
                                787                 :     }
                                788                 : 
                                789             774 :     return res;
                                790                 : }
                                791                 : 
                                792                 : /*
                                793                 :  *  Boolean ordering tests.
                                794                 :  */
                                795                 : Datum
 8284 tgl                       796          151433 : network_lt(PG_FUNCTION_ARGS)
                                797                 : {
 4136 heikki.linnakangas        798          151433 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                799          151433 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                800                 : 
 8284 tgl                       801          151433 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) < 0);
                                802                 : }
                                803                 : 
                                804                 : Datum
                                805            9430 : network_le(PG_FUNCTION_ARGS)
                                806                 : {
 4136 heikki.linnakangas        807            9430 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                808            9430 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                809                 : 
 8284 tgl                       810            9430 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) <= 0);
                                811                 : }
                                812                 : 
                                813                 : Datum
                                814           50970 : network_eq(PG_FUNCTION_ARGS)
                                815                 : {
 4136 heikki.linnakangas        816           50970 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                817           50970 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                818                 : 
 8284 tgl                       819           50970 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) == 0);
                                820                 : }
                                821                 : 
                                822                 : Datum
                                823            9586 : network_ge(PG_FUNCTION_ARGS)
                                824                 : {
 4136 heikki.linnakangas        825            9586 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                826            9586 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                827                 : 
 8284 tgl                       828            9586 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) >= 0);
                                829                 : }
                                830                 : 
                                831                 : Datum
                                832           11036 : network_gt(PG_FUNCTION_ARGS)
                                833                 : {
 4136 heikki.linnakangas        834           11036 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                835           11036 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                836                 : 
 8284 tgl                       837           11036 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) > 0);
                                838                 : }
                                839                 : 
                                840                 : Datum
                                841              51 : network_ne(PG_FUNCTION_ARGS)
                                842                 : {
 4136 heikki.linnakangas        843              51 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                844              51 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                845                 : 
 8284 tgl                       846              51 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
                                847                 : }
                                848                 : 
                                849                 : /*
                                850                 :  * MIN/MAX support functions.
                                851                 :  */
                                852                 : Datum
 3146                           853              96 : network_smaller(PG_FUNCTION_ARGS)
                                854                 : {
                                855              96 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                856              96 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                857                 : 
                                858              96 :     if (network_cmp_internal(a1, a2) < 0)
                                859              57 :         PG_RETURN_INET_P(a1);
                                860                 :     else
                                861              39 :         PG_RETURN_INET_P(a2);
                                862                 : }
                                863                 : 
                                864                 : Datum
                                865              96 : network_larger(PG_FUNCTION_ARGS)
                                866                 : {
                                867              96 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                868              96 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                869                 : 
                                870              96 :     if (network_cmp_internal(a1, a2) > 0)
                                871              78 :         PG_RETURN_INET_P(a1);
                                872                 :     else
                                873              18 :         PG_RETURN_INET_P(a2);
                                874                 : }
                                875                 : 
                                876                 : /*
                                877                 :  * Support function for hash indexes on inet/cidr.
                                878                 :  */
                                879                 : Datum
 6874                           880            3036 : hashinet(PG_FUNCTION_ARGS)
                                881                 : {
 4136 heikki.linnakangas        882            3036 :     inet       *addr = PG_GETARG_INET_PP(0);
 6874 tgl                       883            3036 :     int         addrsize = ip_addrsize(addr);
                                884                 : 
                                885                 :     /* XXX this assumes there are no pad bytes in the data structure */
 5847                           886            3036 :     return hash_any((unsigned char *) VARDATA_ANY(addr), addrsize + 2);
                                887                 : }
                                888                 : 
                                889                 : Datum
 2047 rhaas                     890              30 : hashinetextended(PG_FUNCTION_ARGS)
                                891                 : {
                                892              30 :     inet       *addr = PG_GETARG_INET_PP(0);
                                893              30 :     int         addrsize = ip_addrsize(addr);
                                894                 : 
                                895              30 :     return hash_any_extended((unsigned char *) VARDATA_ANY(addr), addrsize + 2,
                                896              30 :                              PG_GETARG_INT64(1));
                                897                 : }
                                898                 : 
                                899                 : /*
                                900                 :  *  Boolean network-inclusion tests.
                                901                 :  */
                                902                 : Datum
 8284 tgl                       903            3066 : network_sub(PG_FUNCTION_ARGS)
                                904                 : {
 4136 heikki.linnakangas        905            3066 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                906            3066 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                907                 : 
 7229 bruce                     908            3066 :     if (ip_family(a1) == ip_family(a2))
                                909                 :     {
 3382 tgl                       910            2466 :         PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2) &&
                                911                 :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
                                912                 :     }
                                913                 : 
 7229 bruce                     914             600 :     PG_RETURN_BOOL(false);
                                915                 : }
                                916                 : 
                                917                 : Datum
 8284 tgl                       918            4953 : network_subeq(PG_FUNCTION_ARGS)
                                919                 : {
 4136 heikki.linnakangas        920            4953 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                921            4953 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                922                 : 
 7229 bruce                     923            4953 :     if (ip_family(a1) == ip_family(a2))
                                924                 :     {
 3382 tgl                       925            3069 :         PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2) &&
                                926                 :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
                                927                 :     }
                                928                 : 
 7229 bruce                     929            1884 :     PG_RETURN_BOOL(false);
                                930                 : }
                                931                 : 
                                932                 : Datum
 8284 tgl                       933            3090 : network_sup(PG_FUNCTION_ARGS)
                                934                 : {
 4136 heikki.linnakangas        935            3090 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                936            3090 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                937                 : 
 7229 bruce                     938            3090 :     if (ip_family(a1) == ip_family(a2))
                                939                 :     {
 3382 tgl                       940            2490 :         PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2) &&
                                941                 :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
                                942                 :     }
                                943                 : 
 7229 bruce                     944             600 :     PG_RETURN_BOOL(false);
                                945                 : }
                                946                 : 
                                947                 : Datum
 8284 tgl                       948            9294 : network_supeq(PG_FUNCTION_ARGS)
                                949                 : {
 4136 heikki.linnakangas        950            9294 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                951            9294 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                952                 : 
 7229 bruce                     953            9294 :     if (ip_family(a1) == ip_family(a2))
                                954                 :     {
 3382 tgl                       955            5124 :         PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2) &&
                                956                 :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
                                957                 :     }
                                958                 : 
 7229 bruce                     959            4170 :     PG_RETURN_BOOL(false);
                                960                 : }
                                961                 : 
                                962                 : Datum
 3288 tgl                       963           10515 : network_overlap(PG_FUNCTION_ARGS)
                                964                 : {
                                965           10515 :     inet       *a1 = PG_GETARG_INET_PP(0);
                                966           10515 :     inet       *a2 = PG_GETARG_INET_PP(1);
                                967                 : 
                                968           10515 :     if (ip_family(a1) == ip_family(a2))
                                969                 :     {
                                970            6399 :         PG_RETURN_BOOL(bitncmp(ip_addr(a1), ip_addr(a2),
                                971                 :                                Min(ip_bits(a1), ip_bits(a2))) == 0);
                                972                 :     }
                                973                 : 
                                974            4116 :     PG_RETURN_BOOL(false);
                                975                 : }
                                976                 : 
                                977                 : /*
                                978                 :  * Planner support function for network subset/superset operators
                                979                 :  */
                                980                 : Datum
 1518                           981             744 : network_subset_support(PG_FUNCTION_ARGS)
                                982                 : {
                                983             744 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
                                984             744 :     Node       *ret = NULL;
                                985                 : 
                                986             744 :     if (IsA(rawreq, SupportRequestIndexCondition))
                                987                 :     {
                                988                 :         /* Try to convert operator/function call to index conditions */
                                989              24 :         SupportRequestIndexCondition *req = (SupportRequestIndexCondition *) rawreq;
                                990                 : 
                                991              24 :         if (is_opclause(req->node))
                                992                 :         {
                                993              24 :             OpExpr     *clause = (OpExpr *) req->node;
                                994                 : 
                                995              24 :             Assert(list_length(clause->args) == 2);
                                996                 :             ret = (Node *)
                                997              24 :                 match_network_function((Node *) linitial(clause->args),
                                998              24 :                                        (Node *) lsecond(clause->args),
                                999                 :                                        req->indexarg,
                               1000                 :                                        req->funcid,
                               1001                 :                                        req->opfamily);
                               1002                 :         }
 1518 tgl                      1003 UBC           0 :         else if (is_funcclause(req->node))   /* be paranoid */
                               1004                 :         {
                               1005               0 :             FuncExpr   *clause = (FuncExpr *) req->node;
                               1006                 : 
                               1007               0 :             Assert(list_length(clause->args) == 2);
                               1008                 :             ret = (Node *)
                               1009               0 :                 match_network_function((Node *) linitial(clause->args),
                               1010               0 :                                        (Node *) lsecond(clause->args),
                               1011                 :                                        req->indexarg,
                               1012                 :                                        req->funcid,
                               1013                 :                                        req->opfamily);
                               1014                 :         }
                               1015                 :     }
                               1016                 : 
 1518 tgl                      1017 CBC         744 :     PG_RETURN_POINTER(ret);
                               1018                 : }
                               1019                 : 
                               1020                 : /*
                               1021                 :  * match_network_function
                               1022                 :  *    Try to generate an indexqual for a network subset/superset function.
                               1023                 :  *
                               1024                 :  * This layer is just concerned with identifying the function and swapping
                               1025                 :  * the arguments if necessary.
                               1026                 :  */
                               1027                 : static List *
                               1028              24 : match_network_function(Node *leftop,
                               1029                 :                        Node *rightop,
                               1030                 :                        int indexarg,
                               1031                 :                        Oid funcid,
                               1032                 :                        Oid opfamily)
                               1033                 : {
                               1034              24 :     switch (funcid)
                               1035                 :     {
                               1036               6 :         case F_NETWORK_SUB:
                               1037                 :             /* indexkey must be on the left */
                               1038               6 :             if (indexarg != 0)
 1518 tgl                      1039 UBC           0 :                 return NIL;
 1518 tgl                      1040 CBC           6 :             return match_network_subset(leftop, rightop, false, opfamily);
                               1041                 : 
                               1042               6 :         case F_NETWORK_SUBEQ:
                               1043                 :             /* indexkey must be on the left */
                               1044               6 :             if (indexarg != 0)
 1518 tgl                      1045 UBC           0 :                 return NIL;
 1518 tgl                      1046 CBC           6 :             return match_network_subset(leftop, rightop, true, opfamily);
                               1047                 : 
                               1048               6 :         case F_NETWORK_SUP:
                               1049                 :             /* indexkey must be on the right */
                               1050               6 :             if (indexarg != 1)
 1518 tgl                      1051 UBC           0 :                 return NIL;
 1518 tgl                      1052 CBC           6 :             return match_network_subset(rightop, leftop, false, opfamily);
                               1053                 : 
                               1054               6 :         case F_NETWORK_SUPEQ:
                               1055                 :             /* indexkey must be on the right */
                               1056               6 :             if (indexarg != 1)
 1518 tgl                      1057 UBC           0 :                 return NIL;
 1518 tgl                      1058 CBC           6 :             return match_network_subset(rightop, leftop, true, opfamily);
                               1059                 : 
 1518 tgl                      1060 UBC           0 :         default:
                               1061                 : 
                               1062                 :             /*
                               1063                 :              * We'd only get here if somebody attached this support function
                               1064                 :              * to an unexpected function.  Maybe we should complain, but for
                               1065                 :              * now, do nothing.
                               1066                 :              */
                               1067               0 :             return NIL;
                               1068                 :     }
                               1069                 : }
                               1070                 : 
                               1071                 : /*
                               1072                 :  * match_network_subset
                               1073                 :  *    Try to generate an indexqual for a network subset function.
                               1074                 :  */
                               1075                 : static List *
 1518 tgl                      1076 CBC          24 : match_network_subset(Node *leftop,
                               1077                 :                      Node *rightop,
                               1078                 :                      bool is_eq,
                               1079                 :                      Oid opfamily)
                               1080                 : {
                               1081                 :     List       *result;
                               1082                 :     Datum       rightopval;
                               1083              24 :     Oid         datatype = INETOID;
                               1084                 :     Oid         opr1oid;
                               1085                 :     Oid         opr2oid;
                               1086                 :     Datum       opr1right;
                               1087                 :     Datum       opr2right;
                               1088                 :     Expr       *expr;
                               1089                 : 
                               1090                 :     /*
                               1091                 :      * Can't do anything with a non-constant or NULL comparison value.
                               1092                 :      *
                               1093                 :      * Note that since we restrict ourselves to cases with a hard constant on
                               1094                 :      * the RHS, it's a-fortiori a pseudoconstant, and we don't need to worry
                               1095                 :      * about verifying that.
                               1096                 :      */
                               1097              24 :     if (!IsA(rightop, Const) ||
                               1098              24 :         ((Const *) rightop)->constisnull)
 1518 tgl                      1099 UBC           0 :         return NIL;
 1518 tgl                      1100 CBC          24 :     rightopval = ((Const *) rightop)->constvalue;
                               1101                 : 
                               1102                 :     /*
                               1103                 :      * Must check that index's opfamily supports the operators we will want to
                               1104                 :      * apply.
                               1105                 :      *
                               1106                 :      * We insist on the opfamily being the specific one we expect, else we'd
                               1107                 :      * do the wrong thing if someone were to make a reverse-sort opfamily with
                               1108                 :      * the same operators.
                               1109                 :      */
                               1110              24 :     if (opfamily != NETWORK_BTREE_FAM_OID)
 1518 tgl                      1111 UBC           0 :         return NIL;
                               1112                 : 
                               1113                 :     /*
                               1114                 :      * create clause "key >= network_scan_first( rightopval )", or ">" if the
                               1115                 :      * operator disallows equality.
                               1116                 :      *
                               1117                 :      * Note: seeing that this function supports only fixed values for opfamily
                               1118                 :      * and datatype, we could just hard-wire the operator OIDs instead of
                               1119                 :      * looking them up.  But for now it seems better to be general.
                               1120                 :      */
 1518 tgl                      1121 CBC          24 :     if (is_eq)
                               1122                 :     {
                               1123              12 :         opr1oid = get_opfamily_member(opfamily, datatype, datatype,
                               1124                 :                                       BTGreaterEqualStrategyNumber);
                               1125              12 :         if (opr1oid == InvalidOid)
 1518 tgl                      1126 UBC           0 :             elog(ERROR, "no >= operator for opfamily %u", opfamily);
                               1127                 :     }
                               1128                 :     else
                               1129                 :     {
 1518 tgl                      1130 CBC          12 :         opr1oid = get_opfamily_member(opfamily, datatype, datatype,
                               1131                 :                                       BTGreaterStrategyNumber);
                               1132              12 :         if (opr1oid == InvalidOid)
 1518 tgl                      1133 UBC           0 :             elog(ERROR, "no > operator for opfamily %u", opfamily);
                               1134                 :     }
                               1135                 : 
 1518 tgl                      1136 CBC          24 :     opr1right = network_scan_first(rightopval);
                               1137                 : 
                               1138              24 :     expr = make_opclause(opr1oid, BOOLOID, false,
                               1139                 :                          (Expr *) leftop,
                               1140              24 :                          (Expr *) makeConst(datatype, -1,
                               1141                 :                                             InvalidOid, /* not collatable */
                               1142                 :                                             -1, opr1right,
                               1143                 :                                             false, false),
                               1144                 :                          InvalidOid, InvalidOid);
                               1145              24 :     result = list_make1(expr);
                               1146                 : 
                               1147                 :     /* create clause "key <= network_scan_last( rightopval )" */
                               1148                 : 
                               1149              24 :     opr2oid = get_opfamily_member(opfamily, datatype, datatype,
                               1150                 :                                   BTLessEqualStrategyNumber);
                               1151              24 :     if (opr2oid == InvalidOid)
 1518 tgl                      1152 UBC           0 :         elog(ERROR, "no <= operator for opfamily %u", opfamily);
                               1153                 : 
 1518 tgl                      1154 CBC          24 :     opr2right = network_scan_last(rightopval);
                               1155                 : 
                               1156              24 :     expr = make_opclause(opr2oid, BOOLOID, false,
                               1157                 :                          (Expr *) leftop,
                               1158              24 :                          (Expr *) makeConst(datatype, -1,
                               1159                 :                                             InvalidOid, /* not collatable */
                               1160                 :                                             -1, opr2right,
                               1161                 :                                             false, false),
                               1162                 :                          InvalidOid, InvalidOid);
                               1163              24 :     result = lappend(result, expr);
                               1164                 : 
                               1165              24 :     return result;
                               1166                 : }
                               1167                 : 
                               1168                 : 
                               1169                 : /*
                               1170                 :  * Extract data from a network datatype.
                               1171                 :  */
                               1172                 : Datum
 8312                          1173              51 : network_host(PG_FUNCTION_ARGS)
                               1174                 : {
 4136 heikki.linnakangas       1175              51 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1176                 :     char       *ptr;
                               1177                 :     char        tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
                               1178                 : 
                               1179                 :     /* force display of max bits, regardless of masklen... */
 1330 tgl                      1180              51 :     if (pg_inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
                               1181                 :                          tmp, sizeof(tmp)) == NULL)
 7196 tgl                      1182 UBC           0 :         ereport(ERROR,
                               1183                 :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                               1184                 :                  errmsg("could not format inet value: %m")));
                               1185                 : 
                               1186                 :     /* Suppress /n if present (shouldn't happen now) */
 8935 bruce                    1187 CBC          51 :     if ((ptr = strchr(tmp, '/')) != NULL)
 8312 tgl                      1188 UBC           0 :         *ptr = '\0';
                               1189                 : 
 5493 tgl                      1190 CBC          51 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
                               1191                 : }
                               1192                 : 
                               1193                 : /*
                               1194                 :  * network_show implements the inet and cidr casts to text.  This is not
                               1195                 :  * quite the same behavior as network_out, hence we can't drop it in favor
                               1196                 :  * of CoerceViaIO.
                               1197                 :  */
                               1198                 : Datum
 8185                          1199             106 : network_show(PG_FUNCTION_ARGS)
                               1200                 : {
 4136 heikki.linnakangas       1201             106 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1202                 :     int         len;
                               1203                 :     char        tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
                               1204                 : 
 1330 tgl                      1205             106 :     if (pg_inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
                               1206                 :                          tmp, sizeof(tmp)) == NULL)
 7196 tgl                      1207 UBC           0 :         ereport(ERROR,
                               1208                 :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                               1209                 :                  errmsg("could not format inet value: %m")));
                               1210                 : 
                               1211                 :     /* Add /n if not present (which it won't be) */
 7229 bruce                    1212 CBC         106 :     if (strchr(tmp, '/') == NULL)
                               1213                 :     {
                               1214             106 :         len = strlen(tmp);
                               1215             106 :         snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
                               1216                 :     }
                               1217                 : 
 5493 tgl                      1218             106 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
                               1219                 : }
                               1220                 : 
                               1221                 : Datum
 6282 tgl                      1222 UBC           0 : inet_abbrev(PG_FUNCTION_ARGS)
                               1223                 : {
 4136 heikki.linnakangas       1224               0 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1225                 :     char       *dst;
                               1226                 :     char        tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
                               1227                 : 
 1330 tgl                      1228               0 :     dst = pg_inet_net_ntop(ip_family(ip), ip_addr(ip),
                               1229               0 :                            ip_bits(ip), tmp, sizeof(tmp));
                               1230                 : 
 7229 bruce                    1231               0 :     if (dst == NULL)
 7196 tgl                      1232               0 :         ereport(ERROR,
                               1233                 :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                               1234                 :                  errmsg("could not format inet value: %m")));
                               1235                 : 
 5493                          1236               0 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
                               1237                 : }
                               1238                 : 
                               1239                 : Datum
 6282 tgl                      1240 CBC          51 : cidr_abbrev(PG_FUNCTION_ARGS)
                               1241                 : {
 4136 heikki.linnakangas       1242              51 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1243                 :     char       *dst;
                               1244                 :     char        tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
                               1245                 : 
 1330 tgl                      1246              51 :     dst = pg_inet_cidr_ntop(ip_family(ip), ip_addr(ip),
                               1247              51 :                             ip_bits(ip), tmp, sizeof(tmp));
                               1248                 : 
 6282                          1249              51 :     if (dst == NULL)
 6282 tgl                      1250 UBC           0 :         ereport(ERROR,
                               1251                 :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                               1252                 :                  errmsg("could not format cidr value: %m")));
                               1253                 : 
 5493 tgl                      1254 CBC          51 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
                               1255                 : }
                               1256                 : 
                               1257                 : Datum
 8284                          1258             177 : network_masklen(PG_FUNCTION_ARGS)
                               1259                 : {
 4136 heikki.linnakangas       1260             177 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1261                 : 
 8284 tgl                      1262             177 :     PG_RETURN_INT32(ip_bits(ip));
                               1263                 : }
                               1264                 : 
                               1265                 : Datum
 7229 bruce                    1266              51 : network_family(PG_FUNCTION_ARGS)
                               1267                 : {
 4136 heikki.linnakangas       1268              51 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1269                 : 
 7188 bruce                    1270              51 :     switch (ip_family(ip))
                               1271                 :     {
                               1272              42 :         case PGSQL_AF_INET:
                               1273              42 :             PG_RETURN_INT32(4);
                               1274                 :             break;
                               1275               9 :         case PGSQL_AF_INET6:
                               1276               9 :             PG_RETURN_INT32(6);
                               1277                 :             break;
 7188 bruce                    1278 UBC           0 :         default:
                               1279               0 :             PG_RETURN_INT32(0);
                               1280                 :             break;
                               1281                 :     }
                               1282                 : }
                               1283                 : 
                               1284                 : Datum
 8312 tgl                      1285 CBC         126 : network_broadcast(PG_FUNCTION_ARGS)
                               1286                 : {
 4136 heikki.linnakangas       1287             126 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1288                 :     inet       *dst;
                               1289                 :     int         byte;
                               1290                 :     int         bits;
                               1291                 :     int         maxbytes;
                               1292                 :     unsigned char mask;
                               1293                 :     unsigned char *a,
                               1294                 :                *b;
                               1295                 : 
                               1296                 :     /* make sure any unused bits are zeroed */
 5847 tgl                      1297             126 :     dst = (inet *) palloc0(sizeof(inet));
                               1298                 : 
 2420                          1299             126 :     maxbytes = ip_addrsize(ip);
 7229 bruce                    1300             126 :     bits = ip_bits(ip);
                               1301             126 :     a = ip_addr(ip);
                               1302             126 :     b = ip_addr(dst);
                               1303                 : 
 4382                          1304             846 :     for (byte = 0; byte < maxbytes; byte++)
                               1305                 :     {
 7188                          1306             720 :         if (bits >= 8)
                               1307                 :         {
 7229                          1308             495 :             mask = 0x00;
                               1309             495 :             bits -= 8;
                               1310                 :         }
 7188                          1311             225 :         else if (bits == 0)
 7229                          1312             213 :             mask = 0xff;
                               1313                 :         else
                               1314                 :         {
                               1315              12 :             mask = 0xff >> bits;
                               1316              12 :             bits = 0;
                               1317                 :         }
                               1318                 : 
 4382                          1319             720 :         b[byte] = a[byte] | mask;
                               1320                 :     }
                               1321                 : 
 8185 tgl                      1322             126 :     ip_family(dst) = ip_family(ip);
                               1323             126 :     ip_bits(dst) = ip_bits(ip);
 5847                          1324             126 :     SET_INET_VARSIZE(dst);
                               1325                 : 
 8185                          1326             126 :     PG_RETURN_INET_P(dst);
                               1327                 : }
                               1328                 : 
                               1329                 : Datum
 8312                          1330             126 : network_network(PG_FUNCTION_ARGS)
                               1331                 : {
 4136 heikki.linnakangas       1332             126 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1333                 :     inet       *dst;
                               1334                 :     int         byte;
                               1335                 :     int         bits;
                               1336                 :     unsigned char mask;
                               1337                 :     unsigned char *a,
                               1338                 :                *b;
                               1339                 : 
                               1340                 :     /* make sure any unused bits are zeroed */
 5847 tgl                      1341             126 :     dst = (inet *) palloc0(sizeof(inet));
                               1342                 : 
 7229 bruce                    1343             126 :     bits = ip_bits(ip);
                               1344             126 :     a = ip_addr(ip);
                               1345             126 :     b = ip_addr(dst);
                               1346                 : 
                               1347             126 :     byte = 0;
                               1348                 : 
 7188                          1349             633 :     while (bits)
                               1350                 :     {
                               1351             507 :         if (bits >= 8)
                               1352                 :         {
 7229                          1353             495 :             mask = 0xff;
                               1354             495 :             bits -= 8;
                               1355                 :         }
                               1356                 :         else
                               1357                 :         {
                               1358              12 :             mask = 0xff << (8 - bits);
                               1359              12 :             bits = 0;
                               1360                 :         }
                               1361                 : 
 4382                          1362             507 :         b[byte] = a[byte] & mask;
                               1363             507 :         byte++;
                               1364                 :     }
                               1365                 : 
 8185 tgl                      1366             126 :     ip_family(dst) = ip_family(ip);
                               1367             126 :     ip_bits(dst) = ip_bits(ip);
 5847                          1368             126 :     SET_INET_VARSIZE(dst);
                               1369                 : 
 8185                          1370             126 :     PG_RETURN_INET_P(dst);
                               1371                 : }
                               1372                 : 
                               1373                 : Datum
 8312 tgl                      1374 UBC           0 : network_netmask(PG_FUNCTION_ARGS)
                               1375                 : {
 4136 heikki.linnakangas       1376               0 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1377                 :     inet       *dst;
                               1378                 :     int         byte;
                               1379                 :     int         bits;
                               1380                 :     unsigned char mask;
                               1381                 :     unsigned char *b;
                               1382                 : 
                               1383                 :     /* make sure any unused bits are zeroed */
 5847 tgl                      1384               0 :     dst = (inet *) palloc0(sizeof(inet));
                               1385                 : 
 7229 bruce                    1386               0 :     bits = ip_bits(ip);
                               1387               0 :     b = ip_addr(dst);
                               1388                 : 
                               1389               0 :     byte = 0;
                               1390                 : 
 7188                          1391               0 :     while (bits)
                               1392                 :     {
                               1393               0 :         if (bits >= 8)
                               1394                 :         {
 7229                          1395               0 :             mask = 0xff;
                               1396               0 :             bits -= 8;
                               1397                 :         }
                               1398                 :         else
                               1399                 :         {
                               1400               0 :             mask = 0xff << (8 - bits);
                               1401               0 :             bits = 0;
                               1402                 :         }
                               1403                 : 
                               1404               0 :         b[byte] = mask;
 4382                          1405               0 :         byte++;
                               1406                 :     }
                               1407                 : 
 8185 tgl                      1408               0 :     ip_family(dst) = ip_family(ip);
 7069                          1409               0 :     ip_bits(dst) = ip_maxbits(ip);
 5847                          1410               0 :     SET_INET_VARSIZE(dst);
                               1411                 : 
 8185                          1412               0 :     PG_RETURN_INET_P(dst);
                               1413                 : }
                               1414                 : 
                               1415                 : Datum
 7324 bruce                    1416               0 : network_hostmask(PG_FUNCTION_ARGS)
                               1417                 : {
 4136 heikki.linnakangas       1418               0 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1419                 :     inet       *dst;
                               1420                 :     int         byte;
                               1421                 :     int         bits;
                               1422                 :     int         maxbytes;
                               1423                 :     unsigned char mask;
                               1424                 :     unsigned char *b;
                               1425                 : 
                               1426                 :     /* make sure any unused bits are zeroed */
 5847 tgl                      1427               0 :     dst = (inet *) palloc0(sizeof(inet));
                               1428                 : 
 2420                          1429               0 :     maxbytes = ip_addrsize(ip);
 7229 bruce                    1430               0 :     bits = ip_maxbits(ip) - ip_bits(ip);
                               1431               0 :     b = ip_addr(dst);
                               1432                 : 
                               1433               0 :     byte = maxbytes - 1;
                               1434                 : 
 7188                          1435               0 :     while (bits)
                               1436                 :     {
                               1437               0 :         if (bits >= 8)
                               1438                 :         {
 7229                          1439               0 :             mask = 0xff;
                               1440               0 :             bits -= 8;
                               1441                 :         }
                               1442                 :         else
                               1443                 :         {
                               1444               0 :             mask = 0xff >> (8 - bits);
                               1445               0 :             bits = 0;
                               1446                 :         }
                               1447                 : 
                               1448               0 :         b[byte] = mask;
 4382                          1449               0 :         byte--;
                               1450                 :     }
                               1451                 : 
 7324                          1452               0 :     ip_family(dst) = ip_family(ip);
 7069 tgl                      1453               0 :     ip_bits(dst) = ip_maxbits(ip);
 5847                          1454               0 :     SET_INET_VARSIZE(dst);
                               1455                 : 
 7324 bruce                    1456               0 :     PG_RETURN_INET_P(dst);
                               1457                 : }
                               1458                 : 
                               1459                 : /*
                               1460                 :  * Returns true if the addresses are from the same family, or false.  Used to
                               1461                 :  * check that we can create a network which contains both of the networks.
                               1462                 :  */
                               1463                 : Datum
 2896 alvherre                 1464 CBC         120 : inet_same_family(PG_FUNCTION_ARGS)
                               1465                 : {
                               1466             120 :     inet       *a1 = PG_GETARG_INET_PP(0);
                               1467             120 :     inet       *a2 = PG_GETARG_INET_PP(1);
                               1468                 : 
                               1469             120 :     PG_RETURN_BOOL(ip_family(a1) == ip_family(a2));
                               1470                 : }
                               1471                 : 
                               1472                 : /*
                               1473                 :  * Returns the smallest CIDR which contains both of the inputs.
                               1474                 :  */
                               1475                 : Datum
                               1476             117 : inet_merge(PG_FUNCTION_ARGS)
                               1477                 : {
                               1478             117 :     inet       *a1 = PG_GETARG_INET_PP(0),
 2420 tgl                      1479             117 :                *a2 = PG_GETARG_INET_PP(1);
                               1480                 :     int         commonbits;
                               1481                 : 
 2896 alvherre                 1482             117 :     if (ip_family(a1) != ip_family(a2))
                               1483               3 :         ereport(ERROR,
                               1484                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1485                 :                  errmsg("cannot merge addresses from different families")));
                               1486                 : 
                               1487             114 :     commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
                               1488             114 :                             Min(ip_bits(a1), ip_bits(a2)));
                               1489                 : 
 2420 tgl                      1490             114 :     PG_RETURN_INET_P(cidr_set_masklen_internal(a1, commonbits));
                               1491                 : }
                               1492                 : 
                               1493                 : /*
                               1494                 :  * Convert a value of a network datatype to an approximate scalar value.
                               1495                 :  * This is used for estimating selectivities of inequality operators
                               1496                 :  * involving network types.
                               1497                 :  *
                               1498                 :  * On failure (e.g., unsupported typid), set *failure to true;
                               1499                 :  * otherwise, that variable is not changed.
                               1500                 :  */
                               1501                 : double
 1863                          1502            5440 : convert_network_to_scalar(Datum value, Oid typid, bool *failure)
                               1503                 : {
 7974                          1504            5440 :     switch (typid)
                               1505                 :     {
                               1506            5440 :         case INETOID:
                               1507                 :         case CIDROID:
                               1508                 :             {
 4170 heikki.linnakangas       1509            5440 :                 inet       *ip = DatumGetInetPP(value);
                               1510                 :                 int         len;
                               1511                 :                 double      res;
                               1512                 :                 int         i;
                               1513                 : 
                               1514                 :                 /*
                               1515                 :                  * Note that we don't use the full address for IPv6.
                               1516                 :                  */
 7229 bruce                    1517            5440 :                 if (ip_family(ip) == PGSQL_AF_INET)
                               1518            5440 :                     len = 4;
                               1519                 :                 else
 7229 bruce                    1520 UBC           0 :                     len = 5;
                               1521                 : 
 7229 bruce                    1522 CBC        5440 :                 res = ip_family(ip);
 7188                          1523           27200 :                 for (i = 0; i < len; i++)
                               1524                 :                 {
 7229                          1525           21760 :                     res *= 256;
                               1526           21760 :                     res += ip_addr(ip)[i];
                               1527                 :                 }
                               1528            5440 :                 return res;
                               1529                 :             }
 7974 tgl                      1530 UBC           0 :         case MACADDROID:
                               1531                 :             {
 7836 bruce                    1532               0 :                 macaddr    *mac = DatumGetMacaddrP(value);
                               1533                 :                 double      res;
                               1534                 : 
                               1535               0 :                 res = (mac->a << 16) | (mac->b << 8) | (mac->c);
                               1536               0 :                 res *= 256 * 256 * 256;
                               1537               0 :                 res += (mac->d << 16) | (mac->e << 8) | (mac->f);
                               1538               0 :                 return res;
                               1539                 :             }
 2216 sfrost                   1540               0 :         case MACADDR8OID:
                               1541                 :             {
                               1542               0 :                 macaddr8   *mac = DatumGetMacaddr8P(value);
                               1543                 :                 double      res;
                               1544                 : 
                               1545               0 :                 res = (mac->a << 24) | (mac->b << 16) | (mac->c << 8) | (mac->d);
                               1546               0 :                 res *= ((double) 256) * 256 * 256 * 256;
                               1547               0 :                 res += (mac->e << 24) | (mac->f << 16) | (mac->g << 8) | (mac->h);
                               1548               0 :                 return res;
                               1549                 :             }
                               1550                 :     }
                               1551                 : 
 1863 tgl                      1552               0 :     *failure = true;
 7974                          1553               0 :     return 0;
                               1554                 : }
                               1555                 : 
                               1556                 : /*
                               1557                 :  * int
                               1558                 :  * bitncmp(l, r, n)
                               1559                 :  *      compare bit masks l and r, for n bits.
                               1560                 :  * return:
                               1561                 :  *      <0, >0, or 0 in the libc tradition.
                               1562                 :  * note:
                               1563                 :  *      network byte order assumed.  this means 192.5.5.240/28 has
                               1564                 :  *      0x11110000 in its fourth octet.
                               1565                 :  * author:
                               1566                 :  *      Paul Vixie (ISC), June 1996
                               1567                 :  */
                               1568                 : int
 3288 tgl                      1569 CBC      193223 : bitncmp(const unsigned char *l, const unsigned char *r, int n)
                               1570                 : {
                               1571                 :     unsigned int lb,
                               1572                 :                 rb;
                               1573                 :     int         x,
                               1574                 :                 b;
                               1575                 : 
 7229 bruce                    1576          193223 :     b = n / 8;
                               1577          193223 :     x = memcmp(l, r, b);
 4931 heikki.linnakangas       1578          193223 :     if (x || (n % 8) == 0)
 6297 neilc                    1579          193102 :         return x;
                               1580                 : 
 3288 tgl                      1581             121 :     lb = l[b];
                               1582             121 :     rb = r[b];
 7188 bruce                    1583             215 :     for (b = n % 8; b > 0; b--)
                               1584                 :     {
 6314                          1585             148 :         if (IS_HIGHBIT_SET(lb) != IS_HIGHBIT_SET(rb))
                               1586                 :         {
                               1587              54 :             if (IS_HIGHBIT_SET(lb))
                               1588              30 :                 return 1;
                               1589              24 :             return -1;
                               1590                 :         }
 7229                          1591              94 :         lb <<= 1;
                               1592              94 :         rb <<= 1;
                               1593                 :     }
 6314                          1594              67 :     return 0;
                               1595                 : }
                               1596                 : 
                               1597                 : /*
                               1598                 :  * bitncommon: compare bit masks l and r, for up to n bits.
                               1599                 :  *
                               1600                 :  * Returns the number of leading bits that match (0 to n).
                               1601                 :  */
                               1602                 : int
 3288 tgl                      1603            1660 : bitncommon(const unsigned char *l, const unsigned char *r, int n)
                               1604                 : {
                               1605                 :     int         byte,
                               1606                 :                 nbits;
                               1607                 : 
                               1608                 :     /* number of bits to examine in last byte */
                               1609            1660 :     nbits = n % 8;
                               1610                 : 
                               1611                 :     /* check whole bytes */
                               1612            2165 :     for (byte = 0; byte < n / 8; byte++)
                               1613                 :     {
                               1614             533 :         if (l[byte] != r[byte])
                               1615                 :         {
                               1616                 :             /* at least one bit in the last byte is not common */
                               1617              28 :             nbits = 7;
                               1618              28 :             break;
                               1619                 :         }
                               1620                 :     }
                               1621                 : 
                               1622                 :     /* check bits in last partial byte */
                               1623            1660 :     if (nbits != 0)
                               1624                 :     {
                               1625                 :         /* calculate diff of first non-matching bytes */
                               1626            1282 :         unsigned int diff = l[byte] ^ r[byte];
                               1627                 : 
                               1628                 :         /* compare the bits from the most to the least */
                               1629            1512 :         while ((diff >> (8 - nbits)) != 0)
                               1630             230 :             nbits--;
                               1631                 :     }
                               1632                 : 
                               1633            1660 :     return (8 * byte) + nbits;
                               1634                 : }
                               1635                 : 
                               1636                 : 
                               1637                 : /*
                               1638                 :  * Verify a CIDR address is OK (doesn't have bits set past the masklen)
                               1639                 :  */
                               1640                 : static bool
 7229 bruce                    1641             690 : addressOK(unsigned char *a, int bits, int family)
                               1642                 : {
                               1643                 :     int         byte;
                               1644                 :     int         nbits;
                               1645                 :     int         maxbits;
                               1646                 :     int         maxbytes;
                               1647                 :     unsigned char mask;
                               1648                 : 
 7188                          1649             690 :     if (family == PGSQL_AF_INET)
                               1650                 :     {
 7229                          1651             549 :         maxbits = 32;
                               1652             549 :         maxbytes = 4;
                               1653                 :     }
                               1654                 :     else
                               1655                 :     {
                               1656             141 :         maxbits = 128;
                               1657             141 :         maxbytes = 16;
                               1658                 :     }
 7191 tgl                      1659             690 :     Assert(bits <= maxbits);
                               1660                 : 
 7229 bruce                    1661             690 :     if (bits == maxbits)
 7191 tgl                      1662             301 :         return true;
                               1663                 : 
 6757 bruce                    1664             389 :     byte = bits / 8;
                               1665                 : 
 7229                          1666             389 :     nbits = bits % 8;
                               1667             389 :     mask = 0xff;
                               1668             389 :     if (bits != 0)
                               1669             365 :         mask >>= nbits;
                               1670                 : 
 4382                          1671            1501 :     while (byte < maxbytes)
                               1672                 :     {
                               1673            1127 :         if ((a[byte] & mask) != 0)
 7191 tgl                      1674              15 :             return false;
 7229 bruce                    1675            1112 :         mask = 0xff;
 4382                          1676            1112 :         byte++;
                               1677                 :     }
                               1678                 : 
 7191 tgl                      1679             374 :     return true;
                               1680                 : }
                               1681                 : 
                               1682                 : 
                               1683                 : /*
                               1684                 :  * These functions are used by planner to generate indexscan limits
                               1685                 :  * for clauses a << b and a <<= b
                               1686                 :  */
                               1687                 : 
                               1688                 : /* return the minimal value for an IP on a given network */
                               1689                 : Datum
 7966                          1690              24 : network_scan_first(Datum in)
                               1691                 : {
                               1692              24 :     return DirectFunctionCall1(network_network, in);
                               1693                 : }
                               1694                 : 
                               1695                 : /*
                               1696                 :  * return "last" IP on a given network. It's the broadcast address,
                               1697                 :  * however, masklen has to be set to its max bits, since
                               1698                 :  * 192.168.0.255/24 is considered less than 192.168.0.255/32
                               1699                 :  *
                               1700                 :  * inet_set_masklen() hacked to max out the masklength to 128 for IPv6
                               1701                 :  * and 32 for IPv4 when given '-1' as argument.
                               1702                 :  */
                               1703                 : Datum
                               1704              24 : network_scan_last(Datum in)
                               1705                 : {
                               1706              24 :     return DirectFunctionCall2(inet_set_masklen,
                               1707                 :                                DirectFunctionCall1(network_broadcast, in),
                               1708                 :                                Int32GetDatum(-1));
                               1709                 : }
                               1710                 : 
                               1711                 : 
                               1712                 : /*
                               1713                 :  * IP address that the client is connecting from (NULL if Unix socket)
                               1714                 :  */
                               1715                 : Datum
 6874 tgl                      1716 UBC           0 : inet_client_addr(PG_FUNCTION_ARGS)
                               1717                 : {
 6797 bruce                    1718               0 :     Port       *port = MyProcPort;
                               1719                 :     char        remote_host[NI_MAXHOST];
                               1720                 :     int         ret;
                               1721                 : 
 6874 tgl                      1722               0 :     if (port == NULL)
                               1723               0 :         PG_RETURN_NULL();
                               1724                 : 
 6797 bruce                    1725               0 :     switch (port->raddr.addr.ss_family)
                               1726                 :     {
                               1727               0 :         case AF_INET:
 6797 bruce                    1728 EUB             :         case AF_INET6:
 6797 bruce                    1729 UBC           0 :             break;
 6797 bruce                    1730 UIC           0 :         default:
                               1731               0 :             PG_RETURN_NULL();
 6874 tgl                      1732 EUB             :     }
                               1733                 : 
 6874 tgl                      1734 UBC           0 :     remote_host[0] = '\0';
                               1735                 : 
 6383 tgl                      1736 UIC           0 :     ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
                               1737                 :                              remote_host, sizeof(remote_host),
 6383 tgl                      1738 EUB             :                              NULL, 0,
                               1739                 :                              NI_NUMERICHOST | NI_NUMERICSERV);
 4261 peter_e                  1740 UIC           0 :     if (ret != 0)
 6874 tgl                      1741 UBC           0 :         PG_RETURN_NULL();
                               1742                 : 
 5806                          1743               0 :     clean_ipv6_addr(port->raddr.addr.ss_family, remote_host);
                               1744                 : 
  116 tgl                      1745 UNC           0 :     PG_RETURN_INET_P(network_in(remote_host, false, NULL));
                               1746                 : }
                               1747                 : 
                               1748                 : 
                               1749                 : /*
                               1750                 :  * port that the client is connecting from (NULL if Unix socket)
 6874 tgl                      1751 EUB             :  */
                               1752                 : Datum
 6874 tgl                      1753 UBC           0 : inet_client_port(PG_FUNCTION_ARGS)
                               1754                 : {
 6797 bruce                    1755 UIC           0 :     Port       *port = MyProcPort;
                               1756                 :     char        remote_port[NI_MAXSERV];
 6797 bruce                    1757 EUB             :     int         ret;
 6874 tgl                      1758                 : 
 6874 tgl                      1759 UIC           0 :     if (port == NULL)
 6874 tgl                      1760 UBC           0 :         PG_RETURN_NULL();
                               1761                 : 
 6797 bruce                    1762               0 :     switch (port->raddr.addr.ss_family)
                               1763                 :     {
                               1764               0 :         case AF_INET:
 6797 bruce                    1765 EUB             :         case AF_INET6:
 6797 bruce                    1766 UIC           0 :             break;
 6797 bruce                    1767 UBC           0 :         default:
 6797 bruce                    1768 UIC           0 :             PG_RETURN_NULL();
 6874 tgl                      1769 EUB             :     }
                               1770                 : 
 6874 tgl                      1771 UIC           0 :     remote_port[0] = '\0';
                               1772                 : 
 6383 tgl                      1773 UBC           0 :     ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
 6383 tgl                      1774 EUB             :                              NULL, 0,
                               1775                 :                              remote_port, sizeof(remote_port),
                               1776                 :                              NI_NUMERICHOST | NI_NUMERICSERV);
 4261 peter_e                  1777 UIC           0 :     if (ret != 0)
 6874 tgl                      1778               0 :         PG_RETURN_NULL();
                               1779                 : 
                               1780               0 :     PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
                               1781                 : }
                               1782                 : 
                               1783                 : 
 6874 tgl                      1784 EUB             : /*
                               1785                 :  * IP address that the server accepted the connection on (NULL if Unix socket)
                               1786                 :  */
                               1787                 : Datum
 6874 tgl                      1788 UIC           0 : inet_server_addr(PG_FUNCTION_ARGS)
                               1789                 : {
 6797 bruce                    1790 UBC           0 :     Port       *port = MyProcPort;
 6797 bruce                    1791 EUB             :     char        local_host[NI_MAXHOST];
                               1792                 :     int         ret;
 6874 tgl                      1793                 : 
 6874 tgl                      1794 UIC           0 :     if (port == NULL)
 6874 tgl                      1795 UBC           0 :         PG_RETURN_NULL();
                               1796                 : 
 6797 bruce                    1797               0 :     switch (port->laddr.addr.ss_family)
 6797 bruce                    1798 EUB             :     {
 6797 bruce                    1799 UBC           0 :         case AF_INET:
                               1800                 :         case AF_INET6:
 6797 bruce                    1801 UIC           0 :             break;
 6797 bruce                    1802 UBC           0 :         default:
 6797 bruce                    1803 UIC           0 :             PG_RETURN_NULL();
                               1804                 :     }
                               1805                 : 
 6874 tgl                      1806 UBC           0 :     local_host[0] = '\0';
 6874 tgl                      1807 EUB             : 
 6383 tgl                      1808 UIC           0 :     ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
 6383 tgl                      1809 EUB             :                              local_host, sizeof(local_host),
                               1810                 :                              NULL, 0,
                               1811                 :                              NI_NUMERICHOST | NI_NUMERICSERV);
 4261 peter_e                  1812 UIC           0 :     if (ret != 0)
 6874 tgl                      1813               0 :         PG_RETURN_NULL();
                               1814                 : 
 5806                          1815               0 :     clean_ipv6_addr(port->laddr.addr.ss_family, local_host);
                               1816                 : 
  116 tgl                      1817 UNC           0 :     PG_RETURN_INET_P(network_in(local_host, false, NULL));
                               1818                 : }
 6874 tgl                      1819 EUB             : 
                               1820                 : 
                               1821                 : /*
                               1822                 :  * port that the server accepted the connection on (NULL if Unix socket)
                               1823                 :  */
                               1824                 : Datum
 6874 tgl                      1825 UBC           0 : inet_server_port(PG_FUNCTION_ARGS)
 6874 tgl                      1826 EUB             : {
 6797 bruce                    1827 UIC           0 :     Port       *port = MyProcPort;
 6797 bruce                    1828 EUB             :     char        local_port[NI_MAXSERV];
                               1829                 :     int         ret;
 6874 tgl                      1830                 : 
 6874 tgl                      1831 UIC           0 :     if (port == NULL)
 6874 tgl                      1832 UBC           0 :         PG_RETURN_NULL();
 6874 tgl                      1833 EUB             : 
 6797 bruce                    1834 UBC           0 :     switch (port->laddr.addr.ss_family)
                               1835                 :     {
 6797 bruce                    1836 UIC           0 :         case AF_INET:
                               1837                 :         case AF_INET6:
                               1838               0 :             break;
                               1839               0 :         default:
                               1840               0 :             PG_RETURN_NULL();
 6874 tgl                      1841 EUB             :     }
                               1842                 : 
 6874 tgl                      1843 UIC           0 :     local_port[0] = '\0';
 6874 tgl                      1844 EUB             : 
 6383 tgl                      1845 UIC           0 :     ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
                               1846                 :                              NULL, 0,
                               1847                 :                              local_port, sizeof(local_port),
                               1848                 :                              NI_NUMERICHOST | NI_NUMERICSERV);
 4261 peter_e                  1849 LBC           0 :     if (ret != 0)
 6874 tgl                      1850 UIC           0 :         PG_RETURN_NULL();
 6874 tgl                      1851 ECB             : 
 6874 tgl                      1852 UIC           0 :     PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
                               1853                 : }
 6266 bruce                    1854 ECB             : 
                               1855                 : 
                               1856                 : Datum
 6266 bruce                    1857 CBC          51 : inetnot(PG_FUNCTION_ARGS)
 6266 bruce                    1858 ECB             : {
 4136 heikki.linnakangas       1859 CBC          51 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1860                 :     inet       *dst;
 6266 bruce                    1861 ECB             : 
 5847 tgl                      1862 CBC          51 :     dst = (inet *) palloc0(sizeof(inet));
                               1863                 : 
 6266 bruce                    1864 ECB             :     {
 6031 bruce                    1865 GIC          51 :         int         nb = ip_addrsize(ip);
 6031 bruce                    1866 CBC          51 :         unsigned char *pip = ip_addr(ip);
                               1867              51 :         unsigned char *pdst = ip_addr(dst);
                               1868                 : 
   24 andres                   1869             363 :         while (--nb >= 0)
 6266 bruce                    1870 GIC         312 :             pdst[nb] = ~pip[nb];
                               1871                 :     }
                               1872              51 :     ip_bits(dst) = ip_bits(ip);
                               1873                 : 
 6266 bruce                    1874 CBC          51 :     ip_family(dst) = ip_family(ip);
 5847 tgl                      1875 GIC          51 :     SET_INET_VARSIZE(dst);
 6266 bruce                    1876 ECB             : 
 6266 bruce                    1877 CBC          51 :     PG_RETURN_INET_P(dst);
                               1878                 : }
                               1879                 : 
 6266 bruce                    1880 ECB             : 
                               1881                 : Datum
 6266 bruce                    1882 CBC          51 : inetand(PG_FUNCTION_ARGS)
 6266 bruce                    1883 EUB             : {
 4136 heikki.linnakangas       1884 GIC          51 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1885              51 :     inet       *ip2 = PG_GETARG_INET_PP(1);
                               1886                 :     inet       *dst;
                               1887                 : 
 5847 tgl                      1888 CBC          51 :     dst = (inet *) palloc0(sizeof(inet));
 6266 bruce                    1889 ECB             : 
 6266 bruce                    1890 CBC          51 :     if (ip_family(ip) != ip_family(ip2))
 6266 bruce                    1891 LBC           0 :         ereport(ERROR,
                               1892                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 6266 tgl                      1893 ECB             :                  errmsg("cannot AND inet values of different sizes")));
      bruce                    1894                 :     else
                               1895                 :     {
 6031 bruce                    1896 CBC          51 :         int         nb = ip_addrsize(ip);
 6031 bruce                    1897 GIC          51 :         unsigned char *pip = ip_addr(ip);
 6031 bruce                    1898 CBC          51 :         unsigned char *pip2 = ip_addr(ip2);
                               1899              51 :         unsigned char *pdst = ip_addr(dst);
                               1900                 : 
   24 andres                   1901             363 :         while (--nb >= 0)
 6266 bruce                    1902 GIC         312 :             pdst[nb] = pip[nb] & pip2[nb];
                               1903                 :     }
                               1904              51 :     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
                               1905                 : 
 6266 bruce                    1906 CBC          51 :     ip_family(dst) = ip_family(ip);
 5847 tgl                      1907 GIC          51 :     SET_INET_VARSIZE(dst);
 6266 bruce                    1908 ECB             : 
 6266 bruce                    1909 CBC          51 :     PG_RETURN_INET_P(dst);
                               1910                 : }
                               1911                 : 
 6266 bruce                    1912 ECB             : 
                               1913                 : Datum
 6266 bruce                    1914 CBC          51 : inetor(PG_FUNCTION_ARGS)
 6266 bruce                    1915 EUB             : {
 4136 heikki.linnakangas       1916 GIC          51 :     inet       *ip = PG_GETARG_INET_PP(0);
                               1917              51 :     inet       *ip2 = PG_GETARG_INET_PP(1);
                               1918                 :     inet       *dst;
                               1919                 : 
 5847 tgl                      1920 CBC          51 :     dst = (inet *) palloc0(sizeof(inet));
 6266 bruce                    1921 ECB             : 
 6266 bruce                    1922 CBC          51 :     if (ip_family(ip) != ip_family(ip2))
 6266 bruce                    1923 LBC           0 :         ereport(ERROR,
                               1924                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 6266 tgl                      1925 ECB             :                  errmsg("cannot OR inet values of different sizes")));
      bruce                    1926                 :     else
                               1927                 :     {
 6031 bruce                    1928 CBC          51 :         int         nb = ip_addrsize(ip);
 6031 bruce                    1929 GIC          51 :         unsigned char *pip = ip_addr(ip);
 6031 bruce                    1930 CBC          51 :         unsigned char *pip2 = ip_addr(ip2);
                               1931              51 :         unsigned char *pdst = ip_addr(dst);
                               1932                 : 
   24 andres                   1933             363 :         while (--nb >= 0)
 6266 bruce                    1934 GIC         312 :             pdst[nb] = pip[nb] | pip2[nb];
                               1935                 :     }
                               1936              51 :     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
                               1937                 : 
 6266 bruce                    1938 CBC          51 :     ip_family(dst) = ip_family(ip);
 5847 tgl                      1939 GIC          51 :     SET_INET_VARSIZE(dst);
                               1940                 : 
 6266 bruce                    1941              51 :     PG_RETURN_INET_P(dst);
 6266 bruce                    1942 ECB             : }
                               1943                 : 
                               1944                 : 
      tgl                      1945                 : static inet *
 6266 tgl                      1946 CBC        2571 : internal_inetpl(inet *ip, int64 addend)
 6266 bruce                    1947 ECB             : {
                               1948                 :     inet       *dst;
                               1949                 : 
 5847 tgl                      1950 CBC        2571 :     dst = (inet *) palloc0(sizeof(inet));
                               1951                 : 
 6266 bruce                    1952 ECB             :     {
 6031 bruce                    1953 CBC        2571 :         int         nb = ip_addrsize(ip);
                               1954            2571 :         unsigned char *pip = ip_addr(ip);
 6031 bruce                    1955 GIC        2571 :         unsigned char *pdst = ip_addr(dst);
                               1956            2571 :         int         carry = 0;
                               1957                 : 
   24 andres                   1958           18687 :         while (--nb >= 0)
                               1959                 :         {
 6266 tgl                      1960           16116 :             carry = pip[nb] + (int) (addend & 0xFF) + carry;
                               1961           16116 :             pdst[nb] = (unsigned char) (carry & 0xFF);
                               1962           16116 :             carry >>= 8;
                               1963                 : 
                               1964                 :             /*
 6266 tgl                      1965 ECB             :              * We have to be careful about right-shifting addend because
 6031 bruce                    1966                 :              * right-shift isn't portable for negative values, while simply
                               1967                 :              * dividing by 256 doesn't work (the standard rounding is in the
                               1968                 :              * wrong direction, besides which there may be machines out there
                               1969                 :              * that round the wrong way).  So, explicitly clear the low-order
                               1970                 :              * byte to remove any doubt about the correct result of the
                               1971                 :              * division, and then divide rather than shift.
                               1972                 :              */
 6266 tgl                      1973 GIC       16116 :             addend &= ~((int64) 0xFF);
 6266 tgl                      1974 CBC       16116 :             addend /= 0x100;
 6266 bruce                    1975 ECB             :         }
 6031                          1976                 : 
                               1977                 :         /*
                               1978                 :          * At this point we should have addend and carry both zero if original
                               1979                 :          * addend was >= 0, or addend -1 and carry 1 if original addend was <
                               1980                 :          * 0.  Anything else means overflow.
 6266 tgl                      1981                 :          */
 6266 tgl                      1982 CBC        2571 :         if (!((addend == 0 && carry == 0) ||
                               1983              63 :               (addend == -1 && carry == 1)))
 6266 tgl                      1984 GIC           6 :             ereport(ERROR,
 6266 tgl                      1985 ECB             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               1986                 :                      errmsg("result is out of range")));
                               1987                 :     }
                               1988                 : 
 5847 tgl                      1989 GIC        2565 :     ip_bits(dst) = ip_bits(ip);
 6266 bruce                    1990 CBC        2565 :     ip_family(dst) = ip_family(ip);
 5847 tgl                      1991 GIC        2565 :     SET_INET_VARSIZE(dst);
 6266 bruce                    1992 ECB             : 
 6266 tgl                      1993 CBC        2565 :     return dst;
                               1994                 : }
 6266 bruce                    1995 ECB             : 
                               1996                 : 
                               1997                 : Datum
 6266 bruce                    1998 GIC        2505 : inetpl(PG_FUNCTION_ARGS)
                               1999                 : {
 4136 heikki.linnakangas       2000 CBC        2505 :     inet       *ip = PG_GETARG_INET_PP(0);
 6031 bruce                    2001 GIC        2505 :     int64       addend = PG_GETARG_INT64(1);
 6266 bruce                    2002 ECB             : 
 6266 tgl                      2003 CBC        2505 :     PG_RETURN_INET_P(internal_inetpl(ip, addend));
                               2004                 : }
 6266 bruce                    2005 ECB             : 
                               2006                 : 
                               2007                 : Datum
 6266 bruce                    2008 GIC          66 : inetmi_int8(PG_FUNCTION_ARGS)
                               2009                 : {
 4136 heikki.linnakangas       2010 CBC          66 :     inet       *ip = PG_GETARG_INET_PP(0);
 6031 bruce                    2011 GIC          66 :     int64       addend = PG_GETARG_INT64(1);
 6266 bruce                    2012 ECB             : 
 6266 tgl                      2013 CBC          66 :     PG_RETURN_INET_P(internal_inetpl(ip, -addend));
 6266 bruce                    2014 ECB             : }
                               2015                 : 
                               2016                 : 
 6266 bruce                    2017 EUB             : Datum
 6266 bruce                    2018 GIC          72 : inetmi(PG_FUNCTION_ARGS)
                               2019                 : {
 4136 heikki.linnakangas       2020              72 :     inet       *ip = PG_GETARG_INET_PP(0);
                               2021              72 :     inet       *ip2 = PG_GETARG_INET_PP(1);
 6266 bruce                    2022              72 :     int64       res = 0;
                               2023                 : 
                               2024              72 :     if (ip_family(ip) != ip_family(ip2))
 6266 bruce                    2025 UIC           0 :         ereport(ERROR,
                               2026                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               2027                 :                  errmsg("cannot subtract inet values of different sizes")));
 6266 bruce                    2028 ECB             :     else
                               2029                 :     {
      tgl                      2030                 :         /*
 6031 bruce                    2031                 :          * We form the difference using the traditional complement, increment,
                               2032                 :          * and add rule, with the increment part being handled by starting the
                               2033                 :          * carry off at 1.  If you don't think integer arithmetic is done in
                               2034                 :          * two's complement, too bad.
                               2035                 :          */
 6031 bruce                    2036 GIC          72 :         int         nb = ip_addrsize(ip);
 4382                          2037              72 :         int         byte = 0;
 6031 bruce                    2038 CBC          72 :         unsigned char *pip = ip_addr(ip);
                               2039              72 :         unsigned char *pip2 = ip_addr(ip2);
                               2040              72 :         int         carry = 1;
                               2041                 : 
   24 andres                   2042             636 :         while (--nb >= 0)
                               2043                 :         {
                               2044                 :             int         lobyte;
                               2045                 : 
 6266 tgl                      2046 GIC         570 :             carry = pip[nb] + (~pip2[nb] & 0xFF) + carry;
                               2047             570 :             lobyte = carry & 0xFF;
 4382 bruce                    2048             570 :             if (byte < sizeof(int64))
                               2049                 :             {
                               2050             384 :                 res |= ((int64) lobyte) << (byte * 8);
 6266 tgl                      2051 ECB             :             }
                               2052                 :             else
                               2053                 :             {
                               2054                 :                 /*
                               2055                 :                  * Input wider than int64: check for overflow.  All bytes to
 6031 bruce                    2056                 :                  * the left of what will fit should be 0 or 0xFF, depending on
                               2057                 :                  * sign of the now-complete result.
                               2058                 :                  */
 6266 tgl                      2059 GIC         186 :                 if ((res < 0) ? (lobyte != 0xFF) : (lobyte != 0))
      bruce                    2060               6 :                     ereport(ERROR,
                               2061                 :                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                               2062                 :                              errmsg("result is out of range")));
                               2063                 :             }
 6266 tgl                      2064 CBC         564 :             carry >>= 8;
 4382 bruce                    2065             564 :             byte++;
                               2066                 :         }
                               2067                 : 
 6266 tgl                      2068 ECB             :         /*
                               2069                 :          * If input is narrower than int64, overflow is not possible, but we
                               2070                 :          * have to do proper sign extension.
                               2071                 :          */
 4382 bruce                    2072 GIC          66 :         if (carry == 0 && byte < sizeof(int64))
 1757 tgl                      2073               6 :             res |= ((uint64) (int64) -1) << (byte * 8);
                               2074                 :     }
                               2075                 : 
 6266 bruce                    2076              66 :     PG_RETURN_INT64(res);
                               2077                 : }
                               2078                 : 
                               2079                 : 
                               2080                 : /*
                               2081                 :  * clean_ipv6_addr --- remove any '%zone' part from an IPv6 address string
                               2082                 :  *
                               2083                 :  * XXX This should go away someday!
                               2084                 :  *
                               2085                 :  * This is a kluge needed because we don't yet support zones in stored inet
                               2086                 :  * values.  Since the result of getnameinfo() might include a zone spec,
 5806 tgl                      2087 ECB             :  * call this to remove it anywhere we want to feed getnameinfo's output to
                               2088                 :  * network_in.  Beats failing entirely.
                               2089                 :  *
                               2090                 :  * An alternative approach would be to let network_in ignore %-parts for
                               2091                 :  * itself, but that would mean we'd silently drop zone specs in user input,
                               2092                 :  * which seems not such a good idea.
                               2093                 :  */
 5806 tgl                      2094 EUB             : void
 5806 tgl                      2095 GIC          39 : clean_ipv6_addr(int addr_family, char *addr)
 5806 tgl                      2096 ECB             : {
 5806 tgl                      2097 GIC          39 :     if (addr_family == AF_INET6)
                               2098                 :     {
 5624 bruce                    2099              12 :         char       *pct = strchr(addr, '%');
                               2100                 : 
 5806 tgl                      2101              12 :         if (pct)
 5806 tgl                      2102 UIC           0 :             *pct = '\0';
                               2103                 :     }
 5806 tgl                      2104 GIC          39 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a