LCOV - code coverage report
Current view: top level - src/backend/utils/adt - network.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 489 702 69.7 %
Date: 2024-05-09 16:10:48 Functions: 56 70 80.0 %
Legend: Lines: hit not hit

          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        4682 : network_in(char *src, bool is_cidr, Node *escontext)
      76             : {
      77             :     int         bits;
      78             :     inet       *dst;
      79             : 
      80        4682 :     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        4682 :     if (strchr(src, ':') != NULL)
      89         898 :         ip_family(dst) = PGSQL_AF_INET6;
      90             :     else
      91        3784 :         ip_family(dst) = PGSQL_AF_INET;
      92             : 
      93        6080 :     bits = pg_inet_net_pton(ip_family(dst), src, ip_addr(dst),
      94        1398 :                             is_cidr ? ip_addrsize(dst) : -1);
      95        4682 :     if ((bits < 0) || (bits > ip_maxbits(dst)))
      96          30 :         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        4652 :     if (is_cidr)
     106             :     {
     107        1380 :         if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
     108          30 :             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        4622 :     ip_bits(dst) = bits;
     115        4622 :     SET_INET_VARSIZE(dst);
     116             : 
     117        4622 :     return dst;
     118             : }
     119             : 
     120             : Datum
     121        3284 : inet_in(PG_FUNCTION_ARGS)
     122             : {
     123        3284 :     char       *src = PG_GETARG_CSTRING(0);
     124             : 
     125        3284 :     PG_RETURN_INET_P(network_in(src, false, fcinfo->context));
     126             : }
     127             : 
     128             : Datum
     129        1398 : cidr_in(PG_FUNCTION_ARGS)
     130             : {
     131        1398 :     char       *src = PG_GETARG_CSTRING(0);
     132             : 
     133        1398 :     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       14078 : 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       14078 :     dst = pg_inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),
     148             :                            tmp, sizeof(tmp));
     149       14078 :     if (dst == NULL)
     150           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       14078 :     if (is_cidr && strchr(tmp, '/') == NULL)
     156             :     {
     157        1078 :         len = strlen(tmp);
     158        1078 :         snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
     159             :     }
     160             : 
     161       14078 :     return pstrdup(tmp);
     162             : }
     163             : 
     164             : Datum
     165        8478 : inet_out(PG_FUNCTION_ARGS)
     166             : {
     167        8478 :     inet       *src = PG_GETARG_INET_PP(0);
     168             : 
     169        8478 :     PG_RETURN_CSTRING(network_out(src, false));
     170             : }
     171             : 
     172             : Datum
     173        5600 : cidr_out(PG_FUNCTION_ARGS)
     174             : {
     175        5600 :     inet       *src = PG_GETARG_INET_PP(0);
     176             : 
     177        5600 :     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           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        3540 : inet_to_cidr(PG_FUNCTION_ARGS)
     310             : {
     311        3540 :     inet       *src = PG_GETARG_INET_PP(0);
     312             :     int         bits;
     313             : 
     314        3540 :     bits = ip_bits(src);
     315             : 
     316             :     /* safety check */
     317        3540 :     if ((bits < 0) || (bits > ip_maxbits(src)))
     318           0 :         elog(ERROR, "invalid inet bit length: %d", bits);
     319             : 
     320        3540 :     PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
     321             : }
     322             : 
     323             : Datum
     324         150 : inet_set_masklen(PG_FUNCTION_ARGS)
     325             : {
     326         150 :     inet       *src = PG_GETARG_INET_PP(0);
     327         150 :     int         bits = PG_GETARG_INT32(1);
     328             :     inet       *dst;
     329             : 
     330         150 :     if (bits == -1)
     331          48 :         bits = ip_maxbits(src);
     332             : 
     333         150 :     if ((bits < 0) || (bits > ip_maxbits(src)))
     334           0 :         ereport(ERROR,
     335             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     336             :                  errmsg("invalid mask length: %d", bits)));
     337             : 
     338             :     /* clone the original data */
     339         150 :     dst = (inet *) palloc(VARSIZE_ANY(src));
     340         150 :     memcpy(dst, src, VARSIZE_ANY(src));
     341             : 
     342         150 :     ip_bits(dst) = bits;
     343             : 
     344         150 :     PG_RETURN_INET_P(dst);
     345             : }
     346             : 
     347             : Datum
     348           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        3768 : cidr_set_masklen_internal(const inet *src, int bits)
     369             : {
     370        3768 :     inet       *dst = (inet *) palloc0(sizeof(inet));
     371             : 
     372        3768 :     ip_family(dst) = ip_family(src);
     373        3768 :     ip_bits(dst) = bits;
     374             : 
     375        3768 :     if (bits > 0)
     376             :     {
     377             :         Assert(bits <= ip_maxbits(dst));
     378             : 
     379             :         /* Clone appropriate bytes of the address, leaving the rest 0 */
     380        3768 :         memcpy(ip_addr(dst), ip_addr(src), (bits + 7) / 8);
     381             : 
     382             :         /* Clear any unwanted bits in the last partial byte */
     383        3768 :         if (bits % 8)
     384          60 :             ip_addr(dst)[bits / 8] &= ~(0xFF >> (bits % 8));
     385             :     }
     386             : 
     387             :     /* Set varlena header correctly */
     388        3768 :     SET_INET_VARSIZE(dst);
     389             : 
     390        3768 :     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      141974 : network_cmp_internal(inet *a1, inet *a2)
     406             : {
     407      141974 :     if (ip_family(a1) == ip_family(a2))
     408             :     {
     409             :         int         order;
     410             : 
     411      122180 :         order = bitncmp(ip_addr(a1), ip_addr(a2),
     412      122180 :                         Min(ip_bits(a1), ip_bits(a2)));
     413      122180 :         if (order != 0)
     414      108498 :             return order;
     415       13682 :         order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
     416       13682 :         if (order != 0)
     417         780 :             return order;
     418       12902 :         return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));
     419             :     }
     420             : 
     421       19794 :     return ip_family(a1) - ip_family(a2);
     422             : }
     423             : 
     424             : Datum
     425         268 : network_cmp(PG_FUNCTION_ARGS)
     426             : {
     427         268 :     inet       *a1 = PG_GETARG_INET_PP(0);
     428         268 :     inet       *a2 = PG_GETARG_INET_PP(1);
     429             : 
     430         268 :     PG_RETURN_INT32(network_cmp_internal(a1, a2));
     431             : }
     432             : 
     433             : /*
     434             :  * SortSupport strategy routine
     435             :  */
     436             : Datum
     437         306 : network_sortsupport(PG_FUNCTION_ARGS)
     438             : {
     439         306 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     440             : 
     441         306 :     ssup->comparator = network_fast_cmp;
     442         306 :     ssup->ssup_extra = NULL;
     443             : 
     444         306 :     if (ssup->abbreviate)
     445             :     {
     446             :         network_sortsupport_state *uss;
     447             :         MemoryContext oldcontext;
     448             : 
     449         160 :         oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
     450             : 
     451         160 :         uss = palloc(sizeof(network_sortsupport_state));
     452         160 :         uss->input_count = 0;
     453         160 :         uss->estimating = true;
     454         160 :         initHyperLogLog(&uss->abbr_card, 10);
     455             : 
     456         160 :         ssup->ssup_extra = uss;
     457             : 
     458         160 :         ssup->comparator = ssup_datum_unsigned_cmp;
     459         160 :         ssup->abbrev_converter = network_abbrev_convert;
     460         160 :         ssup->abbrev_abort = network_abbrev_abort;
     461         160 :         ssup->abbrev_full_comparator = network_fast_cmp;
     462             : 
     463         160 :         MemoryContextSwitchTo(oldcontext);
     464             :     }
     465             : 
     466         306 :     PG_RETURN_VOID();
     467             : }
     468             : 
     469             : /*
     470             :  * SortSupport comparison func
     471             :  */
     472             : static int
     473       11956 : network_fast_cmp(Datum x, Datum y, SortSupport ssup)
     474             : {
     475       11956 :     inet       *arg1 = DatumGetInetPP(x);
     476       11956 :     inet       *arg2 = DatumGetInetPP(y);
     477             : 
     478       11956 :     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          42 : network_abbrev_abort(int memtupcount, SortSupport ssup)
     489             : {
     490          42 :     network_sortsupport_state *uss = ssup->ssup_extra;
     491             :     double      abbr_card;
     492             : 
     493          42 :     if (memtupcount < 10000 || uss->input_count < 10000 || !uss->estimating)
     494          42 :         return false;
     495             : 
     496           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        1548 : network_abbrev_convert(Datum original, SortSupport ssup)
     626             : {
     627        1548 :     network_sortsupport_state *uss = ssup->ssup_extra;
     628        1548 :     inet       *authoritative = DatumGetInetPP(original);
     629             :     Datum       res,
     630             :                 ipaddr_datum,
     631             :                 subnet_bitmask,
     632             :                 network;
     633             :     int         subnet_size;
     634             : 
     635             :     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        1548 :     if (ip_family(authoritative) == PGSQL_AF_INET)
     649             :     {
     650             :         uint32      ipaddr_datum32;
     651             : 
     652        1170 :         memcpy(&ipaddr_datum32, ip_addr(authoritative), sizeof(uint32));
     653             : 
     654             :         /* Must byteswap on little-endian machines */
     655             : #ifndef WORDS_BIGENDIAN
     656        1170 :         ipaddr_datum = pg_bswap32(ipaddr_datum32);
     657             : #else
     658             :         ipaddr_datum = ipaddr_datum32;
     659             : #endif
     660             : 
     661             :         /* Initialize result without setting ipfamily bit */
     662        1170 :         res = (Datum) 0;
     663             :     }
     664             :     else
     665             :     {
     666         378 :         memcpy(&ipaddr_datum, ip_addr(authoritative), sizeof(Datum));
     667             : 
     668             :         /* Must byteswap on little-endian machines */
     669         378 :         ipaddr_datum = DatumBigEndianToNative(ipaddr_datum);
     670             : 
     671             :         /* Initialize result with ipfamily (most significant) bit set */
     672         378 :         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        1548 :     subnet_size = ip_maxbits(authoritative) - ip_bits(authoritative);
     692             :     Assert(subnet_size >= 0);
     693             :     /* subnet size must work with prefix ipaddr cases */
     694        1548 :     subnet_size %= SIZEOF_DATUM * BITS_PER_BYTE;
     695        1548 :     if (ip_bits(authoritative) == 0)
     696             :     {
     697             :         /* Fit as many ipaddr bits as possible into subnet */
     698         168 :         subnet_bitmask = ((Datum) 0) - 1;
     699         168 :         network = 0;
     700             :     }
     701        1380 :     else if (ip_bits(authoritative) < SIZEOF_DATUM * BITS_PER_BYTE)
     702             :     {
     703             :         /* Split ipaddr bits between network and subnet */
     704        1170 :         subnet_bitmask = (((Datum) 1) << subnet_size) - 1;
     705        1170 :         network = ipaddr_datum & ~subnet_bitmask;
     706             :     }
     707             :     else
     708             :     {
     709             :         /* Fit as many ipaddr bits as possible into network */
     710         210 :         subnet_bitmask = 0;
     711         210 :         network = ipaddr_datum;
     712             :     }
     713             : 
     714             : #if SIZEOF_DATUM == 8
     715        1548 :     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        1170 :         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        1170 :         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        1170 :         netmask_size <<= ABBREV_BITS_INET4_SUBNET;
     739             : 
     740             :         /* Extract subnet bits without shifting them */
     741        1170 :         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        1170 :         if (subnet_size > ABBREV_BITS_INET4_SUBNET)
     754         144 :             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        1170 :         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         378 :         res |= network >> 1;
     771             :     }
     772             : 
     773        1548 :     uss->input_count += 1;
     774             : 
     775             :     /* Hash abbreviated key */
     776        1548 :     if (uss->estimating)
     777             :     {
     778             :         uint32      tmp;
     779             : 
     780             : #if SIZEOF_DATUM == 8
     781        1548 :         tmp = (uint32) res ^ (uint32) ((uint64) res >> 32);
     782             : #else                           /* SIZEOF_DATUM != 8 */
     783             :         tmp = (uint32) res;
     784             : #endif
     785             : 
     786        1548 :         addHyperLogLog(&uss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
     787             :     }
     788             : 
     789        1548 :     return res;
     790             : }
     791             : 
     792             : /*
     793             :  *  Boolean ordering tests.
     794             :  */
     795             : Datum
     796       45586 : network_lt(PG_FUNCTION_ARGS)
     797             : {
     798       45586 :     inet       *a1 = PG_GETARG_INET_PP(0);
     799       45586 :     inet       *a2 = PG_GETARG_INET_PP(1);
     800             : 
     801       45586 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) < 0);
     802             : }
     803             : 
     804             : Datum
     805       18860 : network_le(PG_FUNCTION_ARGS)
     806             : {
     807       18860 :     inet       *a1 = PG_GETARG_INET_PP(0);
     808       18860 :     inet       *a2 = PG_GETARG_INET_PP(1);
     809             : 
     810       18860 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) <= 0);
     811             : }
     812             : 
     813             : Datum
     814       23706 : network_eq(PG_FUNCTION_ARGS)
     815             : {
     816       23706 :     inet       *a1 = PG_GETARG_INET_PP(0);
     817       23706 :     inet       *a2 = PG_GETARG_INET_PP(1);
     818             : 
     819       23706 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) == 0);
     820             : }
     821             : 
     822             : Datum
     823       19100 : network_ge(PG_FUNCTION_ARGS)
     824             : {
     825       19100 :     inet       *a1 = PG_GETARG_INET_PP(0);
     826       19100 :     inet       *a2 = PG_GETARG_INET_PP(1);
     827             : 
     828       19100 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) >= 0);
     829             : }
     830             : 
     831             : Datum
     832       22012 : network_gt(PG_FUNCTION_ARGS)
     833             : {
     834       22012 :     inet       *a1 = PG_GETARG_INET_PP(0);
     835       22012 :     inet       *a2 = PG_GETARG_INET_PP(1);
     836             : 
     837       22012 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) > 0);
     838             : }
     839             : 
     840             : Datum
     841         102 : network_ne(PG_FUNCTION_ARGS)
     842             : {
     843         102 :     inet       *a1 = PG_GETARG_INET_PP(0);
     844         102 :     inet       *a2 = PG_GETARG_INET_PP(1);
     845             : 
     846         102 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
     847             : }
     848             : 
     849             : /*
     850             :  * MIN/MAX support functions.
     851             :  */
     852             : Datum
     853         192 : network_smaller(PG_FUNCTION_ARGS)
     854             : {
     855         192 :     inet       *a1 = PG_GETARG_INET_PP(0);
     856         192 :     inet       *a2 = PG_GETARG_INET_PP(1);
     857             : 
     858         192 :     if (network_cmp_internal(a1, a2) < 0)
     859         114 :         PG_RETURN_INET_P(a1);
     860             :     else
     861          78 :         PG_RETURN_INET_P(a2);
     862             : }
     863             : 
     864             : Datum
     865         192 : network_larger(PG_FUNCTION_ARGS)
     866             : {
     867         192 :     inet       *a1 = PG_GETARG_INET_PP(0);
     868         192 :     inet       *a2 = PG_GETARG_INET_PP(1);
     869             : 
     870         192 :     if (network_cmp_internal(a1, a2) > 0)
     871         156 :         PG_RETURN_INET_P(a1);
     872             :     else
     873          36 :         PG_RETURN_INET_P(a2);
     874             : }
     875             : 
     876             : /*
     877             :  * Support function for hash indexes on inet/cidr.
     878             :  */
     879             : Datum
     880        6072 : hashinet(PG_FUNCTION_ARGS)
     881             : {
     882        6072 :     inet       *addr = PG_GETARG_INET_PP(0);
     883        6072 :     int         addrsize = ip_addrsize(addr);
     884             : 
     885             :     /* XXX this assumes there are no pad bytes in the data structure */
     886        6072 :     return hash_any((unsigned char *) VARDATA_ANY(addr), addrsize + 2);
     887             : }
     888             : 
     889             : Datum
     890          60 : hashinetextended(PG_FUNCTION_ARGS)
     891             : {
     892          60 :     inet       *addr = PG_GETARG_INET_PP(0);
     893          60 :     int         addrsize = ip_addrsize(addr);
     894             : 
     895          60 :     return hash_any_extended((unsigned char *) VARDATA_ANY(addr), addrsize + 2,
     896          60 :                              PG_GETARG_INT64(1));
     897             : }
     898             : 
     899             : /*
     900             :  *  Boolean network-inclusion tests.
     901             :  */
     902             : Datum
     903        6132 : network_sub(PG_FUNCTION_ARGS)
     904             : {
     905        6132 :     inet       *a1 = PG_GETARG_INET_PP(0);
     906        6132 :     inet       *a2 = PG_GETARG_INET_PP(1);
     907             : 
     908        6132 :     if (ip_family(a1) == ip_family(a2))
     909             :     {
     910        4932 :         PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2) &&
     911             :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
     912             :     }
     913             : 
     914        1200 :     PG_RETURN_BOOL(false);
     915             : }
     916             : 
     917             : Datum
     918        9906 : network_subeq(PG_FUNCTION_ARGS)
     919             : {
     920        9906 :     inet       *a1 = PG_GETARG_INET_PP(0);
     921        9906 :     inet       *a2 = PG_GETARG_INET_PP(1);
     922             : 
     923        9906 :     if (ip_family(a1) == ip_family(a2))
     924             :     {
     925        6138 :         PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2) &&
     926             :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
     927             :     }
     928             : 
     929        3768 :     PG_RETURN_BOOL(false);
     930             : }
     931             : 
     932             : Datum
     933        6180 : network_sup(PG_FUNCTION_ARGS)
     934             : {
     935        6180 :     inet       *a1 = PG_GETARG_INET_PP(0);
     936        6180 :     inet       *a2 = PG_GETARG_INET_PP(1);
     937             : 
     938        6180 :     if (ip_family(a1) == ip_family(a2))
     939             :     {
     940        4980 :         PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2) &&
     941             :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
     942             :     }
     943             : 
     944        1200 :     PG_RETURN_BOOL(false);
     945             : }
     946             : 
     947             : Datum
     948       18588 : network_supeq(PG_FUNCTION_ARGS)
     949             : {
     950       18588 :     inet       *a1 = PG_GETARG_INET_PP(0);
     951       18588 :     inet       *a2 = PG_GETARG_INET_PP(1);
     952             : 
     953       18588 :     if (ip_family(a1) == ip_family(a2))
     954             :     {
     955       10248 :         PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2) &&
     956             :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
     957             :     }
     958             : 
     959        8340 :     PG_RETURN_BOOL(false);
     960             : }
     961             : 
     962             : Datum
     963       21030 : network_overlap(PG_FUNCTION_ARGS)
     964             : {
     965       21030 :     inet       *a1 = PG_GETARG_INET_PP(0);
     966       21030 :     inet       *a2 = PG_GETARG_INET_PP(1);
     967             : 
     968       21030 :     if (ip_family(a1) == ip_family(a2))
     969             :     {
     970       12798 :         PG_RETURN_BOOL(bitncmp(ip_addr(a1), ip_addr(a2),
     971             :                                Min(ip_bits(a1), ip_bits(a2))) == 0);
     972             :     }
     973             : 
     974        8232 :     PG_RETURN_BOOL(false);
     975             : }
     976             : 
     977             : /*
     978             :  * Planner support function for network subset/superset operators
     979             :  */
     980             : Datum
     981        1488 : network_subset_support(PG_FUNCTION_ARGS)
     982             : {
     983        1488 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
     984        1488 :     Node       *ret = NULL;
     985             : 
     986        1488 :     if (IsA(rawreq, SupportRequestIndexCondition))
     987             :     {
     988             :         /* Try to convert operator/function call to index conditions */
     989          48 :         SupportRequestIndexCondition *req = (SupportRequestIndexCondition *) rawreq;
     990             : 
     991          48 :         if (is_opclause(req->node))
     992             :         {
     993          48 :             OpExpr     *clause = (OpExpr *) req->node;
     994             : 
     995             :             Assert(list_length(clause->args) == 2);
     996             :             ret = (Node *)
     997          48 :                 match_network_function((Node *) linitial(clause->args),
     998          48 :                                        (Node *) lsecond(clause->args),
     999             :                                        req->indexarg,
    1000             :                                        req->funcid,
    1001             :                                        req->opfamily);
    1002             :         }
    1003           0 :         else if (is_funcclause(req->node))   /* be paranoid */
    1004             :         {
    1005           0 :             FuncExpr   *clause = (FuncExpr *) req->node;
    1006             : 
    1007             :             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        1488 :     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          48 : match_network_function(Node *leftop,
    1029             :                        Node *rightop,
    1030             :                        int indexarg,
    1031             :                        Oid funcid,
    1032             :                        Oid opfamily)
    1033             : {
    1034          48 :     switch (funcid)
    1035             :     {
    1036          12 :         case F_NETWORK_SUB:
    1037             :             /* indexkey must be on the left */
    1038          12 :             if (indexarg != 0)
    1039           0 :                 return NIL;
    1040          12 :             return match_network_subset(leftop, rightop, false, opfamily);
    1041             : 
    1042          12 :         case F_NETWORK_SUBEQ:
    1043             :             /* indexkey must be on the left */
    1044          12 :             if (indexarg != 0)
    1045           0 :                 return NIL;
    1046          12 :             return match_network_subset(leftop, rightop, true, opfamily);
    1047             : 
    1048          12 :         case F_NETWORK_SUP:
    1049             :             /* indexkey must be on the right */
    1050          12 :             if (indexarg != 1)
    1051           0 :                 return NIL;
    1052          12 :             return match_network_subset(rightop, leftop, false, opfamily);
    1053             : 
    1054          12 :         case F_NETWORK_SUPEQ:
    1055             :             /* indexkey must be on the right */
    1056          12 :             if (indexarg != 1)
    1057           0 :                 return NIL;
    1058          12 :             return match_network_subset(rightop, leftop, true, opfamily);
    1059             : 
    1060           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          48 : match_network_subset(Node *leftop,
    1077             :                      Node *rightop,
    1078             :                      bool is_eq,
    1079             :                      Oid opfamily)
    1080             : {
    1081             :     List       *result;
    1082             :     Datum       rightopval;
    1083          48 :     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          48 :     if (!IsA(rightop, Const) ||
    1098          48 :         ((Const *) rightop)->constisnull)
    1099           0 :         return NIL;
    1100          48 :     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          48 :     if (opfamily != NETWORK_BTREE_FAM_OID)
    1111           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          48 :     if (is_eq)
    1122             :     {
    1123          24 :         opr1oid = get_opfamily_member(opfamily, datatype, datatype,
    1124             :                                       BTGreaterEqualStrategyNumber);
    1125          24 :         if (opr1oid == InvalidOid)
    1126           0 :             elog(ERROR, "no >= operator for opfamily %u", opfamily);
    1127             :     }
    1128             :     else
    1129             :     {
    1130          24 :         opr1oid = get_opfamily_member(opfamily, datatype, datatype,
    1131             :                                       BTGreaterStrategyNumber);
    1132          24 :         if (opr1oid == InvalidOid)
    1133           0 :             elog(ERROR, "no > operator for opfamily %u", opfamily);
    1134             :     }
    1135             : 
    1136          48 :     opr1right = network_scan_first(rightopval);
    1137             : 
    1138          48 :     expr = make_opclause(opr1oid, BOOLOID, false,
    1139             :                          (Expr *) leftop,
    1140          48 :                          (Expr *) makeConst(datatype, -1,
    1141             :                                             InvalidOid, /* not collatable */
    1142             :                                             -1, opr1right,
    1143             :                                             false, false),
    1144             :                          InvalidOid, InvalidOid);
    1145          48 :     result = list_make1(expr);
    1146             : 
    1147             :     /* create clause "key <= network_scan_last( rightopval )" */
    1148             : 
    1149          48 :     opr2oid = get_opfamily_member(opfamily, datatype, datatype,
    1150             :                                   BTLessEqualStrategyNumber);
    1151          48 :     if (opr2oid == InvalidOid)
    1152           0 :         elog(ERROR, "no <= operator for opfamily %u", opfamily);
    1153             : 
    1154          48 :     opr2right = network_scan_last(rightopval);
    1155             : 
    1156          48 :     expr = make_opclause(opr2oid, BOOLOID, false,
    1157             :                          (Expr *) leftop,
    1158          48 :                          (Expr *) makeConst(datatype, -1,
    1159             :                                             InvalidOid, /* not collatable */
    1160             :                                             -1, opr2right,
    1161             :                                             false, false),
    1162             :                          InvalidOid, InvalidOid);
    1163          48 :     result = lappend(result, expr);
    1164             : 
    1165          48 :     return result;
    1166             : }
    1167             : 
    1168             : 
    1169             : /*
    1170             :  * Extract data from a network datatype.
    1171             :  */
    1172             : Datum
    1173         102 : network_host(PG_FUNCTION_ARGS)
    1174             : {
    1175         102 :     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         102 :     if (pg_inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
    1181             :                          tmp, sizeof(tmp)) == NULL)
    1182           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         102 :     if ((ptr = strchr(tmp, '/')) != NULL)
    1188           0 :         *ptr = '\0';
    1189             : 
    1190         102 :     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         212 : network_show(PG_FUNCTION_ARGS)
    1200             : {
    1201         212 :     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         212 :     if (pg_inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
    1206             :                          tmp, sizeof(tmp)) == NULL)
    1207           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         212 :     if (strchr(tmp, '/') == NULL)
    1213             :     {
    1214         212 :         len = strlen(tmp);
    1215         212 :         snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
    1216             :     }
    1217             : 
    1218         212 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1219             : }
    1220             : 
    1221             : Datum
    1222           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         102 : cidr_abbrev(PG_FUNCTION_ARGS)
    1241             : {
    1242         102 :     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         102 :     dst = pg_inet_cidr_ntop(ip_family(ip), ip_addr(ip),
    1247         102 :                             ip_bits(ip), tmp, sizeof(tmp));
    1248             : 
    1249         102 :     if (dst == NULL)
    1250           0 :         ereport(ERROR,
    1251             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    1252             :                  errmsg("could not format cidr value: %m")));
    1253             : 
    1254         102 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1255             : }
    1256             : 
    1257             : Datum
    1258         354 : network_masklen(PG_FUNCTION_ARGS)
    1259             : {
    1260         354 :     inet       *ip = PG_GETARG_INET_PP(0);
    1261             : 
    1262         354 :     PG_RETURN_INT32(ip_bits(ip));
    1263             : }
    1264             : 
    1265             : Datum
    1266         102 : network_family(PG_FUNCTION_ARGS)
    1267             : {
    1268         102 :     inet       *ip = PG_GETARG_INET_PP(0);
    1269             : 
    1270         102 :     switch (ip_family(ip))
    1271             :     {
    1272          84 :         case PGSQL_AF_INET:
    1273          84 :             PG_RETURN_INT32(4);
    1274             :             break;
    1275          18 :         case PGSQL_AF_INET6:
    1276          18 :             PG_RETURN_INT32(6);
    1277             :             break;
    1278           0 :         default:
    1279           0 :             PG_RETURN_INT32(0);
    1280             :             break;
    1281             :     }
    1282             : }
    1283             : 
    1284             : Datum
    1285         252 : network_broadcast(PG_FUNCTION_ARGS)
    1286             : {
    1287         252 :     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         252 :     dst = (inet *) palloc0(sizeof(inet));
    1298             : 
    1299         252 :     maxbytes = ip_addrsize(ip);
    1300         252 :     bits = ip_bits(ip);
    1301         252 :     a = ip_addr(ip);
    1302         252 :     b = ip_addr(dst);
    1303             : 
    1304        1692 :     for (byte = 0; byte < maxbytes; byte++)
    1305             :     {
    1306        1440 :         if (bits >= 8)
    1307             :         {
    1308         990 :             mask = 0x00;
    1309         990 :             bits -= 8;
    1310             :         }
    1311         450 :         else if (bits == 0)
    1312         426 :             mask = 0xff;
    1313             :         else
    1314             :         {
    1315          24 :             mask = 0xff >> bits;
    1316          24 :             bits = 0;
    1317             :         }
    1318             : 
    1319        1440 :         b[byte] = a[byte] | mask;
    1320             :     }
    1321             : 
    1322         252 :     ip_family(dst) = ip_family(ip);
    1323         252 :     ip_bits(dst) = ip_bits(ip);
    1324         252 :     SET_INET_VARSIZE(dst);
    1325             : 
    1326         252 :     PG_RETURN_INET_P(dst);
    1327             : }
    1328             : 
    1329             : Datum
    1330         252 : network_network(PG_FUNCTION_ARGS)
    1331             : {
    1332         252 :     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         252 :     dst = (inet *) palloc0(sizeof(inet));
    1342             : 
    1343         252 :     bits = ip_bits(ip);
    1344         252 :     a = ip_addr(ip);
    1345         252 :     b = ip_addr(dst);
    1346             : 
    1347         252 :     byte = 0;
    1348             : 
    1349        1266 :     while (bits)
    1350             :     {
    1351        1014 :         if (bits >= 8)
    1352             :         {
    1353         990 :             mask = 0xff;
    1354         990 :             bits -= 8;
    1355             :         }
    1356             :         else
    1357             :         {
    1358          24 :             mask = 0xff << (8 - bits);
    1359          24 :             bits = 0;
    1360             :         }
    1361             : 
    1362        1014 :         b[byte] = a[byte] & mask;
    1363        1014 :         byte++;
    1364             :     }
    1365             : 
    1366         252 :     ip_family(dst) = ip_family(ip);
    1367         252 :     ip_bits(dst) = ip_bits(ip);
    1368         252 :     SET_INET_VARSIZE(dst);
    1369             : 
    1370         252 :     PG_RETURN_INET_P(dst);
    1371             : }
    1372             : 
    1373             : Datum
    1374           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         240 : inet_same_family(PG_FUNCTION_ARGS)
    1465             : {
    1466         240 :     inet       *a1 = PG_GETARG_INET_PP(0);
    1467         240 :     inet       *a2 = PG_GETARG_INET_PP(1);
    1468             : 
    1469         240 :     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         234 : inet_merge(PG_FUNCTION_ARGS)
    1477             : {
    1478         234 :     inet       *a1 = PG_GETARG_INET_PP(0),
    1479         234 :                *a2 = PG_GETARG_INET_PP(1);
    1480             :     int         commonbits;
    1481             : 
    1482         234 :     if (ip_family(a1) != ip_family(a2))
    1483           6 :         ereport(ERROR,
    1484             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1485             :                  errmsg("cannot merge addresses from different families")));
    1486             : 
    1487         228 :     commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
    1488         228 :                             Min(ip_bits(a1), ip_bits(a2)));
    1489             : 
    1490         228 :     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       10880 : convert_network_to_scalar(Datum value, Oid typid, bool *failure)
    1503             : {
    1504       10880 :     switch (typid)
    1505             :     {
    1506       10880 :         case INETOID:
    1507             :         case CIDROID:
    1508             :             {
    1509       10880 :                 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       10880 :                 if (ip_family(ip) == PGSQL_AF_INET)
    1518       10880 :                     len = 4;
    1519             :                 else
    1520           0 :                     len = 5;
    1521             : 
    1522       10880 :                 res = ip_family(ip);
    1523       54400 :                 for (i = 0; i < len; i++)
    1524             :                 {
    1525       43520 :                     res *= 256;
    1526       43520 :                     res += ip_addr(ip)[i];
    1527             :                 }
    1528       10880 :                 return res;
    1529             :             }
    1530           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      175642 : 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      175642 :     b = n / 8;
    1577      175642 :     x = memcmp(l, r, b);
    1578      175642 :     if (x || (n % 8) == 0)
    1579      175406 :         return x;
    1580             : 
    1581         236 :     lb = l[b];
    1582         236 :     rb = r[b];
    1583         400 :     for (b = n % 8; b > 0; b--)
    1584             :     {
    1585         272 :         if (IS_HIGHBIT_SET(lb) != IS_HIGHBIT_SET(rb))
    1586             :         {
    1587         108 :             if (IS_HIGHBIT_SET(lb))
    1588          60 :                 return 1;
    1589          48 :             return -1;
    1590             :         }
    1591         164 :         lb <<= 1;
    1592         164 :         rb <<= 1;
    1593             :     }
    1594         128 :     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        3320 : 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        3320 :     nbits = n % 8;
    1610             : 
    1611             :     /* check whole bytes */
    1612        4330 :     for (byte = 0; byte < n / 8; byte++)
    1613             :     {
    1614        1066 :         if (l[byte] != r[byte])
    1615             :         {
    1616             :             /* at least one bit in the last byte is not common */
    1617          56 :             nbits = 7;
    1618          56 :             break;
    1619             :         }
    1620             :     }
    1621             : 
    1622             :     /* check bits in last partial byte */
    1623        3320 :     if (nbits != 0)
    1624             :     {
    1625             :         /* calculate diff of first non-matching bytes */
    1626        2564 :         unsigned int diff = l[byte] ^ r[byte];
    1627             : 
    1628             :         /* compare the bits from the most to the least */
    1629        3024 :         while ((diff >> (8 - nbits)) != 0)
    1630         460 :             nbits--;
    1631             :     }
    1632             : 
    1633        3320 :     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        1380 : 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        1380 :     if (family == PGSQL_AF_INET)
    1650             :     {
    1651        1098 :         maxbits = 32;
    1652        1098 :         maxbytes = 4;
    1653             :     }
    1654             :     else
    1655             :     {
    1656         282 :         maxbits = 128;
    1657         282 :         maxbytes = 16;
    1658             :     }
    1659             :     Assert(bits <= maxbits);
    1660             : 
    1661        1380 :     if (bits == maxbits)
    1662         602 :         return true;
    1663             : 
    1664         778 :     byte = bits / 8;
    1665             : 
    1666         778 :     nbits = bits % 8;
    1667         778 :     mask = 0xff;
    1668         778 :     if (bits != 0)
    1669         730 :         mask >>= nbits;
    1670             : 
    1671        3002 :     while (byte < maxbytes)
    1672             :     {
    1673        2254 :         if ((a[byte] & mask) != 0)
    1674          30 :             return false;
    1675        2224 :         mask = 0xff;
    1676        2224 :         byte++;
    1677             :     }
    1678             : 
    1679         748 :     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          48 : network_scan_first(Datum in)
    1691             : {
    1692          48 :     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          48 : network_scan_last(Datum in)
    1705             : {
    1706          48 :     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           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             :         case AF_INET6:
    1729           0 :             break;
    1730           0 :         default:
    1731           0 :             PG_RETURN_NULL();
    1732             :     }
    1733             : 
    1734           0 :     remote_host[0] = '\0';
    1735             : 
    1736           0 :     ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
    1737             :                              remote_host, sizeof(remote_host),
    1738             :                              NULL, 0,
    1739             :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1740           0 :     if (ret != 0)
    1741           0 :         PG_RETURN_NULL();
    1742             : 
    1743           0 :     clean_ipv6_addr(port->raddr.addr.ss_family, remote_host);
    1744             : 
    1745           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             :  */
    1752             : Datum
    1753           0 : inet_client_port(PG_FUNCTION_ARGS)
    1754             : {
    1755           0 :     Port       *port = MyProcPort;
    1756             :     char        remote_port[NI_MAXSERV];
    1757             :     int         ret;
    1758             : 
    1759           0 :     if (port == NULL)
    1760           0 :         PG_RETURN_NULL();
    1761             : 
    1762           0 :     switch (port->raddr.addr.ss_family)
    1763             :     {
    1764           0 :         case AF_INET:
    1765             :         case AF_INET6:
    1766           0 :             break;
    1767           0 :         default:
    1768           0 :             PG_RETURN_NULL();
    1769             :     }
    1770             : 
    1771           0 :     remote_port[0] = '\0';
    1772             : 
    1773           0 :     ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
    1774             :                              NULL, 0,
    1775             :                              remote_port, sizeof(remote_port),
    1776             :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1777           0 :     if (ret != 0)
    1778           0 :         PG_RETURN_NULL();
    1779             : 
    1780           0 :     PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
    1781             : }
    1782             : 
    1783             : 
    1784             : /*
    1785             :  * IP address that the server accepted the connection on (NULL if Unix socket)
    1786             :  */
    1787             : Datum
    1788           0 : inet_server_addr(PG_FUNCTION_ARGS)
    1789             : {
    1790           0 :     Port       *port = MyProcPort;
    1791             :     char        local_host[NI_MAXHOST];
    1792             :     int         ret;
    1793             : 
    1794           0 :     if (port == NULL)
    1795           0 :         PG_RETURN_NULL();
    1796             : 
    1797           0 :     switch (port->laddr.addr.ss_family)
    1798             :     {
    1799           0 :         case AF_INET:
    1800             :         case AF_INET6:
    1801           0 :             break;
    1802           0 :         default:
    1803           0 :             PG_RETURN_NULL();
    1804             :     }
    1805             : 
    1806           0 :     local_host[0] = '\0';
    1807             : 
    1808           0 :     ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
    1809             :                              local_host, sizeof(local_host),
    1810             :                              NULL, 0,
    1811             :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1812           0 :     if (ret != 0)
    1813           0 :         PG_RETURN_NULL();
    1814             : 
    1815           0 :     clean_ipv6_addr(port->laddr.addr.ss_family, local_host);
    1816             : 
    1817           0 :     PG_RETURN_INET_P(network_in(local_host, false, NULL));
    1818             : }
    1819             : 
    1820             : 
    1821             : /*
    1822             :  * port that the server accepted the connection on (NULL if Unix socket)
    1823             :  */
    1824             : Datum
    1825           0 : inet_server_port(PG_FUNCTION_ARGS)
    1826             : {
    1827           0 :     Port       *port = MyProcPort;
    1828             :     char        local_port[NI_MAXSERV];
    1829             :     int         ret;
    1830             : 
    1831           0 :     if (port == NULL)
    1832           0 :         PG_RETURN_NULL();
    1833             : 
    1834           0 :     switch (port->laddr.addr.ss_family)
    1835             :     {
    1836           0 :         case AF_INET:
    1837             :         case AF_INET6:
    1838           0 :             break;
    1839           0 :         default:
    1840           0 :             PG_RETURN_NULL();
    1841             :     }
    1842             : 
    1843           0 :     local_port[0] = '\0';
    1844             : 
    1845           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           0 :     if (ret != 0)
    1850           0 :         PG_RETURN_NULL();
    1851             : 
    1852           0 :     PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
    1853             : }
    1854             : 
    1855             : 
    1856             : Datum
    1857         102 : inetnot(PG_FUNCTION_ARGS)
    1858             : {
    1859         102 :     inet       *ip = PG_GETARG_INET_PP(0);
    1860             :     inet       *dst;
    1861             : 
    1862         102 :     dst = (inet *) palloc0(sizeof(inet));
    1863             : 
    1864             :     {
    1865         102 :         int         nb = ip_addrsize(ip);
    1866         102 :         unsigned char *pip = ip_addr(ip);
    1867         102 :         unsigned char *pdst = ip_addr(dst);
    1868             : 
    1869         726 :         while (--nb >= 0)
    1870         624 :             pdst[nb] = ~pip[nb];
    1871             :     }
    1872         102 :     ip_bits(dst) = ip_bits(ip);
    1873             : 
    1874         102 :     ip_family(dst) = ip_family(ip);
    1875         102 :     SET_INET_VARSIZE(dst);
    1876             : 
    1877         102 :     PG_RETURN_INET_P(dst);
    1878             : }
    1879             : 
    1880             : 
    1881             : Datum
    1882         102 : inetand(PG_FUNCTION_ARGS)
    1883             : {
    1884         102 :     inet       *ip = PG_GETARG_INET_PP(0);
    1885         102 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    1886             :     inet       *dst;
    1887             : 
    1888         102 :     dst = (inet *) palloc0(sizeof(inet));
    1889             : 
    1890         102 :     if (ip_family(ip) != ip_family(ip2))
    1891           0 :         ereport(ERROR,
    1892             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1893             :                  errmsg("cannot AND inet values of different sizes")));
    1894             :     else
    1895             :     {
    1896         102 :         int         nb = ip_addrsize(ip);
    1897         102 :         unsigned char *pip = ip_addr(ip);
    1898         102 :         unsigned char *pip2 = ip_addr(ip2);
    1899         102 :         unsigned char *pdst = ip_addr(dst);
    1900             : 
    1901         726 :         while (--nb >= 0)
    1902         624 :             pdst[nb] = pip[nb] & pip2[nb];
    1903             :     }
    1904         102 :     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
    1905             : 
    1906         102 :     ip_family(dst) = ip_family(ip);
    1907         102 :     SET_INET_VARSIZE(dst);
    1908             : 
    1909         102 :     PG_RETURN_INET_P(dst);
    1910             : }
    1911             : 
    1912             : 
    1913             : Datum
    1914         102 : inetor(PG_FUNCTION_ARGS)
    1915             : {
    1916         102 :     inet       *ip = PG_GETARG_INET_PP(0);
    1917         102 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    1918             :     inet       *dst;
    1919             : 
    1920         102 :     dst = (inet *) palloc0(sizeof(inet));
    1921             : 
    1922         102 :     if (ip_family(ip) != ip_family(ip2))
    1923           0 :         ereport(ERROR,
    1924             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1925             :                  errmsg("cannot OR inet values of different sizes")));
    1926             :     else
    1927             :     {
    1928         102 :         int         nb = ip_addrsize(ip);
    1929         102 :         unsigned char *pip = ip_addr(ip);
    1930         102 :         unsigned char *pip2 = ip_addr(ip2);
    1931         102 :         unsigned char *pdst = ip_addr(dst);
    1932             : 
    1933         726 :         while (--nb >= 0)
    1934         624 :             pdst[nb] = pip[nb] | pip2[nb];
    1935             :     }
    1936         102 :     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
    1937             : 
    1938         102 :     ip_family(dst) = ip_family(ip);
    1939         102 :     SET_INET_VARSIZE(dst);
    1940             : 
    1941         102 :     PG_RETURN_INET_P(dst);
    1942             : }
    1943             : 
    1944             : 
    1945             : static inet *
    1946        5142 : internal_inetpl(inet *ip, int64 addend)
    1947             : {
    1948             :     inet       *dst;
    1949             : 
    1950        5142 :     dst = (inet *) palloc0(sizeof(inet));
    1951             : 
    1952             :     {
    1953        5142 :         int         nb = ip_addrsize(ip);
    1954        5142 :         unsigned char *pip = ip_addr(ip);
    1955        5142 :         unsigned char *pdst = ip_addr(dst);
    1956        5142 :         int         carry = 0;
    1957             : 
    1958       37374 :         while (--nb >= 0)
    1959             :         {
    1960       32232 :             carry = pip[nb] + (int) (addend & 0xFF) + carry;
    1961       32232 :             pdst[nb] = (unsigned char) (carry & 0xFF);
    1962       32232 :             carry >>= 8;
    1963             : 
    1964             :             /*
    1965             :              * 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       32232 :             addend &= ~((int64) 0xFF);
    1974       32232 :             addend /= 0x100;
    1975             :         }
    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        5142 :         if (!((addend == 0 && carry == 0) ||
    1983         126 :               (addend == -1 && carry == 1)))
    1984          12 :             ereport(ERROR,
    1985             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1986             :                      errmsg("result is out of range")));
    1987             :     }
    1988             : 
    1989        5130 :     ip_bits(dst) = ip_bits(ip);
    1990        5130 :     ip_family(dst) = ip_family(ip);
    1991        5130 :     SET_INET_VARSIZE(dst);
    1992             : 
    1993        5130 :     return dst;
    1994             : }
    1995             : 
    1996             : 
    1997             : Datum
    1998        5010 : inetpl(PG_FUNCTION_ARGS)
    1999             : {
    2000        5010 :     inet       *ip = PG_GETARG_INET_PP(0);
    2001        5010 :     int64       addend = PG_GETARG_INT64(1);
    2002             : 
    2003        5010 :     PG_RETURN_INET_P(internal_inetpl(ip, addend));
    2004             : }
    2005             : 
    2006             : 
    2007             : Datum
    2008         132 : inetmi_int8(PG_FUNCTION_ARGS)
    2009             : {
    2010         132 :     inet       *ip = PG_GETARG_INET_PP(0);
    2011         132 :     int64       addend = PG_GETARG_INT64(1);
    2012             : 
    2013         132 :     PG_RETURN_INET_P(internal_inetpl(ip, -addend));
    2014             : }
    2015             : 
    2016             : 
    2017             : Datum
    2018         144 : inetmi(PG_FUNCTION_ARGS)
    2019             : {
    2020         144 :     inet       *ip = PG_GETARG_INET_PP(0);
    2021         144 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    2022         144 :     int64       res = 0;
    2023             : 
    2024         144 :     if (ip_family(ip) != ip_family(ip2))
    2025           0 :         ereport(ERROR,
    2026             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2027             :                  errmsg("cannot subtract inet values of different sizes")));
    2028             :     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         144 :         int         nb = ip_addrsize(ip);
    2037         144 :         int         byte = 0;
    2038         144 :         unsigned char *pip = ip_addr(ip);
    2039         144 :         unsigned char *pip2 = ip_addr(ip2);
    2040         144 :         int         carry = 1;
    2041             : 
    2042        1272 :         while (--nb >= 0)
    2043             :         {
    2044             :             int         lobyte;
    2045             : 
    2046        1140 :             carry = pip[nb] + (~pip2[nb] & 0xFF) + carry;
    2047        1140 :             lobyte = carry & 0xFF;
    2048        1140 :             if (byte < sizeof(int64))
    2049             :             {
    2050         768 :                 res |= ((int64) lobyte) << (byte * 8);
    2051             :             }
    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         372 :                 if ((res < 0) ? (lobyte != 0xFF) : (lobyte != 0))
    2060          12 :                     ereport(ERROR,
    2061             :                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    2062             :                              errmsg("result is out of range")));
    2063             :             }
    2064        1128 :             carry >>= 8;
    2065        1128 :             byte++;
    2066             :         }
    2067             : 
    2068             :         /*
    2069             :          * If input is narrower than int64, overflow is not possible, but we
    2070             :          * have to do proper sign extension.
    2071             :          */
    2072         132 :         if (carry == 0 && byte < sizeof(int64))
    2073          12 :             res |= ((uint64) (int64) -1) << (byte * 8);
    2074             :     }
    2075             : 
    2076         132 :     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             :  * 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             : void
    2095          62 : clean_ipv6_addr(int addr_family, char *addr)
    2096             : {
    2097          62 :     if (addr_family == AF_INET6)
    2098             :     {
    2099          24 :         char       *pct = strchr(addr, '%');
    2100             : 
    2101          24 :         if (pct)
    2102           0 :             *pct = '\0';
    2103             :     }
    2104          62 : }

Generated by: LCOV version 1.14