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

Generated by: LCOV version 1.16