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 15:15:32 Functions: 80.0 % 70 56 1 3 10 8 3 45 3 8 1
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           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 *
      75 GNC        2348 : network_in(char *src, bool is_cidr, Node *escontext)
      76                 : {
      77                 :     int         bits;
      78                 :     inet       *dst;
      79                 : 
      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                 : 
      88            2348 :     if (strchr(src, ':') != NULL)
      89             448 :         ip_family(dst) = PGSQL_AF_INET6;
      90                 :     else
      91            1900 :         ip_family(dst) = PGSQL_AF_INET;
      92                 : 
      93            3047 :     bits = pg_inet_net_pton(ip_family(dst), src, ip_addr(dst),
      94             699 :                             is_cidr ? ip_addrsize(dst) : -1);
      95            2348 :     if ((bits < 0) || (bits > ip_maxbits(dst)))
      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                 :      */
     105 CBC        2333 :     if (is_cidr)
     106                 :     {
     107             690 :         if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
     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                 : 
     114 CBC        2318 :     ip_bits(dst) = bits;
     115            2318 :     SET_INET_VARSIZE(dst);
     116                 : 
     117            2318 :     return dst;
     118                 : }
     119                 : 
     120                 : Datum
     121            1649 : inet_in(PG_FUNCTION_ARGS)
     122                 : {
     123            1649 :     char       *src = PG_GETARG_CSTRING(0);
     124                 : 
     125 GNC        1649 :     PG_RETURN_INET_P(network_in(src, false, fcinfo->context));
     126                 : }
     127                 : 
     128                 : Datum
     129 CBC         699 : cidr_in(PG_FUNCTION_ARGS)
     130                 : {
     131             699 :     char       *src = PG_GETARG_CSTRING(0);
     132                 : 
     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 *
     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                 : 
     147            7038 :     dst = pg_inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),
     148                 :                            tmp, sizeof(tmp));
     149            7038 :     if (dst == NULL)
     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 */
     155 CBC        7038 :     if (is_cidr && strchr(tmp, '/') == NULL)
     156                 :     {
     157             539 :         len = strlen(tmp);
     158             539 :         snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
     159                 :     }
     160                 : 
     161            7038 :     return pstrdup(tmp);
     162                 : }
     163                 : 
     164                 : Datum
     165            4238 : inet_out(PG_FUNCTION_ARGS)
     166                 : {
     167            4238 :     inet       *src = PG_GETARG_INET_PP(0);
     168                 : 
     169            4238 :     PG_RETURN_CSTRING(network_out(src, false));
     170                 : }
     171                 : 
     172                 : Datum
     173            2800 : cidr_out(PG_FUNCTION_ARGS)
     174                 : {
     175            2800 :     inet       *src = PG_GETARG_INET_PP(0);
     176                 : 
     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 *
     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 */
     201               0 :     addr = (inet *) palloc0(sizeof(inet));
     202                 : 
     203               0 :     ip_family(addr) = pq_getmsgbyte(buf);
     204               0 :     if (ip_family(addr) != PGSQL_AF_INET &&
     205               0 :         ip_family(addr) != PGSQL_AF_INET6)
     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")));
     211               0 :     bits = pq_getmsgbyte(buf);
     212               0 :     if (bits < 0 || bits > ip_maxbits(addr))
     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")));
     218               0 :     ip_bits(addr) = bits;
     219               0 :     i = pq_getmsgbyte(buf);     /* ignore is_cidr */
     220               0 :     nb = pq_getmsgbyte(buf);
     221               0 :     if (nb != ip_addrsize(addr))
     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                 : 
     228               0 :     addrptr = (char *) ip_addr(addr);
     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                 :      */
     235               0 :     if (is_cidr)
     236                 :     {
     237               0 :         if (!addressOK(ip_addr(addr), bits, ip_family(addr)))
     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                 : 
     244               0 :     SET_INET_VARSIZE(addr);
     245                 : 
     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
     258               0 : cidr_recv(PG_FUNCTION_ARGS)
     259                 : {
     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                 : 
     277               0 :     pq_begintypsend(&buf);
     278               0 :     pq_sendbyte(&buf, ip_family(addr));
     279               0 :     pq_sendbyte(&buf, ip_bits(addr));
     280               0 :     pq_sendbyte(&buf, is_cidr);
     281               0 :     nb = ip_addrsize(addr);
     282               0 :     if (nb < 0)
     283               0 :         nb = 0;
     284               0 :     pq_sendbyte(&buf, nb);
     285               0 :     addrptr = (char *) ip_addr(addr);
     286               0 :     for (i = 0; i < nb; i++)
     287               0 :         pq_sendbyte(&buf, addrptr[i]);
     288               0 :     return pq_endtypsend(&buf);
     289                 : }
     290                 : 
     291                 : Datum
     292               0 : inet_send(PG_FUNCTION_ARGS)
     293                 : {
     294               0 :     inet       *addr = PG_GETARG_INET_PP(0);
     295                 : 
     296               0 :     PG_RETURN_BYTEA_P(network_send(addr, false));
     297                 : }
     298                 : 
     299                 : Datum
     300               0 : cidr_send(PG_FUNCTION_ARGS)
     301                 : {
     302               0 :     inet       *addr = PG_GETARG_INET_PP(0);
     303                 : 
     304               0 :     PG_RETURN_BYTEA_P(network_send(addr, true));
     305                 : }
     306                 : 
     307                 : 
     308                 : Datum
     309 CBC        1770 : inet_to_cidr(PG_FUNCTION_ARGS)
     310                 : {
     311            1770 :     inet       *src = PG_GETARG_INET_PP(0);
     312                 :     int         bits;
     313                 : 
     314            1770 :     bits = ip_bits(src);
     315                 : 
     316                 :     /* safety check */
     317            1770 :     if ((bits < 0) || (bits > ip_maxbits(src)))
     318 UBC           0 :         elog(ERROR, "invalid inet bit length: %d", bits);
     319                 : 
     320 CBC        1770 :     PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
     321                 : }
     322                 : 
     323                 : Datum
     324              75 : inet_set_masklen(PG_FUNCTION_ARGS)
     325                 : {
     326              75 :     inet       *src = PG_GETARG_INET_PP(0);
     327              75 :     int         bits = PG_GETARG_INT32(1);
     328                 :     inet       *dst;
     329                 : 
     330              75 :     if (bits == -1)
     331              24 :         bits = ip_maxbits(src);
     332                 : 
     333              75 :     if ((bits < 0) || (bits > ip_maxbits(src)))
     334 UBC           0 :         ereport(ERROR,
     335                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     336                 :                  errmsg("invalid mask length: %d", bits)));
     337                 : 
     338                 :     /* clone the original data */
     339 CBC          75 :     dst = (inet *) palloc(VARSIZE_ANY(src));
     340              75 :     memcpy(dst, src, VARSIZE_ANY(src));
     341                 : 
     342              75 :     ip_bits(dst) = bits;
     343                 : 
     344              75 :     PG_RETURN_INET_P(dst);
     345                 : }
     346                 : 
     347                 : Datum
     348 UBC           0 : cidr_set_masklen(PG_FUNCTION_ARGS)
     349                 : {
     350               0 :     inet       *src = PG_GETARG_INET_PP(0);
     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                 : 
     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 *
     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
     405          238810 : network_cmp_internal(inet *a1, inet *a2)
     406                 : {
     407          238810 :     if (ip_family(a1) == ip_family(a2))
     408                 :     {
     409                 :         int         order;
     410                 : 
     411          163042 :         order = bitncmp(ip_addr(a1), ip_addr(a2),
     412          163042 :                         Min(ip_bits(a1), ip_bits(a2)));
     413          163042 :         if (order != 0)
     414          152703 :             return order;
     415           10339 :         order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
     416           10339 :         if (order != 0)
     417             438 :             return order;
     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
     425             134 : network_cmp(PG_FUNCTION_ARGS)
     426                 : {
     427             134 :     inet       *a1 = PG_GETARG_INET_PP(0);
     428             134 :     inet       *a2 = PG_GETARG_INET_PP(1);
     429                 : 
     430             134 :     PG_RETURN_INT32(network_cmp_internal(a1, a2));
     431                 : }
     432                 : 
     433                 : /*
     434                 :  * SortSupport strategy routine
     435                 :  */
     436                 : Datum
     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                 : 
     458              80 :         ssup->comparator = ssup_datum_unsigned_cmp;
     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                 : 
     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
     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
     796          151433 : network_lt(PG_FUNCTION_ARGS)
     797                 : {
     798          151433 :     inet       *a1 = PG_GETARG_INET_PP(0);
     799          151433 :     inet       *a2 = PG_GETARG_INET_PP(1);
     800                 : 
     801          151433 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) < 0);
     802                 : }
     803                 : 
     804                 : Datum
     805            9430 : network_le(PG_FUNCTION_ARGS)
     806                 : {
     807            9430 :     inet       *a1 = PG_GETARG_INET_PP(0);
     808            9430 :     inet       *a2 = PG_GETARG_INET_PP(1);
     809                 : 
     810            9430 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) <= 0);
     811                 : }
     812                 : 
     813                 : Datum
     814           50970 : network_eq(PG_FUNCTION_ARGS)
     815                 : {
     816           50970 :     inet       *a1 = PG_GETARG_INET_PP(0);
     817           50970 :     inet       *a2 = PG_GETARG_INET_PP(1);
     818                 : 
     819           50970 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) == 0);
     820                 : }
     821                 : 
     822                 : Datum
     823            9586 : network_ge(PG_FUNCTION_ARGS)
     824                 : {
     825            9586 :     inet       *a1 = PG_GETARG_INET_PP(0);
     826            9586 :     inet       *a2 = PG_GETARG_INET_PP(1);
     827                 : 
     828            9586 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) >= 0);
     829                 : }
     830                 : 
     831                 : Datum
     832           11036 : network_gt(PG_FUNCTION_ARGS)
     833                 : {
     834           11036 :     inet       *a1 = PG_GETARG_INET_PP(0);
     835           11036 :     inet       *a2 = PG_GETARG_INET_PP(1);
     836                 : 
     837           11036 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) > 0);
     838                 : }
     839                 : 
     840                 : Datum
     841              51 : network_ne(PG_FUNCTION_ARGS)
     842                 : {
     843              51 :     inet       *a1 = PG_GETARG_INET_PP(0);
     844              51 :     inet       *a2 = PG_GETARG_INET_PP(1);
     845                 : 
     846              51 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
     847                 : }
     848                 : 
     849                 : /*
     850                 :  * MIN/MAX support functions.
     851                 :  */
     852                 : Datum
     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
     880            3036 : hashinet(PG_FUNCTION_ARGS)
     881                 : {
     882            3036 :     inet       *addr = PG_GETARG_INET_PP(0);
     883            3036 :     int         addrsize = ip_addrsize(addr);
     884                 : 
     885                 :     /* XXX this assumes there are no pad bytes in the data structure */
     886            3036 :     return hash_any((unsigned char *) VARDATA_ANY(addr), addrsize + 2);
     887                 : }
     888                 : 
     889                 : Datum
     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
     903            3066 : network_sub(PG_FUNCTION_ARGS)
     904                 : {
     905            3066 :     inet       *a1 = PG_GETARG_INET_PP(0);
     906            3066 :     inet       *a2 = PG_GETARG_INET_PP(1);
     907                 : 
     908            3066 :     if (ip_family(a1) == ip_family(a2))
     909                 :     {
     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                 : 
     914             600 :     PG_RETURN_BOOL(false);
     915                 : }
     916                 : 
     917                 : Datum
     918            4953 : network_subeq(PG_FUNCTION_ARGS)
     919                 : {
     920            4953 :     inet       *a1 = PG_GETARG_INET_PP(0);
     921            4953 :     inet       *a2 = PG_GETARG_INET_PP(1);
     922                 : 
     923            4953 :     if (ip_family(a1) == ip_family(a2))
     924                 :     {
     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                 : 
     929            1884 :     PG_RETURN_BOOL(false);
     930                 : }
     931                 : 
     932                 : Datum
     933            3090 : network_sup(PG_FUNCTION_ARGS)
     934                 : {
     935            3090 :     inet       *a1 = PG_GETARG_INET_PP(0);
     936            3090 :     inet       *a2 = PG_GETARG_INET_PP(1);
     937                 : 
     938            3090 :     if (ip_family(a1) == ip_family(a2))
     939                 :     {
     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                 : 
     944             600 :     PG_RETURN_BOOL(false);
     945                 : }
     946                 : 
     947                 : Datum
     948            9294 : network_supeq(PG_FUNCTION_ARGS)
     949                 : {
     950            9294 :     inet       *a1 = PG_GETARG_INET_PP(0);
     951            9294 :     inet       *a2 = PG_GETARG_INET_PP(1);
     952                 : 
     953            9294 :     if (ip_family(a1) == ip_family(a2))
     954                 :     {
     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                 : 
     959            4170 :     PG_RETURN_BOOL(false);
     960                 : }
     961                 : 
     962                 : Datum
     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
     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                 :         }
    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                 : 
    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)
    1039 UBC           0 :                 return NIL;
    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)
    1045 UBC           0 :                 return NIL;
    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)
    1051 UBC           0 :                 return NIL;
    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)
    1057 UBC           0 :                 return NIL;
    1058 CBC           6 :             return match_network_subset(rightop, leftop, true, opfamily);
    1059                 : 
    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 *
    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)
    1099 UBC           0 :         return NIL;
    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)
    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                 :      */
    1121 CBC          24 :     if (is_eq)
    1122                 :     {
    1123              12 :         opr1oid = get_opfamily_member(opfamily, datatype, datatype,
    1124                 :                                       BTGreaterEqualStrategyNumber);
    1125              12 :         if (opr1oid == InvalidOid)
    1126 UBC           0 :             elog(ERROR, "no >= operator for opfamily %u", opfamily);
    1127                 :     }
    1128                 :     else
    1129                 :     {
    1130 CBC          12 :         opr1oid = get_opfamily_member(opfamily, datatype, datatype,
    1131                 :                                       BTGreaterStrategyNumber);
    1132              12 :         if (opr1oid == InvalidOid)
    1133 UBC           0 :             elog(ERROR, "no > operator for opfamily %u", opfamily);
    1134                 :     }
    1135                 : 
    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)
    1152 UBC           0 :         elog(ERROR, "no <= operator for opfamily %u", opfamily);
    1153                 : 
    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
    1173              51 : network_host(PG_FUNCTION_ARGS)
    1174                 : {
    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... */
    1180              51 :     if (pg_inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
    1181                 :                          tmp, sizeof(tmp)) == NULL)
    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) */
    1187 CBC          51 :     if ((ptr = strchr(tmp, '/')) != NULL)
    1188 UBC           0 :         *ptr = '\0';
    1189                 : 
    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
    1199             106 : network_show(PG_FUNCTION_ARGS)
    1200                 : {
    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                 : 
    1205             106 :     if (pg_inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
    1206                 :                          tmp, sizeof(tmp)) == NULL)
    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) */
    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                 : 
    1218             106 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1219                 : }
    1220                 : 
    1221                 : Datum
    1222 UBC           0 : inet_abbrev(PG_FUNCTION_ARGS)
    1223                 : {
    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                 : 
    1228               0 :     dst = pg_inet_net_ntop(ip_family(ip), ip_addr(ip),
    1229               0 :                            ip_bits(ip), tmp, sizeof(tmp));
    1230                 : 
    1231               0 :     if (dst == NULL)
    1232               0 :         ereport(ERROR,
    1233                 :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    1234                 :                  errmsg("could not format inet value: %m")));
    1235                 : 
    1236               0 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1237                 : }
    1238                 : 
    1239                 : Datum
    1240 CBC          51 : cidr_abbrev(PG_FUNCTION_ARGS)
    1241                 : {
    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                 : 
    1246              51 :     dst = pg_inet_cidr_ntop(ip_family(ip), ip_addr(ip),
    1247              51 :                             ip_bits(ip), tmp, sizeof(tmp));
    1248                 : 
    1249              51 :     if (dst == NULL)
    1250 UBC           0 :         ereport(ERROR,
    1251                 :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    1252                 :                  errmsg("could not format cidr value: %m")));
    1253                 : 
    1254 CBC          51 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1255                 : }
    1256                 : 
    1257                 : Datum
    1258             177 : network_masklen(PG_FUNCTION_ARGS)
    1259                 : {
    1260             177 :     inet       *ip = PG_GETARG_INET_PP(0);
    1261                 : 
    1262             177 :     PG_RETURN_INT32(ip_bits(ip));
    1263                 : }
    1264                 : 
    1265                 : Datum
    1266              51 : network_family(PG_FUNCTION_ARGS)
    1267                 : {
    1268              51 :     inet       *ip = PG_GETARG_INET_PP(0);
    1269                 : 
    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;
    1278 UBC           0 :         default:
    1279               0 :             PG_RETURN_INT32(0);
    1280                 :             break;
    1281                 :     }
    1282                 : }
    1283                 : 
    1284                 : Datum
    1285 CBC         126 : network_broadcast(PG_FUNCTION_ARGS)
    1286                 : {
    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 */
    1297             126 :     dst = (inet *) palloc0(sizeof(inet));
    1298                 : 
    1299             126 :     maxbytes = ip_addrsize(ip);
    1300             126 :     bits = ip_bits(ip);
    1301             126 :     a = ip_addr(ip);
    1302             126 :     b = ip_addr(dst);
    1303                 : 
    1304             846 :     for (byte = 0; byte < maxbytes; byte++)
    1305                 :     {
    1306             720 :         if (bits >= 8)
    1307                 :         {
    1308             495 :             mask = 0x00;
    1309             495 :             bits -= 8;
    1310                 :         }
    1311             225 :         else if (bits == 0)
    1312             213 :             mask = 0xff;
    1313                 :         else
    1314                 :         {
    1315              12 :             mask = 0xff >> bits;
    1316              12 :             bits = 0;
    1317                 :         }
    1318                 : 
    1319             720 :         b[byte] = a[byte] | mask;
    1320                 :     }
    1321                 : 
    1322             126 :     ip_family(dst) = ip_family(ip);
    1323             126 :     ip_bits(dst) = ip_bits(ip);
    1324             126 :     SET_INET_VARSIZE(dst);
    1325                 : 
    1326             126 :     PG_RETURN_INET_P(dst);
    1327                 : }
    1328                 : 
    1329                 : Datum
    1330             126 : network_network(PG_FUNCTION_ARGS)
    1331                 : {
    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 */
    1341             126 :     dst = (inet *) palloc0(sizeof(inet));
    1342                 : 
    1343             126 :     bits = ip_bits(ip);
    1344             126 :     a = ip_addr(ip);
    1345             126 :     b = ip_addr(dst);
    1346                 : 
    1347             126 :     byte = 0;
    1348                 : 
    1349             633 :     while (bits)
    1350                 :     {
    1351             507 :         if (bits >= 8)
    1352                 :         {
    1353             495 :             mask = 0xff;
    1354             495 :             bits -= 8;
    1355                 :         }
    1356                 :         else
    1357                 :         {
    1358              12 :             mask = 0xff << (8 - bits);
    1359              12 :             bits = 0;
    1360                 :         }
    1361                 : 
    1362             507 :         b[byte] = a[byte] & mask;
    1363             507 :         byte++;
    1364                 :     }
    1365                 : 
    1366             126 :     ip_family(dst) = ip_family(ip);
    1367             126 :     ip_bits(dst) = ip_bits(ip);
    1368             126 :     SET_INET_VARSIZE(dst);
    1369                 : 
    1370             126 :     PG_RETURN_INET_P(dst);
    1371                 : }
    1372                 : 
    1373                 : Datum
    1374 UBC           0 : network_netmask(PG_FUNCTION_ARGS)
    1375                 : {
    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 */
    1384               0 :     dst = (inet *) palloc0(sizeof(inet));
    1385                 : 
    1386               0 :     bits = ip_bits(ip);
    1387               0 :     b = ip_addr(dst);
    1388                 : 
    1389               0 :     byte = 0;
    1390                 : 
    1391               0 :     while (bits)
    1392                 :     {
    1393               0 :         if (bits >= 8)
    1394                 :         {
    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;
    1405               0 :         byte++;
    1406                 :     }
    1407                 : 
    1408               0 :     ip_family(dst) = ip_family(ip);
    1409               0 :     ip_bits(dst) = ip_maxbits(ip);
    1410               0 :     SET_INET_VARSIZE(dst);
    1411                 : 
    1412               0 :     PG_RETURN_INET_P(dst);
    1413                 : }
    1414                 : 
    1415                 : Datum
    1416               0 : network_hostmask(PG_FUNCTION_ARGS)
    1417                 : {
    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 */
    1427               0 :     dst = (inet *) palloc0(sizeof(inet));
    1428                 : 
    1429               0 :     maxbytes = ip_addrsize(ip);
    1430               0 :     bits = ip_maxbits(ip) - ip_bits(ip);
    1431               0 :     b = ip_addr(dst);
    1432                 : 
    1433               0 :     byte = maxbytes - 1;
    1434                 : 
    1435               0 :     while (bits)
    1436                 :     {
    1437               0 :         if (bits >= 8)
    1438                 :         {
    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;
    1449               0 :         byte--;
    1450                 :     }
    1451                 : 
    1452               0 :     ip_family(dst) = ip_family(ip);
    1453               0 :     ip_bits(dst) = ip_maxbits(ip);
    1454               0 :     SET_INET_VARSIZE(dst);
    1455                 : 
    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
    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),
    1479             117 :                *a2 = PG_GETARG_INET_PP(1);
    1480                 :     int         commonbits;
    1481                 : 
    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                 : 
    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
    1502            5440 : convert_network_to_scalar(Datum value, Oid typid, bool *failure)
    1503                 : {
    1504            5440 :     switch (typid)
    1505                 :     {
    1506            5440 :         case INETOID:
    1507                 :         case CIDROID:
    1508                 :             {
    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                 :                  */
    1517            5440 :                 if (ip_family(ip) == PGSQL_AF_INET)
    1518            5440 :                     len = 4;
    1519                 :                 else
    1520 UBC           0 :                     len = 5;
    1521                 : 
    1522 CBC        5440 :                 res = ip_family(ip);
    1523           27200 :                 for (i = 0; i < len; i++)
    1524                 :                 {
    1525           21760 :                     res *= 256;
    1526           21760 :                     res += ip_addr(ip)[i];
    1527                 :                 }
    1528            5440 :                 return res;
    1529                 :             }
    1530 UBC           0 :         case MACADDROID:
    1531                 :             {
    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                 :             }
    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                 : 
    1552               0 :     *failure = true;
    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
    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                 : 
    1576          193223 :     b = n / 8;
    1577          193223 :     x = memcmp(l, r, b);
    1578          193223 :     if (x || (n % 8) == 0)
    1579          193102 :         return x;
    1580                 : 
    1581             121 :     lb = l[b];
    1582             121 :     rb = r[b];
    1583             215 :     for (b = n % 8; b > 0; b--)
    1584                 :     {
    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                 :         }
    1591              94 :         lb <<= 1;
    1592              94 :         rb <<= 1;
    1593                 :     }
    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
    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
    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                 : 
    1649             690 :     if (family == PGSQL_AF_INET)
    1650                 :     {
    1651             549 :         maxbits = 32;
    1652             549 :         maxbytes = 4;
    1653                 :     }
    1654                 :     else
    1655                 :     {
    1656             141 :         maxbits = 128;
    1657             141 :         maxbytes = 16;
    1658                 :     }
    1659             690 :     Assert(bits <= maxbits);
    1660                 : 
    1661             690 :     if (bits == maxbits)
    1662             301 :         return true;
    1663                 : 
    1664             389 :     byte = bits / 8;
    1665                 : 
    1666             389 :     nbits = bits % 8;
    1667             389 :     mask = 0xff;
    1668             389 :     if (bits != 0)
    1669             365 :         mask >>= nbits;
    1670                 : 
    1671            1501 :     while (byte < maxbytes)
    1672                 :     {
    1673            1127 :         if ((a[byte] & mask) != 0)
    1674              15 :             return false;
    1675            1112 :         mask = 0xff;
    1676            1112 :         byte++;
    1677                 :     }
    1678                 : 
    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
    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
    1716 UBC           0 : inet_client_addr(PG_FUNCTION_ARGS)
    1717                 : {
    1718               0 :     Port       *port = MyProcPort;
    1719                 :     char        remote_host[NI_MAXHOST];
    1720                 :     int         ret;
    1721                 : 
    1722               0 :     if (port == NULL)
    1723               0 :         PG_RETURN_NULL();
    1724                 : 
    1725               0 :     switch (port->raddr.addr.ss_family)
    1726                 :     {
    1727               0 :         case AF_INET:
    1728 EUB             :         case AF_INET6:
    1729 UBC           0 :             break;
    1730 UIC           0 :         default:
    1731               0 :             PG_RETURN_NULL();
    1732 EUB             :     }
    1733                 : 
    1734 UBC           0 :     remote_host[0] = '\0';
    1735                 : 
    1736 UIC           0 :     ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
    1737                 :                              remote_host, sizeof(remote_host),
    1738 EUB             :                              NULL, 0,
    1739                 :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1740 UIC           0 :     if (ret != 0)
    1741 UBC           0 :         PG_RETURN_NULL();
    1742                 : 
    1743               0 :     clean_ipv6_addr(port->raddr.addr.ss_family, remote_host);
    1744                 : 
    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)
    1751 EUB             :  */
    1752                 : Datum
    1753 UBC           0 : inet_client_port(PG_FUNCTION_ARGS)
    1754                 : {
    1755 UIC           0 :     Port       *port = MyProcPort;
    1756                 :     char        remote_port[NI_MAXSERV];
    1757 EUB             :     int         ret;
    1758                 : 
    1759 UIC           0 :     if (port == NULL)
    1760 UBC           0 :         PG_RETURN_NULL();
    1761                 : 
    1762               0 :     switch (port->raddr.addr.ss_family)
    1763                 :     {
    1764               0 :         case AF_INET:
    1765 EUB             :         case AF_INET6:
    1766 UIC           0 :             break;
    1767 UBC           0 :         default:
    1768 UIC           0 :             PG_RETURN_NULL();
    1769 EUB             :     }
    1770                 : 
    1771 UIC           0 :     remote_port[0] = '\0';
    1772                 : 
    1773 UBC           0 :     ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
    1774 EUB             :                              NULL, 0,
    1775                 :                              remote_port, sizeof(remote_port),
    1776                 :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1777 UIC           0 :     if (ret != 0)
    1778               0 :         PG_RETURN_NULL();
    1779                 : 
    1780               0 :     PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
    1781                 : }
    1782                 : 
    1783                 : 
    1784 EUB             : /*
    1785                 :  * IP address that the server accepted the connection on (NULL if Unix socket)
    1786                 :  */
    1787                 : Datum
    1788 UIC           0 : inet_server_addr(PG_FUNCTION_ARGS)
    1789                 : {
    1790 UBC           0 :     Port       *port = MyProcPort;
    1791 EUB             :     char        local_host[NI_MAXHOST];
    1792                 :     int         ret;
    1793                 : 
    1794 UIC           0 :     if (port == NULL)
    1795 UBC           0 :         PG_RETURN_NULL();
    1796                 : 
    1797               0 :     switch (port->laddr.addr.ss_family)
    1798 EUB             :     {
    1799 UBC           0 :         case AF_INET:
    1800                 :         case AF_INET6:
    1801 UIC           0 :             break;
    1802 UBC           0 :         default:
    1803 UIC           0 :             PG_RETURN_NULL();
    1804                 :     }
    1805                 : 
    1806 UBC           0 :     local_host[0] = '\0';
    1807 EUB             : 
    1808 UIC           0 :     ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
    1809 EUB             :                              local_host, sizeof(local_host),
    1810                 :                              NULL, 0,
    1811                 :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1812 UIC           0 :     if (ret != 0)
    1813               0 :         PG_RETURN_NULL();
    1814                 : 
    1815               0 :     clean_ipv6_addr(port->laddr.addr.ss_family, local_host);
    1816                 : 
    1817 UNC           0 :     PG_RETURN_INET_P(network_in(local_host, false, NULL));
    1818                 : }
    1819 EUB             : 
    1820                 : 
    1821                 : /*
    1822                 :  * port that the server accepted the connection on (NULL if Unix socket)
    1823                 :  */
    1824                 : Datum
    1825 UBC           0 : inet_server_port(PG_FUNCTION_ARGS)
    1826 EUB             : {
    1827 UIC           0 :     Port       *port = MyProcPort;
    1828 EUB             :     char        local_port[NI_MAXSERV];
    1829                 :     int         ret;
    1830                 : 
    1831 UIC           0 :     if (port == NULL)
    1832 UBC           0 :         PG_RETURN_NULL();
    1833 EUB             : 
    1834 UBC           0 :     switch (port->laddr.addr.ss_family)
    1835                 :     {
    1836 UIC           0 :         case AF_INET:
    1837                 :         case AF_INET6:
    1838               0 :             break;
    1839               0 :         default:
    1840               0 :             PG_RETURN_NULL();
    1841 EUB             :     }
    1842                 : 
    1843 UIC           0 :     local_port[0] = '\0';
    1844 EUB             : 
    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);
    1849 LBC           0 :     if (ret != 0)
    1850 UIC           0 :         PG_RETURN_NULL();
    1851 ECB             : 
    1852 UIC           0 :     PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
    1853                 : }
    1854 ECB             : 
    1855                 : 
    1856                 : Datum
    1857 CBC          51 : inetnot(PG_FUNCTION_ARGS)
    1858 ECB             : {
    1859 CBC          51 :     inet       *ip = PG_GETARG_INET_PP(0);
    1860                 :     inet       *dst;
    1861 ECB             : 
    1862 CBC          51 :     dst = (inet *) palloc0(sizeof(inet));
    1863                 : 
    1864 ECB             :     {
    1865 GIC          51 :         int         nb = ip_addrsize(ip);
    1866 CBC          51 :         unsigned char *pip = ip_addr(ip);
    1867              51 :         unsigned char *pdst = ip_addr(dst);
    1868                 : 
    1869             363 :         while (--nb >= 0)
    1870 GIC         312 :             pdst[nb] = ~pip[nb];
    1871                 :     }
    1872              51 :     ip_bits(dst) = ip_bits(ip);
    1873                 : 
    1874 CBC          51 :     ip_family(dst) = ip_family(ip);
    1875 GIC          51 :     SET_INET_VARSIZE(dst);
    1876 ECB             : 
    1877 CBC          51 :     PG_RETURN_INET_P(dst);
    1878                 : }
    1879                 : 
    1880 ECB             : 
    1881                 : Datum
    1882 CBC          51 : inetand(PG_FUNCTION_ARGS)
    1883 EUB             : {
    1884 GIC          51 :     inet       *ip = PG_GETARG_INET_PP(0);
    1885              51 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    1886                 :     inet       *dst;
    1887                 : 
    1888 CBC          51 :     dst = (inet *) palloc0(sizeof(inet));
    1889 ECB             : 
    1890 CBC          51 :     if (ip_family(ip) != ip_family(ip2))
    1891 LBC           0 :         ereport(ERROR,
    1892                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1893 ECB             :                  errmsg("cannot AND inet values of different sizes")));
    1894                 :     else
    1895                 :     {
    1896 CBC          51 :         int         nb = ip_addrsize(ip);
    1897 GIC          51 :         unsigned char *pip = ip_addr(ip);
    1898 CBC          51 :         unsigned char *pip2 = ip_addr(ip2);
    1899              51 :         unsigned char *pdst = ip_addr(dst);
    1900                 : 
    1901             363 :         while (--nb >= 0)
    1902 GIC         312 :             pdst[nb] = pip[nb] & pip2[nb];
    1903                 :     }
    1904              51 :     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
    1905                 : 
    1906 CBC          51 :     ip_family(dst) = ip_family(ip);
    1907 GIC          51 :     SET_INET_VARSIZE(dst);
    1908 ECB             : 
    1909 CBC          51 :     PG_RETURN_INET_P(dst);
    1910                 : }
    1911                 : 
    1912 ECB             : 
    1913                 : Datum
    1914 CBC          51 : inetor(PG_FUNCTION_ARGS)
    1915 EUB             : {
    1916 GIC          51 :     inet       *ip = PG_GETARG_INET_PP(0);
    1917              51 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    1918                 :     inet       *dst;
    1919                 : 
    1920 CBC          51 :     dst = (inet *) palloc0(sizeof(inet));
    1921 ECB             : 
    1922 CBC          51 :     if (ip_family(ip) != ip_family(ip2))
    1923 LBC           0 :         ereport(ERROR,
    1924                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1925 ECB             :                  errmsg("cannot OR inet values of different sizes")));
    1926                 :     else
    1927                 :     {
    1928 CBC          51 :         int         nb = ip_addrsize(ip);
    1929 GIC          51 :         unsigned char *pip = ip_addr(ip);
    1930 CBC          51 :         unsigned char *pip2 = ip_addr(ip2);
    1931              51 :         unsigned char *pdst = ip_addr(dst);
    1932                 : 
    1933             363 :         while (--nb >= 0)
    1934 GIC         312 :             pdst[nb] = pip[nb] | pip2[nb];
    1935                 :     }
    1936              51 :     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
    1937                 : 
    1938 CBC          51 :     ip_family(dst) = ip_family(ip);
    1939 GIC          51 :     SET_INET_VARSIZE(dst);
    1940                 : 
    1941              51 :     PG_RETURN_INET_P(dst);
    1942 ECB             : }
    1943                 : 
    1944                 : 
    1945                 : static inet *
    1946 CBC        2571 : internal_inetpl(inet *ip, int64 addend)
    1947 ECB             : {
    1948                 :     inet       *dst;
    1949                 : 
    1950 CBC        2571 :     dst = (inet *) palloc0(sizeof(inet));
    1951                 : 
    1952 ECB             :     {
    1953 CBC        2571 :         int         nb = ip_addrsize(ip);
    1954            2571 :         unsigned char *pip = ip_addr(ip);
    1955 GIC        2571 :         unsigned char *pdst = ip_addr(dst);
    1956            2571 :         int         carry = 0;
    1957                 : 
    1958           18687 :         while (--nb >= 0)
    1959                 :         {
    1960           16116 :             carry = pip[nb] + (int) (addend & 0xFF) + carry;
    1961           16116 :             pdst[nb] = (unsigned char) (carry & 0xFF);
    1962           16116 :             carry >>= 8;
    1963                 : 
    1964                 :             /*
    1965 ECB             :              * We have to be careful about right-shifting addend because
    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                 :              */
    1973 GIC       16116 :             addend &= ~((int64) 0xFF);
    1974 CBC       16116 :             addend /= 0x100;
    1975 ECB             :         }
    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.
    1981                 :          */
    1982 CBC        2571 :         if (!((addend == 0 && carry == 0) ||
    1983              63 :               (addend == -1 && carry == 1)))
    1984 GIC           6 :             ereport(ERROR,
    1985 ECB             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1986                 :                      errmsg("result is out of range")));
    1987                 :     }
    1988                 : 
    1989 GIC        2565 :     ip_bits(dst) = ip_bits(ip);
    1990 CBC        2565 :     ip_family(dst) = ip_family(ip);
    1991 GIC        2565 :     SET_INET_VARSIZE(dst);
    1992 ECB             : 
    1993 CBC        2565 :     return dst;
    1994                 : }
    1995 ECB             : 
    1996                 : 
    1997                 : Datum
    1998 GIC        2505 : inetpl(PG_FUNCTION_ARGS)
    1999                 : {
    2000 CBC        2505 :     inet       *ip = PG_GETARG_INET_PP(0);
    2001 GIC        2505 :     int64       addend = PG_GETARG_INT64(1);
    2002 ECB             : 
    2003 CBC        2505 :     PG_RETURN_INET_P(internal_inetpl(ip, addend));
    2004                 : }
    2005 ECB             : 
    2006                 : 
    2007                 : Datum
    2008 GIC          66 : inetmi_int8(PG_FUNCTION_ARGS)
    2009                 : {
    2010 CBC          66 :     inet       *ip = PG_GETARG_INET_PP(0);
    2011 GIC          66 :     int64       addend = PG_GETARG_INT64(1);
    2012 ECB             : 
    2013 CBC          66 :     PG_RETURN_INET_P(internal_inetpl(ip, -addend));
    2014 ECB             : }
    2015                 : 
    2016                 : 
    2017 EUB             : Datum
    2018 GIC          72 : inetmi(PG_FUNCTION_ARGS)
    2019                 : {
    2020              72 :     inet       *ip = PG_GETARG_INET_PP(0);
    2021              72 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    2022              72 :     int64       res = 0;
    2023                 : 
    2024              72 :     if (ip_family(ip) != ip_family(ip2))
    2025 UIC           0 :         ereport(ERROR,
    2026                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2027                 :                  errmsg("cannot subtract inet values of different sizes")));
    2028 ECB             :     else
    2029                 :     {
    2030                 :         /*
    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                 :          */
    2036 GIC          72 :         int         nb = ip_addrsize(ip);
    2037              72 :         int         byte = 0;
    2038 CBC          72 :         unsigned char *pip = ip_addr(ip);
    2039              72 :         unsigned char *pip2 = ip_addr(ip2);
    2040              72 :         int         carry = 1;
    2041                 : 
    2042             636 :         while (--nb >= 0)
    2043                 :         {
    2044                 :             int         lobyte;
    2045                 : 
    2046 GIC         570 :             carry = pip[nb] + (~pip2[nb] & 0xFF) + carry;
    2047             570 :             lobyte = carry & 0xFF;
    2048             570 :             if (byte < sizeof(int64))
    2049                 :             {
    2050             384 :                 res |= ((int64) lobyte) << (byte * 8);
    2051 ECB             :             }
    2052                 :             else
    2053                 :             {
    2054                 :                 /*
    2055                 :                  * Input wider than int64: check for overflow.  All bytes to
    2056                 :                  * the left of what will fit should be 0 or 0xFF, depending on
    2057                 :                  * sign of the now-complete result.
    2058                 :                  */
    2059 GIC         186 :                 if ((res < 0) ? (lobyte != 0xFF) : (lobyte != 0))
    2060               6 :                     ereport(ERROR,
    2061                 :                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    2062                 :                              errmsg("result is out of range")));
    2063                 :             }
    2064 CBC         564 :             carry >>= 8;
    2065             564 :             byte++;
    2066                 :         }
    2067                 : 
    2068 ECB             :         /*
    2069                 :          * If input is narrower than int64, overflow is not possible, but we
    2070                 :          * have to do proper sign extension.
    2071                 :          */
    2072 GIC          66 :         if (carry == 0 && byte < sizeof(int64))
    2073               6 :             res |= ((uint64) (int64) -1) << (byte * 8);
    2074                 :     }
    2075                 : 
    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,
    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                 :  */
    2094 EUB             : void
    2095 GIC          39 : clean_ipv6_addr(int addr_family, char *addr)
    2096 ECB             : {
    2097 GIC          39 :     if (addr_family == AF_INET6)
    2098                 :     {
    2099              12 :         char       *pct = strchr(addr, '%');
    2100                 : 
    2101              12 :         if (pct)
    2102 UIC           0 :             *pct = '\0';
    2103                 :     }
    2104 GIC          39 : }
        

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