LCOV - code coverage report
Current view: top level - src/backend/utils/adt - network.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 77.4 % 694 537
Test Date: 2026-07-22 12:15:41 Functions: 85.7 % 70 60
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 65.4 % 422 276

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

Generated by: LCOV version 2.0-1