LCOV - code coverage report
Current view: top level - src/backend/utils/adt - network.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 77.4 % 694 537
Test Date: 2026-03-03 15:15:20 Functions: 85.7 % 70 60
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         2538 : network_in(char *src, bool is_cidr, Node *escontext)
      74              : {
      75              :     int         bits;
      76              :     inet       *dst;
      77              : 
      78         2538 :     dst = (inet *) palloc0_object(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         2538 :     if (strchr(src, ':') != NULL)
      87          476 :         ip_family(dst) = PGSQL_AF_INET6;
      88              :     else
      89         2062 :         ip_family(dst) = PGSQL_AF_INET;
      90              : 
      91         3342 :     bits = pg_inet_net_pton(ip_family(dst), src, ip_addr(dst),
      92          804 :                             is_cidr ? ip_addrsize(dst) : -1);
      93         2538 :     if ((bits < 0) || (bits > ip_maxbits(dst)))
      94           15 :         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         2523 :     if (is_cidr)
     104              :     {
     105          795 :         if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
     106           15 :             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         2508 :     ip_bits(dst) = bits;
     113         2508 :     SET_INET_VARSIZE(dst);
     114              : 
     115         2508 :     return dst;
     116              : }
     117              : 
     118              : Datum
     119         1734 : inet_in(PG_FUNCTION_ARGS)
     120              : {
     121         1734 :     char       *src = PG_GETARG_CSTRING(0);
     122              : 
     123         1734 :     PG_RETURN_INET_P(network_in(src, false, fcinfo->context));
     124              : }
     125              : 
     126              : Datum
     127          804 : cidr_in(PG_FUNCTION_ARGS)
     128              : {
     129          804 :     char       *src = PG_GETARG_CSTRING(0);
     130              : 
     131          804 :     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         8295 : 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         8295 :     dst = pg_inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),
     146              :                            tmp, sizeof(tmp));
     147         8295 :     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         8295 :     if (is_cidr && strchr(tmp, '/') == NULL)
     154              :     {
     155          714 :         len = strlen(tmp);
     156          714 :         snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
     157              :     }
     158              : 
     159         8295 :     return pstrdup(tmp);
     160              : }
     161              : 
     162              : Datum
     163         5051 : inet_out(PG_FUNCTION_ARGS)
     164              : {
     165         5051 :     inet       *src = PG_GETARG_INET_PP(0);
     166              : 
     167         5051 :     PG_RETURN_CSTRING(network_out(src, false));
     168              : }
     169              : 
     170              : Datum
     171         3244 : cidr_out(PG_FUNCTION_ARGS)
     172              : {
     173         3244 :     inet       *src = PG_GETARG_INET_PP(0);
     174              : 
     175         3244 :     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 = palloc0_object(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         1770 : inet_to_cidr(PG_FUNCTION_ARGS)
     306              : {
     307         1770 :     inet       *src = PG_GETARG_INET_PP(0);
     308              :     int         bits;
     309              : 
     310         1770 :     bits = ip_bits(src);
     311              : 
     312              :     /* safety check */
     313         1770 :     if ((bits < 0) || (bits > ip_maxbits(src)))
     314            0 :         elog(ERROR, "invalid inet bit length: %d", bits);
     315              : 
     316         1770 :     PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
     317              : }
     318              : 
     319              : Datum
     320          129 : inet_set_masklen(PG_FUNCTION_ARGS)
     321              : {
     322          129 :     inet       *src = PG_GETARG_INET_PP(0);
     323          129 :     int         bits = PG_GETARG_INT32(1);
     324              :     inet       *dst;
     325              : 
     326          129 :     if (bits == -1)
     327           75 :         bits = ip_maxbits(src);
     328              : 
     329          129 :     if ((bits < 0) || (bits > ip_maxbits(src)))
     330            3 :         ereport(ERROR,
     331              :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     332              :                  errmsg("invalid mask length: %d", bits)));
     333              : 
     334              :     /* clone the original data */
     335          126 :     dst = (inet *) palloc(VARSIZE_ANY(src));
     336          126 :     memcpy(dst, src, VARSIZE_ANY(src));
     337              : 
     338          126 :     ip_bits(dst) = bits;
     339              : 
     340          126 :     PG_RETURN_INET_P(dst);
     341              : }
     342              : 
     343              : Datum
     344          105 : cidr_set_masklen(PG_FUNCTION_ARGS)
     345              : {
     346          105 :     inet       *src = PG_GETARG_INET_PP(0);
     347          105 :     int         bits = PG_GETARG_INT32(1);
     348              : 
     349          105 :     if (bits == -1)
     350           51 :         bits = ip_maxbits(src);
     351              : 
     352          105 :     if ((bits < 0) || (bits > ip_maxbits(src)))
     353            3 :         ereport(ERROR,
     354              :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     355              :                  errmsg("invalid mask length: %d", bits)));
     356              : 
     357          102 :     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         1986 : cidr_set_masklen_internal(const inet *src, int bits)
     365              : {
     366         1986 :     inet       *dst = palloc0_object(inet);
     367              : 
     368         1986 :     ip_family(dst) = ip_family(src);
     369         1986 :     ip_bits(dst) = bits;
     370              : 
     371         1986 :     if (bits > 0)
     372              :     {
     373              :         Assert(bits <= ip_maxbits(dst));
     374              : 
     375              :         /* Clone appropriate bytes of the address, leaving the rest 0 */
     376         1986 :         memcpy(ip_addr(dst), ip_addr(src), (bits + 7) / 8);
     377              : 
     378              :         /* Clear any unwanted bits in the last partial byte */
     379         1986 :         if (bits % 8)
     380           30 :             ip_addr(dst)[bits / 8] &= ~(0xFF >> (bits % 8));
     381              :     }
     382              : 
     383              :     /* Set varlena header correctly */
     384         1986 :     SET_INET_VARSIZE(dst);
     385              : 
     386         1986 :     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        74871 : network_cmp_internal(inet *a1, inet *a2)
     402              : {
     403        74871 :     if (ip_family(a1) == ip_family(a2))
     404              :     {
     405              :         int         order;
     406              : 
     407        64658 :         order = bitncmp(ip_addr(a1), ip_addr(a2),
     408        64658 :                         Min(ip_bits(a1), ip_bits(a2)));
     409        64658 :         if (order != 0)
     410        57243 :             return order;
     411         7415 :         order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
     412         7415 :         if (order != 0)
     413          456 :             return order;
     414         6959 :         return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));
     415              :     }
     416              : 
     417        10213 :     return ip_family(a1) - ip_family(a2);
     418              : }
     419              : 
     420              : Datum
     421          134 : network_cmp(PG_FUNCTION_ARGS)
     422              : {
     423          134 :     inet       *a1 = PG_GETARG_INET_PP(0);
     424          134 :     inet       *a2 = PG_GETARG_INET_PP(1);
     425              : 
     426          134 :     PG_RETURN_INT32(network_cmp_internal(a1, a2));
     427              : }
     428              : 
     429              : /*
     430              :  * SortSupport strategy routine
     431              :  */
     432              : Datum
     433          157 : network_sortsupport(PG_FUNCTION_ARGS)
     434              : {
     435          157 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     436              : 
     437          157 :     ssup->comparator = network_fast_cmp;
     438          157 :     ssup->ssup_extra = NULL;
     439              : 
     440          157 :     if (ssup->abbreviate)
     441              :     {
     442              :         network_sortsupport_state *uss;
     443              :         MemoryContext oldcontext;
     444              : 
     445           80 :         oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
     446              : 
     447           80 :         uss = palloc_object(network_sortsupport_state);
     448           80 :         uss->input_count = 0;
     449           80 :         uss->estimating = true;
     450           80 :         initHyperLogLog(&uss->abbr_card, 10);
     451              : 
     452           80 :         ssup->ssup_extra = uss;
     453              : 
     454           80 :         ssup->comparator = ssup_datum_unsigned_cmp;
     455           80 :         ssup->abbrev_converter = network_abbrev_convert;
     456           80 :         ssup->abbrev_abort = network_abbrev_abort;
     457           80 :         ssup->abbrev_full_comparator = network_fast_cmp;
     458              : 
     459           80 :         MemoryContextSwitchTo(oldcontext);
     460              :     }
     461              : 
     462          157 :     PG_RETURN_VOID();
     463              : }
     464              : 
     465              : /*
     466              :  * SortSupport comparison func
     467              :  */
     468              : static int
     469         9766 : network_fast_cmp(Datum x, Datum y, SortSupport ssup)
     470              : {
     471         9766 :     inet       *arg1 = DatumGetInetPP(x);
     472         9766 :     inet       *arg2 = DatumGetInetPP(y);
     473              : 
     474         9766 :     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           21 : network_abbrev_abort(int memtupcount, SortSupport ssup)
     485              : {
     486           21 :     network_sortsupport_state *uss = ssup->ssup_extra;
     487              :     double      abbr_card;
     488              : 
     489           21 :     if (memtupcount < 10000 || uss->input_count < 10000 || !uss->estimating)
     490           21 :         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          774 : network_abbrev_convert(Datum original, SortSupport ssup)
     594              : {
     595          774 :     network_sortsupport_state *uss = ssup->ssup_extra;
     596          774 :     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          774 :     if (ip_family(authoritative) == PGSQL_AF_INET)
     616              :     {
     617              :         uint32      ipaddr_datum32;
     618              : 
     619          585 :         memcpy(&ipaddr_datum32, ip_addr(authoritative), sizeof(uint32));
     620              : 
     621              :         /* Must byteswap on little-endian machines */
     622              : #ifndef WORDS_BIGENDIAN
     623          585 :         ipaddr_datum = pg_bswap32(ipaddr_datum32);
     624              : #else
     625              :         ipaddr_datum = ipaddr_datum32;
     626              : #endif
     627              : 
     628              :         /* Initialize result without setting ipfamily bit */
     629          585 :         res = (Datum) 0;
     630              :     }
     631              :     else
     632              :     {
     633          189 :         memcpy(&ipaddr_datum, ip_addr(authoritative), sizeof(Datum));
     634              : 
     635              :         /* Must byteswap on little-endian machines */
     636          189 :         ipaddr_datum = DatumBigEndianToNative(ipaddr_datum);
     637              : 
     638              :         /* Initialize result with ipfamily (most significant) bit set */
     639          189 :         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          774 :     subnet_size = ip_maxbits(authoritative) - ip_bits(authoritative);
     658              :     Assert(subnet_size >= 0);
     659              :     /* subnet size must work with prefix ipaddr cases */
     660          774 :     subnet_size %= sizeof(Datum) * BITS_PER_BYTE;
     661          774 :     if (ip_bits(authoritative) == 0)
     662              :     {
     663              :         /* Fit as many ipaddr bits as possible into subnet */
     664           84 :         subnet_bitmask = ((Datum) 0) - 1;
     665           84 :         network = 0;
     666              :     }
     667          690 :     else if (ip_bits(authoritative) < sizeof(Datum) * BITS_PER_BYTE)
     668              :     {
     669              :         /* Split ipaddr bits between network and subnet */
     670          585 :         subnet_bitmask = (((Datum) 1) << subnet_size) - 1;
     671          585 :         network = ipaddr_datum & ~subnet_bitmask;
     672              :     }
     673              :     else
     674              :     {
     675              :         /* Fit as many ipaddr bits as possible into network */
     676          105 :         subnet_bitmask = 0;
     677          105 :         network = ipaddr_datum;
     678              :     }
     679              : 
     680          774 :     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          585 :         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          585 :         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          585 :         netmask_size <<= ABBREV_BITS_INET4_SUBNET;
     704              : 
     705              :         /* Extract subnet bits without shifting them */
     706          585 :         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          585 :         if (subnet_size > ABBREV_BITS_INET4_SUBNET)
     719           72 :             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          585 :         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          189 :         res |= network >> 1;
     735              :     }
     736              : 
     737          774 :     uss->input_count += 1;
     738              : 
     739              :     /* Hash abbreviated key */
     740          774 :     if (uss->estimating)
     741              :     {
     742              :         uint32      tmp;
     743              : 
     744          774 :         tmp = DatumGetUInt32(res) ^ (uint32) (DatumGetUInt64(res) >> 32);
     745              : 
     746          774 :         addHyperLogLog(&uss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
     747              :     }
     748              : 
     749          774 :     return res;
     750              : }
     751              : 
     752              : /*
     753              :  *  Boolean ordering tests.
     754              :  */
     755              : Datum
     756        22815 : network_lt(PG_FUNCTION_ARGS)
     757              : {
     758        22815 :     inet       *a1 = PG_GETARG_INET_PP(0);
     759        22815 :     inet       *a2 = PG_GETARG_INET_PP(1);
     760              : 
     761        22815 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) < 0);
     762              : }
     763              : 
     764              : Datum
     765         9430 : network_le(PG_FUNCTION_ARGS)
     766              : {
     767         9430 :     inet       *a1 = PG_GETARG_INET_PP(0);
     768         9430 :     inet       *a2 = PG_GETARG_INET_PP(1);
     769              : 
     770         9430 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) <= 0);
     771              : }
     772              : 
     773              : Datum
     774        11861 : network_eq(PG_FUNCTION_ARGS)
     775              : {
     776        11861 :     inet       *a1 = PG_GETARG_INET_PP(0);
     777        11861 :     inet       *a2 = PG_GETARG_INET_PP(1);
     778              : 
     779        11861 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) == 0);
     780              : }
     781              : 
     782              : Datum
     783         9586 : network_ge(PG_FUNCTION_ARGS)
     784              : {
     785         9586 :     inet       *a1 = PG_GETARG_INET_PP(0);
     786         9586 :     inet       *a2 = PG_GETARG_INET_PP(1);
     787              : 
     788         9586 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) >= 0);
     789              : }
     790              : 
     791              : Datum
     792        11036 : network_gt(PG_FUNCTION_ARGS)
     793              : {
     794        11036 :     inet       *a1 = PG_GETARG_INET_PP(0);
     795        11036 :     inet       *a2 = PG_GETARG_INET_PP(1);
     796              : 
     797        11036 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) > 0);
     798              : }
     799              : 
     800              : Datum
     801           51 : network_ne(PG_FUNCTION_ARGS)
     802              : {
     803           51 :     inet       *a1 = PG_GETARG_INET_PP(0);
     804           51 :     inet       *a2 = PG_GETARG_INET_PP(1);
     805              : 
     806           51 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
     807              : }
     808              : 
     809              : /*
     810              :  * MIN/MAX support functions.
     811              :  */
     812              : Datum
     813           96 : network_smaller(PG_FUNCTION_ARGS)
     814              : {
     815           96 :     inet       *a1 = PG_GETARG_INET_PP(0);
     816           96 :     inet       *a2 = PG_GETARG_INET_PP(1);
     817              : 
     818           96 :     if (network_cmp_internal(a1, a2) < 0)
     819           57 :         PG_RETURN_INET_P(a1);
     820              :     else
     821           39 :         PG_RETURN_INET_P(a2);
     822              : }
     823              : 
     824              : Datum
     825           96 : network_larger(PG_FUNCTION_ARGS)
     826              : {
     827           96 :     inet       *a1 = PG_GETARG_INET_PP(0);
     828           96 :     inet       *a2 = PG_GETARG_INET_PP(1);
     829              : 
     830           96 :     if (network_cmp_internal(a1, a2) > 0)
     831           78 :         PG_RETURN_INET_P(a1);
     832              :     else
     833           18 :         PG_RETURN_INET_P(a2);
     834              : }
     835              : 
     836              : /*
     837              :  * Support function for hash indexes on inet/cidr.
     838              :  */
     839              : Datum
     840         3040 : hashinet(PG_FUNCTION_ARGS)
     841              : {
     842         3040 :     inet       *addr = PG_GETARG_INET_PP(0);
     843         3040 :     int         addrsize = ip_addrsize(addr);
     844              : 
     845              :     /* XXX this assumes there are no pad bytes in the data structure */
     846         3040 :     return hash_any((unsigned char *) VARDATA_ANY(addr), addrsize + 2);
     847              : }
     848              : 
     849              : Datum
     850           30 : hashinetextended(PG_FUNCTION_ARGS)
     851              : {
     852           30 :     inet       *addr = PG_GETARG_INET_PP(0);
     853           30 :     int         addrsize = ip_addrsize(addr);
     854              : 
     855           30 :     return hash_any_extended((unsigned char *) VARDATA_ANY(addr), addrsize + 2,
     856           30 :                              PG_GETARG_INT64(1));
     857              : }
     858              : 
     859              : /*
     860              :  *  Boolean network-inclusion tests.
     861              :  */
     862              : Datum
     863         3066 : network_sub(PG_FUNCTION_ARGS)
     864              : {
     865         3066 :     inet       *a1 = PG_GETARG_INET_PP(0);
     866         3066 :     inet       *a2 = PG_GETARG_INET_PP(1);
     867              : 
     868         3066 :     if (ip_family(a1) == ip_family(a2))
     869              :     {
     870         2466 :         PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2) &&
     871              :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
     872              :     }
     873              : 
     874          600 :     PG_RETURN_BOOL(false);
     875              : }
     876              : 
     877              : Datum
     878         4953 : network_subeq(PG_FUNCTION_ARGS)
     879              : {
     880         4953 :     inet       *a1 = PG_GETARG_INET_PP(0);
     881         4953 :     inet       *a2 = PG_GETARG_INET_PP(1);
     882              : 
     883         4953 :     if (ip_family(a1) == ip_family(a2))
     884              :     {
     885         3069 :         PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2) &&
     886              :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
     887              :     }
     888              : 
     889         1884 :     PG_RETURN_BOOL(false);
     890              : }
     891              : 
     892              : Datum
     893         3090 : network_sup(PG_FUNCTION_ARGS)
     894              : {
     895         3090 :     inet       *a1 = PG_GETARG_INET_PP(0);
     896         3090 :     inet       *a2 = PG_GETARG_INET_PP(1);
     897              : 
     898         3090 :     if (ip_family(a1) == ip_family(a2))
     899              :     {
     900         2490 :         PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2) &&
     901              :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
     902              :     }
     903              : 
     904          600 :     PG_RETURN_BOOL(false);
     905              : }
     906              : 
     907              : Datum
     908         9294 : network_supeq(PG_FUNCTION_ARGS)
     909              : {
     910         9294 :     inet       *a1 = PG_GETARG_INET_PP(0);
     911         9294 :     inet       *a2 = PG_GETARG_INET_PP(1);
     912              : 
     913         9294 :     if (ip_family(a1) == ip_family(a2))
     914              :     {
     915         5124 :         PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2) &&
     916              :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
     917              :     }
     918              : 
     919         4170 :     PG_RETURN_BOOL(false);
     920              : }
     921              : 
     922              : Datum
     923        10515 : network_overlap(PG_FUNCTION_ARGS)
     924              : {
     925        10515 :     inet       *a1 = PG_GETARG_INET_PP(0);
     926        10515 :     inet       *a2 = PG_GETARG_INET_PP(1);
     927              : 
     928        10515 :     if (ip_family(a1) == ip_family(a2))
     929              :     {
     930         6399 :         PG_RETURN_BOOL(bitncmp(ip_addr(a1), ip_addr(a2),
     931              :                                Min(ip_bits(a1), ip_bits(a2))) == 0);
     932              :     }
     933              : 
     934         4116 :     PG_RETURN_BOOL(false);
     935              : }
     936              : 
     937              : /*
     938              :  * Planner support function for network subset/superset operators
     939              :  */
     940              : Datum
     941          744 : network_subset_support(PG_FUNCTION_ARGS)
     942              : {
     943          744 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
     944          744 :     Node       *ret = NULL;
     945              : 
     946          744 :     if (IsA(rawreq, SupportRequestIndexCondition))
     947              :     {
     948              :         /* Try to convert operator/function call to index conditions */
     949           24 :         SupportRequestIndexCondition *req = (SupportRequestIndexCondition *) rawreq;
     950              : 
     951           24 :         if (is_opclause(req->node))
     952              :         {
     953           24 :             OpExpr     *clause = (OpExpr *) req->node;
     954              : 
     955              :             Assert(list_length(clause->args) == 2);
     956              :             ret = (Node *)
     957           24 :                 match_network_function((Node *) linitial(clause->args),
     958           24 :                                        (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          744 :     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           24 : match_network_function(Node *leftop,
     989              :                        Node *rightop,
     990              :                        int indexarg,
     991              :                        Oid funcid,
     992              :                        Oid opfamily)
     993              : {
     994           24 :     switch (funcid)
     995              :     {
     996            6 :         case F_NETWORK_SUB:
     997              :             /* indexkey must be on the left */
     998            6 :             if (indexarg != 0)
     999            0 :                 return NIL;
    1000            6 :             return match_network_subset(leftop, rightop, false, opfamily);
    1001              : 
    1002            6 :         case F_NETWORK_SUBEQ:
    1003              :             /* indexkey must be on the left */
    1004            6 :             if (indexarg != 0)
    1005            0 :                 return NIL;
    1006            6 :             return match_network_subset(leftop, rightop, true, opfamily);
    1007              : 
    1008            6 :         case F_NETWORK_SUP:
    1009              :             /* indexkey must be on the right */
    1010            6 :             if (indexarg != 1)
    1011            0 :                 return NIL;
    1012            6 :             return match_network_subset(rightop, leftop, false, opfamily);
    1013              : 
    1014            6 :         case F_NETWORK_SUPEQ:
    1015              :             /* indexkey must be on the right */
    1016            6 :             if (indexarg != 1)
    1017            0 :                 return NIL;
    1018            6 :             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           24 : match_network_subset(Node *leftop,
    1037              :                      Node *rightop,
    1038              :                      bool is_eq,
    1039              :                      Oid opfamily)
    1040              : {
    1041              :     List       *result;
    1042              :     Datum       rightopval;
    1043           24 :     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           24 :     if (!IsA(rightop, Const) ||
    1058           24 :         ((Const *) rightop)->constisnull)
    1059            0 :         return NIL;
    1060           24 :     rightopval = ((Const *) rightop)->constvalue;
    1061              : 
    1062              :     /*
    1063              :      * create clause "key >= network_scan_first( rightopval )", or ">" if the
    1064              :      * operator disallows equality.
    1065              :      */
    1066           24 :     opr1oid = get_opfamily_member_for_cmptype(opfamily, datatype, datatype, is_eq ? COMPARE_GE : COMPARE_GT);
    1067           24 :     if (opr1oid == InvalidOid)
    1068            0 :         return NIL;
    1069              : 
    1070           24 :     opr1right = network_scan_first(rightopval);
    1071              : 
    1072           24 :     expr = make_opclause(opr1oid, BOOLOID, false,
    1073              :                          (Expr *) leftop,
    1074           24 :                          (Expr *) makeConst(datatype, -1,
    1075              :                                             InvalidOid, /* not collatable */
    1076              :                                             -1, opr1right,
    1077              :                                             false, false),
    1078              :                          InvalidOid, InvalidOid);
    1079           24 :     result = list_make1(expr);
    1080              : 
    1081              :     /* create clause "key <= network_scan_last( rightopval )" */
    1082              : 
    1083           24 :     opr2oid = get_opfamily_member_for_cmptype(opfamily, datatype, datatype, COMPARE_LE);
    1084           24 :     if (opr2oid == InvalidOid)
    1085            0 :         return NIL;
    1086              : 
    1087           24 :     opr2right = network_scan_last(rightopval);
    1088              : 
    1089           24 :     expr = make_opclause(opr2oid, BOOLOID, false,
    1090              :                          (Expr *) leftop,
    1091           24 :                          (Expr *) makeConst(datatype, -1,
    1092              :                                             InvalidOid, /* not collatable */
    1093              :                                             -1, opr2right,
    1094              :                                             false, false),
    1095              :                          InvalidOid, InvalidOid);
    1096           24 :     result = lappend(result, expr);
    1097              : 
    1098           24 :     return result;
    1099              : }
    1100              : 
    1101              : 
    1102              : /*
    1103              :  * Extract data from a network datatype.
    1104              :  */
    1105              : Datum
    1106           51 : network_host(PG_FUNCTION_ARGS)
    1107              : {
    1108           51 :     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           51 :     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           51 :     if ((ptr = strchr(tmp, '/')) != NULL)
    1121            0 :         *ptr = '\0';
    1122              : 
    1123           51 :     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          265 : network_show(PG_FUNCTION_ARGS)
    1133              : {
    1134          265 :     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          265 :     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          265 :     if (strchr(tmp, '/') == NULL)
    1146              :     {
    1147          265 :         len = strlen(tmp);
    1148          265 :         snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
    1149              :     }
    1150              : 
    1151          265 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1152              : }
    1153              : 
    1154              : Datum
    1155           51 : inet_abbrev(PG_FUNCTION_ARGS)
    1156              : {
    1157           51 :     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           51 :     dst = pg_inet_net_ntop(ip_family(ip), ip_addr(ip),
    1162           51 :                            ip_bits(ip), tmp, sizeof(tmp));
    1163              : 
    1164           51 :     if (dst == NULL)
    1165            0 :         ereport(ERROR,
    1166              :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    1167              :                  errmsg("could not format inet value: %m")));
    1168              : 
    1169           51 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1170              : }
    1171              : 
    1172              : Datum
    1173           51 : cidr_abbrev(PG_FUNCTION_ARGS)
    1174              : {
    1175           51 :     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           51 :     dst = pg_inet_cidr_ntop(ip_family(ip), ip_addr(ip),
    1180           51 :                             ip_bits(ip), tmp, sizeof(tmp));
    1181              : 
    1182           51 :     if (dst == NULL)
    1183            0 :         ereport(ERROR,
    1184              :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    1185              :                  errmsg("could not format cidr value: %m")));
    1186              : 
    1187           51 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1188              : }
    1189              : 
    1190              : Datum
    1191          177 : network_masklen(PG_FUNCTION_ARGS)
    1192              : {
    1193          177 :     inet       *ip = PG_GETARG_INET_PP(0);
    1194              : 
    1195          177 :     PG_RETURN_INT32(ip_bits(ip));
    1196              : }
    1197              : 
    1198              : Datum
    1199           51 : network_family(PG_FUNCTION_ARGS)
    1200              : {
    1201           51 :     inet       *ip = PG_GETARG_INET_PP(0);
    1202              : 
    1203           51 :     switch (ip_family(ip))
    1204              :     {
    1205           42 :         case PGSQL_AF_INET:
    1206           42 :             PG_RETURN_INT32(4);
    1207              :             break;
    1208            9 :         case PGSQL_AF_INET6:
    1209            9 :             PG_RETURN_INT32(6);
    1210              :             break;
    1211            0 :         default:
    1212            0 :             PG_RETURN_INT32(0);
    1213              :             break;
    1214              :     }
    1215              : }
    1216              : 
    1217              : Datum
    1218          126 : network_broadcast(PG_FUNCTION_ARGS)
    1219              : {
    1220          126 :     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          126 :     dst = palloc0_object(inet);
    1231              : 
    1232          126 :     maxbytes = ip_addrsize(ip);
    1233          126 :     bits = ip_bits(ip);
    1234          126 :     a = ip_addr(ip);
    1235          126 :     b = ip_addr(dst);
    1236              : 
    1237          846 :     for (byte = 0; byte < maxbytes; byte++)
    1238              :     {
    1239          720 :         if (bits >= 8)
    1240              :         {
    1241          495 :             mask = 0x00;
    1242          495 :             bits -= 8;
    1243              :         }
    1244          225 :         else if (bits == 0)
    1245          213 :             mask = 0xff;
    1246              :         else
    1247              :         {
    1248           12 :             mask = 0xff >> bits;
    1249           12 :             bits = 0;
    1250              :         }
    1251              : 
    1252          720 :         b[byte] = a[byte] | mask;
    1253              :     }
    1254              : 
    1255          126 :     ip_family(dst) = ip_family(ip);
    1256          126 :     ip_bits(dst) = ip_bits(ip);
    1257          126 :     SET_INET_VARSIZE(dst);
    1258              : 
    1259          126 :     PG_RETURN_INET_P(dst);
    1260              : }
    1261              : 
    1262              : Datum
    1263          126 : network_network(PG_FUNCTION_ARGS)
    1264              : {
    1265          126 :     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          126 :     dst = palloc0_object(inet);
    1275              : 
    1276          126 :     bits = ip_bits(ip);
    1277          126 :     a = ip_addr(ip);
    1278          126 :     b = ip_addr(dst);
    1279              : 
    1280          126 :     byte = 0;
    1281              : 
    1282          633 :     while (bits)
    1283              :     {
    1284          507 :         if (bits >= 8)
    1285              :         {
    1286          495 :             mask = 0xff;
    1287          495 :             bits -= 8;
    1288              :         }
    1289              :         else
    1290              :         {
    1291           12 :             mask = 0xff << (8 - bits);
    1292           12 :             bits = 0;
    1293              :         }
    1294              : 
    1295          507 :         b[byte] = a[byte] & mask;
    1296          507 :         byte++;
    1297              :     }
    1298              : 
    1299          126 :     ip_family(dst) = ip_family(ip);
    1300          126 :     ip_bits(dst) = ip_bits(ip);
    1301          126 :     SET_INET_VARSIZE(dst);
    1302              : 
    1303          126 :     PG_RETURN_INET_P(dst);
    1304              : }
    1305              : 
    1306              : Datum
    1307           51 : network_netmask(PG_FUNCTION_ARGS)
    1308              : {
    1309           51 :     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           51 :     dst = palloc0_object(inet);
    1318              : 
    1319           51 :     bits = ip_bits(ip);
    1320           51 :     b = ip_addr(dst);
    1321              : 
    1322           51 :     byte = 0;
    1323              : 
    1324          237 :     while (bits)
    1325              :     {
    1326          186 :         if (bits >= 8)
    1327              :         {
    1328          180 :             mask = 0xff;
    1329          180 :             bits -= 8;
    1330              :         }
    1331              :         else
    1332              :         {
    1333            6 :             mask = 0xff << (8 - bits);
    1334            6 :             bits = 0;
    1335              :         }
    1336              : 
    1337          186 :         b[byte] = mask;
    1338          186 :         byte++;
    1339              :     }
    1340              : 
    1341           51 :     ip_family(dst) = ip_family(ip);
    1342           51 :     ip_bits(dst) = ip_maxbits(ip);
    1343           51 :     SET_INET_VARSIZE(dst);
    1344              : 
    1345           51 :     PG_RETURN_INET_P(dst);
    1346              : }
    1347              : 
    1348              : Datum
    1349           51 : network_hostmask(PG_FUNCTION_ARGS)
    1350              : {
    1351           51 :     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           51 :     dst = palloc0_object(inet);
    1361              : 
    1362           51 :     maxbytes = ip_addrsize(ip);
    1363           51 :     bits = ip_maxbits(ip) - ip_bits(ip);
    1364           51 :     b = ip_addr(dst);
    1365              : 
    1366           51 :     byte = maxbytes - 1;
    1367              : 
    1368          183 :     while (bits)
    1369              :     {
    1370          132 :         if (bits >= 8)
    1371              :         {
    1372          126 :             mask = 0xff;
    1373          126 :             bits -= 8;
    1374              :         }
    1375              :         else
    1376              :         {
    1377            6 :             mask = 0xff >> (8 - bits);
    1378            6 :             bits = 0;
    1379              :         }
    1380              : 
    1381          132 :         b[byte] = mask;
    1382          132 :         byte--;
    1383              :     }
    1384              : 
    1385           51 :     ip_family(dst) = ip_family(ip);
    1386           51 :     ip_bits(dst) = ip_maxbits(ip);
    1387           51 :     SET_INET_VARSIZE(dst);
    1388              : 
    1389           51 :     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          120 : inet_same_family(PG_FUNCTION_ARGS)
    1398              : {
    1399          120 :     inet       *a1 = PG_GETARG_INET_PP(0);
    1400          120 :     inet       *a2 = PG_GETARG_INET_PP(1);
    1401              : 
    1402          120 :     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          117 : inet_merge(PG_FUNCTION_ARGS)
    1410              : {
    1411          117 :     inet       *a1 = PG_GETARG_INET_PP(0),
    1412          117 :                *a2 = PG_GETARG_INET_PP(1);
    1413              :     int         commonbits;
    1414              : 
    1415          117 :     if (ip_family(a1) != ip_family(a2))
    1416            3 :         ereport(ERROR,
    1417              :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1418              :                  errmsg("cannot merge addresses from different families")));
    1419              : 
    1420          114 :     commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
    1421          114 :                             Min(ip_bits(a1), ip_bits(a2)));
    1422              : 
    1423          114 :     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         5454 : convert_network_to_scalar(Datum value, Oid typid, bool *failure)
    1436              : {
    1437         5454 :     switch (typid)
    1438              :     {
    1439         5454 :         case INETOID:
    1440              :         case CIDROID:
    1441              :             {
    1442         5454 :                 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         5454 :                 if (ip_family(ip) == PGSQL_AF_INET)
    1451         5454 :                     len = 4;
    1452              :                 else
    1453            0 :                     len = 5;
    1454              : 
    1455         5454 :                 res = ip_family(ip);
    1456        27270 :                 for (i = 0; i < len; i++)
    1457              :                 {
    1458        21816 :                     res *= 256;
    1459        21816 :                     res += ip_addr(ip)[i];
    1460              :                 }
    1461         5454 :                 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        91897 : 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        91897 :     b = n / 8;
    1510        91897 :     x = memcmp(l, r, b);
    1511        91897 :     if (x || (n % 8) == 0)
    1512        91776 :         return x;
    1513              : 
    1514          121 :     lb = l[b];
    1515          121 :     rb = r[b];
    1516          206 :     for (b = n % 8; b > 0; b--)
    1517              :     {
    1518          139 :         if (IS_HIGHBIT_SET(lb) != IS_HIGHBIT_SET(rb))
    1519              :         {
    1520           54 :             if (IS_HIGHBIT_SET(lb))
    1521           30 :                 return 1;
    1522           24 :             return -1;
    1523              :         }
    1524           85 :         lb <<= 1;
    1525           85 :         rb <<= 1;
    1526              :     }
    1527           67 :     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         1660 : 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         1660 :     nbits = n % 8;
    1543              : 
    1544              :     /* check whole bytes */
    1545         2165 :     for (byte = 0; byte < n / 8; byte++)
    1546              :     {
    1547          533 :         if (l[byte] != r[byte])
    1548              :         {
    1549              :             /* at least one bit in the last byte is not common */
    1550           28 :             nbits = 7;
    1551           28 :             break;
    1552              :         }
    1553              :     }
    1554              : 
    1555              :     /* check bits in last partial byte */
    1556         1660 :     if (nbits != 0)
    1557              :     {
    1558              :         /* calculate diff of first non-matching bytes */
    1559         1282 :         unsigned int diff = l[byte] ^ r[byte];
    1560              : 
    1561              :         /* compare the bits from the most to the least */
    1562         1512 :         while ((diff >> (8 - nbits)) != 0)
    1563          230 :             nbits--;
    1564              :     }
    1565              : 
    1566         1660 :     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          795 : 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          795 :     if (family == PGSQL_AF_INET)
    1583              :     {
    1584          636 :         maxbits = 32;
    1585          636 :         maxbytes = 4;
    1586              :     }
    1587              :     else
    1588              :     {
    1589          159 :         maxbits = 128;
    1590          159 :         maxbytes = 16;
    1591              :     }
    1592              :     Assert(bits <= maxbits);
    1593              : 
    1594          795 :     if (bits == maxbits)
    1595          325 :         return true;
    1596              : 
    1597          470 :     byte = bits / 8;
    1598              : 
    1599          470 :     nbits = bits % 8;
    1600          470 :     mask = 0xff;
    1601          470 :     if (bits != 0)
    1602          446 :         mask >>= nbits;
    1603              : 
    1604         1723 :     while (byte < maxbytes)
    1605              :     {
    1606         1268 :         if ((a[byte] & mask) != 0)
    1607           15 :             return false;
    1608         1253 :         mask = 0xff;
    1609         1253 :         byte++;
    1610              :     }
    1611              : 
    1612          455 :     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           24 : network_scan_first(Datum in)
    1624              : {
    1625           24 :     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           24 : network_scan_last(Datum in)
    1638              : {
    1639           24 :     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           51 : inetnot(PG_FUNCTION_ARGS)
    1791              : {
    1792           51 :     inet       *ip = PG_GETARG_INET_PP(0);
    1793              :     inet       *dst;
    1794              : 
    1795           51 :     dst = palloc0_object(inet);
    1796              : 
    1797              :     {
    1798           51 :         int         nb = ip_addrsize(ip);
    1799           51 :         unsigned char *pip = ip_addr(ip);
    1800           51 :         unsigned char *pdst = ip_addr(dst);
    1801              : 
    1802          363 :         while (--nb >= 0)
    1803          312 :             pdst[nb] = ~pip[nb];
    1804              :     }
    1805           51 :     ip_bits(dst) = ip_bits(ip);
    1806              : 
    1807           51 :     ip_family(dst) = ip_family(ip);
    1808           51 :     SET_INET_VARSIZE(dst);
    1809              : 
    1810           51 :     PG_RETURN_INET_P(dst);
    1811              : }
    1812              : 
    1813              : 
    1814              : Datum
    1815           51 : inetand(PG_FUNCTION_ARGS)
    1816              : {
    1817           51 :     inet       *ip = PG_GETARG_INET_PP(0);
    1818           51 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    1819              :     inet       *dst;
    1820              : 
    1821           51 :     dst = palloc0_object(inet);
    1822              : 
    1823           51 :     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           51 :         int         nb = ip_addrsize(ip);
    1830           51 :         unsigned char *pip = ip_addr(ip);
    1831           51 :         unsigned char *pip2 = ip_addr(ip2);
    1832           51 :         unsigned char *pdst = ip_addr(dst);
    1833              : 
    1834          363 :         while (--nb >= 0)
    1835          312 :             pdst[nb] = pip[nb] & pip2[nb];
    1836              :     }
    1837           51 :     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
    1838              : 
    1839           51 :     ip_family(dst) = ip_family(ip);
    1840           51 :     SET_INET_VARSIZE(dst);
    1841              : 
    1842           51 :     PG_RETURN_INET_P(dst);
    1843              : }
    1844              : 
    1845              : 
    1846              : Datum
    1847           51 : inetor(PG_FUNCTION_ARGS)
    1848              : {
    1849           51 :     inet       *ip = PG_GETARG_INET_PP(0);
    1850           51 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    1851              :     inet       *dst;
    1852              : 
    1853           51 :     dst = palloc0_object(inet);
    1854              : 
    1855           51 :     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           51 :         int         nb = ip_addrsize(ip);
    1862           51 :         unsigned char *pip = ip_addr(ip);
    1863           51 :         unsigned char *pip2 = ip_addr(ip2);
    1864           51 :         unsigned char *pdst = ip_addr(dst);
    1865              : 
    1866          363 :         while (--nb >= 0)
    1867          312 :             pdst[nb] = pip[nb] | pip2[nb];
    1868              :     }
    1869           51 :     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
    1870              : 
    1871           51 :     ip_family(dst) = ip_family(ip);
    1872           51 :     SET_INET_VARSIZE(dst);
    1873              : 
    1874           51 :     PG_RETURN_INET_P(dst);
    1875              : }
    1876              : 
    1877              : 
    1878              : static inet *
    1879         2571 : internal_inetpl(inet *ip, int64 addend)
    1880              : {
    1881              :     inet       *dst;
    1882              : 
    1883         2571 :     dst = palloc0_object(inet);
    1884              : 
    1885              :     {
    1886         2571 :         int         nb = ip_addrsize(ip);
    1887         2571 :         unsigned char *pip = ip_addr(ip);
    1888         2571 :         unsigned char *pdst = ip_addr(dst);
    1889         2571 :         int         carry = 0;
    1890              : 
    1891        18687 :         while (--nb >= 0)
    1892              :         {
    1893        16116 :             carry = pip[nb] + (int) (addend & 0xFF) + carry;
    1894        16116 :             pdst[nb] = (unsigned char) (carry & 0xFF);
    1895        16116 :             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        16116 :             addend &= ~((int64) 0xFF);
    1907        16116 :             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         2571 :         if (!((addend == 0 && carry == 0) ||
    1916           63 :               (addend == -1 && carry == 1)))
    1917            6 :             ereport(ERROR,
    1918              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1919              :                      errmsg("result is out of range")));
    1920              :     }
    1921              : 
    1922         2565 :     ip_bits(dst) = ip_bits(ip);
    1923         2565 :     ip_family(dst) = ip_family(ip);
    1924         2565 :     SET_INET_VARSIZE(dst);
    1925              : 
    1926         2565 :     return dst;
    1927              : }
    1928              : 
    1929              : 
    1930              : Datum
    1931         2505 : inetpl(PG_FUNCTION_ARGS)
    1932              : {
    1933         2505 :     inet       *ip = PG_GETARG_INET_PP(0);
    1934         2505 :     int64       addend = PG_GETARG_INT64(1);
    1935              : 
    1936         2505 :     PG_RETURN_INET_P(internal_inetpl(ip, addend));
    1937              : }
    1938              : 
    1939              : 
    1940              : Datum
    1941           66 : inetmi_int8(PG_FUNCTION_ARGS)
    1942              : {
    1943           66 :     inet       *ip = PG_GETARG_INET_PP(0);
    1944           66 :     int64       addend = PG_GETARG_INT64(1);
    1945              : 
    1946           66 :     PG_RETURN_INET_P(internal_inetpl(ip, -addend));
    1947              : }
    1948              : 
    1949              : 
    1950              : Datum
    1951           72 : inetmi(PG_FUNCTION_ARGS)
    1952              : {
    1953           72 :     inet       *ip = PG_GETARG_INET_PP(0);
    1954           72 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    1955           72 :     int64       res = 0;
    1956              : 
    1957           72 :     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           72 :         int         nb = ip_addrsize(ip);
    1970           72 :         int         byte = 0;
    1971           72 :         unsigned char *pip = ip_addr(ip);
    1972           72 :         unsigned char *pip2 = ip_addr(ip2);
    1973           72 :         int         carry = 1;
    1974              : 
    1975          636 :         while (--nb >= 0)
    1976              :         {
    1977              :             int         lobyte;
    1978              : 
    1979          570 :             carry = pip[nb] + (~pip2[nb] & 0xFF) + carry;
    1980          570 :             lobyte = carry & 0xFF;
    1981          570 :             if (byte < sizeof(int64))
    1982              :             {
    1983          384 :                 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          186 :                 if ((res < 0) ? (lobyte != 0xFF) : (lobyte != 0))
    1993            6 :                     ereport(ERROR,
    1994              :                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1995              :                              errmsg("result is out of range")));
    1996              :             }
    1997          564 :             carry >>= 8;
    1998          564 :             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           66 :         if (carry == 0 && byte < sizeof(int64))
    2006            6 :             res |= ((uint64) (int64) -1) << (byte * 8);
    2007              :     }
    2008              : 
    2009           66 :     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           69 : clean_ipv6_addr(int addr_family, char *addr)
    2029              : {
    2030           69 :     if (addr_family == AF_INET6)
    2031              :     {
    2032           12 :         char       *pct = strchr(addr, '%');
    2033              : 
    2034           12 :         if (pct)
    2035            0 :             *pct = '\0';
    2036              :     }
    2037           69 : }
        

Generated by: LCOV version 2.0-1