LCOV - code coverage report
Current view: top level - src/backend/utils/adt - network.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 77.1 % 894 689
Test Date: 2026-01-26 10:56:24 Functions: 84.3 % 70 59
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 54.2 % 380 206

             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                 :         609 : network_in(char *src, bool is_cidr, Node *escontext)
      74                 :             : {
      75                 :         609 :         int                     bits;
      76                 :         609 :         inet       *dst;
      77                 :             : 
      78                 :         609 :         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         [ +  + ]:         609 :         if (strchr(src, ':') != NULL)
      87                 :         158 :                 ip_family(dst) = PGSQL_AF_INET6;
      88                 :             :         else
      89                 :         451 :                 ip_family(dst) = PGSQL_AF_INET;
      90                 :             : 
      91                 :        1218 :         bits = pg_inet_net_pton(ip_family(dst), src, ip_addr(dst),
      92         [ +  + ]:         609 :                                                         is_cidr ? ip_addrsize(dst) : -1);
      93   [ +  +  +  + ]:         609 :         if ((bits < 0) || (bits > ip_maxbits(dst)))
      94         [ +  + ]:           6 :                 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         [ +  + ]:         605 :         if (is_cidr)
     104                 :             :         {
     105         [ +  + ]:         259 :                 if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
     106         [ +  + ]:           6 :                         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                 :         253 :         }
     111                 :             : 
     112                 :         599 :         ip_bits(dst) = bits;
     113                 :         599 :         SET_INET_VARSIZE(dst);
     114                 :             : 
     115                 :         599 :         return dst;
     116                 :         607 : }
     117                 :             : 
     118                 :             : Datum
     119                 :         348 : inet_in(PG_FUNCTION_ARGS)
     120                 :             : {
     121                 :         348 :         char       *src = PG_GETARG_CSTRING(0);
     122                 :             : 
     123                 :         696 :         PG_RETURN_INET_P(network_in(src, false, fcinfo->context));
     124                 :         348 : }
     125                 :             : 
     126                 :             : Datum
     127                 :         261 : cidr_in(PG_FUNCTION_ARGS)
     128                 :             : {
     129                 :         261 :         char       *src = PG_GETARG_CSTRING(0);
     130                 :             : 
     131                 :         522 :         PG_RETURN_INET_P(network_in(src, true, fcinfo->context));
     132                 :         261 : }
     133                 :             : 
     134                 :             : 
     135                 :             : /*
     136                 :             :  * Common INET/CIDR output routine
     137                 :             :  */
     138                 :             : static char *
     139                 :        1449 : network_out(inet *src, bool is_cidr)
     140                 :             : {
     141                 :        1449 :         char            tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
     142                 :        1449 :         char       *dst;
     143                 :        1449 :         int                     len;
     144                 :             : 
     145                 :        2898 :         dst = pg_inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),
     146                 :        1449 :                                                    tmp, sizeof(tmp));
     147         [ +  - ]:        1449 :         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   [ +  +  +  + ]:        1449 :         if (is_cidr && strchr(tmp, '/') == NULL)
     154                 :             :         {
     155                 :          95 :                 len = strlen(tmp);
     156                 :          95 :                 snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
     157                 :          95 :         }
     158                 :             : 
     159                 :        2898 :         return pstrdup(tmp);
     160                 :        1449 : }
     161                 :             : 
     162                 :             : Datum
     163                 :         998 : inet_out(PG_FUNCTION_ARGS)
     164                 :             : {
     165                 :         998 :         inet       *src = PG_GETARG_INET_PP(0);
     166                 :             : 
     167                 :        1996 :         PG_RETURN_CSTRING(network_out(src, false));
     168                 :         998 : }
     169                 :             : 
     170                 :             : Datum
     171                 :         451 : cidr_out(PG_FUNCTION_ARGS)
     172                 :             : {
     173                 :         451 :         inet       *src = PG_GETARG_INET_PP(0);
     174                 :             : 
     175                 :         902 :         PG_RETURN_CSTRING(network_out(src, true));
     176                 :         451 : }
     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                 :           0 :         inet       *addr;
     193                 :           0 :         char       *addrptr;
     194                 :           0 :         int                     bits;
     195                 :           0 :         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                 :           0 :         }
     241                 :             : 
     242                 :           0 :         SET_INET_VARSIZE(addr);
     243                 :             : 
     244                 :           0 :         return addr;
     245                 :           0 : }
     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                 :           0 : }
     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                 :           0 : }
     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                 :           0 :         StringInfoData buf;
     271                 :           0 :         char       *addrptr;
     272                 :           0 :         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                 :           0 : }
     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                 :           0 : }
     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                 :           0 : }
     302                 :             : 
     303                 :             : 
     304                 :             : Datum
     305                 :         390 : inet_to_cidr(PG_FUNCTION_ARGS)
     306                 :             : {
     307                 :         390 :         inet       *src = PG_GETARG_INET_PP(0);
     308                 :         390 :         int                     bits;
     309                 :             : 
     310                 :         390 :         bits = ip_bits(src);
     311                 :             : 
     312                 :             :         /* safety check */
     313         [ +  - ]:         390 :         if ((bits < 0) || (bits > ip_maxbits(src)))
     314   [ #  #  #  # ]:           0 :                 elog(ERROR, "invalid inet bit length: %d", bits);
     315                 :             : 
     316                 :         780 :         PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
     317                 :         390 : }
     318                 :             : 
     319                 :             : Datum
     320                 :          43 : inet_set_masklen(PG_FUNCTION_ARGS)
     321                 :             : {
     322                 :          43 :         inet       *src = PG_GETARG_INET_PP(0);
     323                 :          43 :         int                     bits = PG_GETARG_INT32(1);
     324                 :          43 :         inet       *dst;
     325                 :             : 
     326         [ +  + ]:          43 :         if (bits == -1)
     327                 :          25 :                 bits = ip_maxbits(src);
     328                 :             : 
     329         [ +  + ]:          43 :         if ((bits < 0) || (bits > ip_maxbits(src)))
     330   [ +  -  +  - ]:           1 :                 ereport(ERROR,
     331                 :             :                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     332                 :             :                                  errmsg("invalid mask length: %d", bits)));
     333                 :             : 
     334                 :             :         /* clone the original data */
     335                 :          42 :         dst = (inet *) palloc(VARSIZE_ANY(src));
     336                 :          42 :         memcpy(dst, src, VARSIZE_ANY(src));
     337                 :             : 
     338                 :          42 :         ip_bits(dst) = bits;
     339                 :             : 
     340                 :          84 :         PG_RETURN_INET_P(dst);
     341                 :          42 : }
     342                 :             : 
     343                 :             : Datum
     344                 :          35 : cidr_set_masklen(PG_FUNCTION_ARGS)
     345                 :             : {
     346                 :          35 :         inet       *src = PG_GETARG_INET_PP(0);
     347                 :          35 :         int                     bits = PG_GETARG_INT32(1);
     348                 :             : 
     349         [ +  + ]:          35 :         if (bits == -1)
     350                 :          17 :                 bits = ip_maxbits(src);
     351                 :             : 
     352         [ +  + ]:          35 :         if ((bits < 0) || (bits > ip_maxbits(src)))
     353   [ +  -  +  - ]:           1 :                 ereport(ERROR,
     354                 :             :                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     355                 :             :                                  errmsg("invalid mask length: %d", bits)));
     356                 :             : 
     357                 :          68 :         PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
     358                 :          34 : }
     359                 :             : 
     360                 :             : /*
     361                 :             :  * Copy src and set mask length to 'bits' (which must be valid for the family)
     362                 :             :  */
     363                 :             : inet *
     364                 :         462 : cidr_set_masklen_internal(const inet *src, int bits)
     365                 :             : {
     366                 :         462 :         inet       *dst = palloc0_object(inet);
     367                 :             : 
     368                 :         462 :         ip_family(dst) = ip_family(src);
     369                 :         462 :         ip_bits(dst) = bits;
     370                 :             : 
     371         [ -  + ]:         462 :         if (bits > 0)
     372                 :             :         {
     373         [ +  - ]:         462 :                 Assert(bits <= ip_maxbits(dst));
     374                 :             : 
     375                 :             :                 /* Clone appropriate bytes of the address, leaving the rest 0 */
     376                 :         462 :                 memcpy(ip_addr(dst), ip_addr(src), (bits + 7) / 8);
     377                 :             : 
     378                 :             :                 /* Clear any unwanted bits in the last partial byte */
     379         [ +  + ]:         462 :                 if (bits % 8)
     380                 :          10 :                         ip_addr(dst)[bits / 8] &= ~(0xFF >> (bits % 8));
     381                 :         462 :         }
     382                 :             : 
     383                 :             :         /* Set varlena header correctly */
     384                 :         462 :         SET_INET_VARSIZE(dst);
     385                 :             : 
     386                 :         924 :         return dst;
     387                 :         462 : }
     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                 :       74907 : network_cmp_internal(inet *a1, inet *a2)
     402                 :             : {
     403         [ +  + ]:       74907 :         if (ip_family(a1) == ip_family(a2))
     404                 :             :         {
     405                 :       49651 :                 int                     order;
     406                 :             : 
     407                 :       99302 :                 order = bitncmp(ip_addr(a1), ip_addr(a2),
     408         [ +  + ]:       49651 :                                                 Min(ip_bits(a1), ip_bits(a2)));
     409         [ +  + ]:       49651 :                 if (order != 0)
     410                 :       46230 :                         return order;
     411                 :        3421 :                 order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
     412         [ +  + ]:        3421 :                 if (order != 0)
     413                 :         142 :                         return order;
     414                 :        3279 :                 return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));
     415                 :       49651 :         }
     416                 :             : 
     417                 :       25256 :         return ip_family(a1) - ip_family(a2);
     418                 :       74907 : }
     419                 :             : 
     420                 :             : Datum
     421                 :          16 : network_cmp(PG_FUNCTION_ARGS)
     422                 :             : {
     423                 :          16 :         inet       *a1 = PG_GETARG_INET_PP(0);
     424                 :          16 :         inet       *a2 = PG_GETARG_INET_PP(1);
     425                 :             : 
     426                 :          32 :         PG_RETURN_INT32(network_cmp_internal(a1, a2));
     427                 :          16 : }
     428                 :             : 
     429                 :             : /*
     430                 :             :  * SortSupport strategy routine
     431                 :             :  */
     432                 :             : Datum
     433                 :          48 : network_sortsupport(PG_FUNCTION_ARGS)
     434                 :             : {
     435                 :          48 :         SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     436                 :             : 
     437                 :          48 :         ssup->comparator = network_fast_cmp;
     438                 :          48 :         ssup->ssup_extra = NULL;
     439                 :             : 
     440         [ +  + ]:          48 :         if (ssup->abbreviate)
     441                 :             :         {
     442                 :          24 :                 network_sortsupport_state *uss;
     443                 :          24 :                 MemoryContext oldcontext;
     444                 :             : 
     445                 :          24 :                 oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
     446                 :             : 
     447                 :          24 :                 uss = palloc_object(network_sortsupport_state);
     448                 :          24 :                 uss->input_count = 0;
     449                 :          24 :                 uss->estimating = true;
     450                 :          24 :                 initHyperLogLog(&uss->abbr_card, 10);
     451                 :             : 
     452                 :          24 :                 ssup->ssup_extra = uss;
     453                 :             : 
     454                 :          24 :                 ssup->comparator = ssup_datum_unsigned_cmp;
     455                 :          24 :                 ssup->abbrev_converter = network_abbrev_convert;
     456                 :          24 :                 ssup->abbrev_abort = network_abbrev_abort;
     457                 :          24 :                 ssup->abbrev_full_comparator = network_fast_cmp;
     458                 :             : 
     459                 :          24 :                 MemoryContextSwitchTo(oldcontext);
     460                 :          24 :         }
     461                 :             : 
     462                 :          48 :         PG_RETURN_VOID();
     463                 :          48 : }
     464                 :             : 
     465                 :             : /*
     466                 :             :  * SortSupport comparison func
     467                 :             :  */
     468                 :             : static int
     469                 :         127 : network_fast_cmp(Datum x, Datum y, SortSupport ssup)
     470                 :             : {
     471                 :         127 :         inet       *arg1 = DatumGetInetPP(x);
     472                 :         127 :         inet       *arg2 = DatumGetInetPP(y);
     473                 :             : 
     474                 :         254 :         return network_cmp_internal(arg1, arg2);
     475                 :         127 : }
     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                 :           7 : network_abbrev_abort(int memtupcount, SortSupport ssup)
     485                 :             : {
     486                 :           7 :         network_sortsupport_state *uss = ssup->ssup_extra;
     487                 :           7 :         double          abbr_card;
     488                 :             : 
     489   [ -  +  #  #  :           7 :         if (memtupcount < 10000 || uss->input_count < 10000 || !uss->estimating)
                   #  # ]
     490                 :           7 :                 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                 :           7 : }
     535                 :             : 
     536                 :             : /*
     537                 :             :  * SortSupport conversion routine. Converts original inet/cidr representation
     538                 :             :  * to abbreviated key representation that works with simple 3-way unsigned int
     539                 :             :  * comparisons. The network_cmp_internal() rules for sorting inet/cidr datums
     540                 :             :  * are followed by abbreviated comparisons by an encoding scheme that
     541                 :             :  * conditions keys through careful use of padding.
     542                 :             :  *
     543                 :             :  * Some background: inet values have three major components (take for example
     544                 :             :  * the address 1.2.3.4/24):
     545                 :             :  *
     546                 :             :  *     * A network, or netmasked bits (1.2.3.0).
     547                 :             :  *     * A netmask size (/24).
     548                 :             :  *     * A subnet, or bits outside of the netmask (0.0.0.4).
     549                 :             :  *
     550                 :             :  * cidr values are the same except that with only the first two components --
     551                 :             :  * all their subnet bits *must* be zero (1.2.3.0/24).
     552                 :             :  *
     553                 :             :  * IPv4 and IPv6 are identical in this makeup, with the difference being that
     554                 :             :  * IPv4 addresses have a maximum of 32 bits compared to IPv6's 64 bits, so in
     555                 :             :  * IPv6 each part may be larger.
     556                 :             :  *
     557                 :             :  * inet/cidr types compare using these sorting rules. If inequality is detected
     558                 :             :  * at any step, comparison is finished. If any rule is a tie, the algorithm
     559                 :             :  * drops through to the next to break it:
     560                 :             :  *
     561                 :             :  *     1. IPv4 always appears before IPv6.
     562                 :             :  *     2. Network bits are compared.
     563                 :             :  *     3. Netmask size is compared.
     564                 :             :  *     4. All bits are compared (having made it here, we know that both
     565                 :             :  *        netmasked bits and netmask size are equal, so we're in effect only
     566                 :             :  *        comparing subnet bits).
     567                 :             :  *
     568                 :             :  * When generating abbreviated keys for SortSupport, we pack as much as we can
     569                 :             :  * into a datum while ensuring that when comparing those keys as integers,
     570                 :             :  * these rules will be respected. Exact contents depend on IP family:
     571                 :             :  *
     572                 :             :  * IPv4
     573                 :             :  * ----
     574                 :             :  *
     575                 :             :  * We have space to store all netmasked bits, followed by the netmask size,
     576                 :             :  * followed by 25 bits of the subnet (25 bits is usually more than enough in
     577                 :             :  * practice). cidr datums always have all-zero subnet bits.
     578                 :             :  *
     579                 :             :  * +----------+-----------------------+--------------+--------------------+
     580                 :             :  * | 1 bit IP |    32 bits network    |    6 bits    |   25 bits subnet   |
     581                 :             :  * |  family  |        (full)         | network size |    (truncated)     |
     582                 :             :  * +----------+-----------------------+--------------+--------------------+
     583                 :             :  *
     584                 :             :  * IPv6
     585                 :             :  * ----
     586                 :             :  *
     587                 :             :  * +----------+---------------------------------+
     588                 :             :  * | 1 bit IP |         63 bits network         |    (up to 65 bits
     589                 :             :  * |  family  |           (truncated)           |   network omitted)
     590                 :             :  * +----------+---------------------------------+
     591                 :             :  */
     592                 :             : static Datum
     593                 :         250 : network_abbrev_convert(Datum original, SortSupport ssup)
     594                 :             : {
     595                 :         250 :         network_sortsupport_state *uss = ssup->ssup_extra;
     596                 :         250 :         inet       *authoritative = DatumGetInetPP(original);
     597                 :         250 :         Datum           res,
     598                 :             :                                 ipaddr_datum,
     599                 :             :                                 subnet_bitmask,
     600                 :             :                                 network;
     601                 :         250 :         int                     subnet_size;
     602                 :             : 
     603   [ +  +  +  - ]:         250 :         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         [ +  + ]:         250 :         if (ip_family(authoritative) == PGSQL_AF_INET)
     616                 :             :         {
     617                 :         187 :                 uint32          ipaddr_datum32;
     618                 :             : 
     619                 :         187 :                 memcpy(&ipaddr_datum32, ip_addr(authoritative), sizeof(uint32));
     620                 :             : 
     621                 :             :                 /* Must byteswap on little-endian machines */
     622                 :             : #ifndef WORDS_BIGENDIAN
     623                 :         187 :                 ipaddr_datum = pg_bswap32(ipaddr_datum32);
     624                 :             : #else
     625                 :             :                 ipaddr_datum = ipaddr_datum32;
     626                 :             : #endif
     627                 :             : 
     628                 :             :                 /* Initialize result without setting ipfamily bit */
     629                 :         187 :                 res = (Datum) 0;
     630                 :         187 :         }
     631                 :             :         else
     632                 :             :         {
     633                 :          63 :                 memcpy(&ipaddr_datum, ip_addr(authoritative), sizeof(Datum));
     634                 :             : 
     635                 :             :                 /* Must byteswap on little-endian machines */
     636                 :          63 :                 ipaddr_datum = DatumBigEndianToNative(ipaddr_datum);
     637                 :             : 
     638                 :             :                 /* Initialize result with ipfamily (most significant) bit set */
     639                 :          63 :                 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                 :         250 :         subnet_size = ip_maxbits(authoritative) - ip_bits(authoritative);
     658         [ +  - ]:         250 :         Assert(subnet_size >= 0);
     659                 :             :         /* subnet size must work with prefix ipaddr cases */
     660                 :         250 :         subnet_size %= sizeof(Datum) * BITS_PER_BYTE;
     661         [ +  + ]:         250 :         if (ip_bits(authoritative) == 0)
     662                 :             :         {
     663                 :             :                 /* Fit as many ipaddr bits as possible into subnet */
     664                 :          28 :                 subnet_bitmask = ((Datum) 0) - 1;
     665                 :          28 :                 network = 0;
     666                 :          28 :         }
     667         [ +  + ]:         222 :         else if (ip_bits(authoritative) < sizeof(Datum) * BITS_PER_BYTE)
     668                 :             :         {
     669                 :             :                 /* Split ipaddr bits between network and subnet */
     670                 :         187 :                 subnet_bitmask = (((Datum) 1) << subnet_size) - 1;
     671                 :         187 :                 network = ipaddr_datum & ~subnet_bitmask;
     672                 :         187 :         }
     673                 :             :         else
     674                 :             :         {
     675                 :             :                 /* Fit as many ipaddr bits as possible into network */
     676                 :          35 :                 subnet_bitmask = 0;
     677                 :          35 :                 network = ipaddr_datum;
     678                 :             :         }
     679                 :             : 
     680         [ +  + ]:         250 :         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                 :         187 :                 Datum           netmask_size = (Datum) ip_bits(authoritative);
     687                 :         187 :                 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                 :         187 :                 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                 :         187 :                 netmask_size <<= ABBREV_BITS_INET4_SUBNET;
     704                 :             : 
     705                 :             :                 /* Extract subnet bits without shifting them */
     706                 :         187 :                 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         [ +  + ]:         187 :                 if (subnet_size > ABBREV_BITS_INET4_SUBNET)
     719                 :          24 :                         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                 :         187 :                 res |= network | netmask_size | subnet;
     726                 :         187 :         }
     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                 :          63 :                 res |= network >> 1;
     735                 :             :         }
     736                 :             : 
     737                 :         250 :         uss->input_count += 1;
     738                 :             : 
     739                 :             :         /* Hash abbreviated key */
     740         [ -  + ]:         250 :         if (uss->estimating)
     741                 :             :         {
     742                 :         250 :                 uint32          tmp;
     743                 :             : 
     744                 :         250 :                 tmp = DatumGetUInt32(res) ^ (uint32) (DatumGetUInt64(res) >> 32);
     745                 :             : 
     746                 :         250 :                 addHyperLogLog(&uss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
     747                 :         250 :         }
     748                 :             : 
     749                 :         500 :         return res;
     750                 :         250 : }
     751                 :             : 
     752                 :             : /*
     753                 :             :  *      Boolean ordering tests.
     754                 :             :  */
     755                 :             : Datum
     756                 :       49910 : network_lt(PG_FUNCTION_ARGS)
     757                 :             : {
     758                 :       49910 :         inet       *a1 = PG_GETARG_INET_PP(0);
     759                 :       49910 :         inet       *a2 = PG_GETARG_INET_PP(1);
     760                 :             : 
     761                 :       99820 :         PG_RETURN_BOOL(network_cmp_internal(a1, a2) < 0);
     762                 :       49910 : }
     763                 :             : 
     764                 :             : Datum
     765                 :        2575 : network_le(PG_FUNCTION_ARGS)
     766                 :             : {
     767                 :        2575 :         inet       *a1 = PG_GETARG_INET_PP(0);
     768                 :        2575 :         inet       *a2 = PG_GETARG_INET_PP(1);
     769                 :             : 
     770                 :        5150 :         PG_RETURN_BOOL(network_cmp_internal(a1, a2) <= 0);
     771                 :        2575 : }
     772                 :             : 
     773                 :             : Datum
     774                 :       16588 : network_eq(PG_FUNCTION_ARGS)
     775                 :             : {
     776                 :       16588 :         inet       *a1 = PG_GETARG_INET_PP(0);
     777                 :       16588 :         inet       *a2 = PG_GETARG_INET_PP(1);
     778                 :             : 
     779                 :       33176 :         PG_RETURN_BOOL(network_cmp_internal(a1, a2) == 0);
     780                 :       16588 : }
     781                 :             : 
     782                 :             : Datum
     783                 :        2563 : network_ge(PG_FUNCTION_ARGS)
     784                 :             : {
     785                 :        2563 :         inet       *a1 = PG_GETARG_INET_PP(0);
     786                 :        2563 :         inet       *a2 = PG_GETARG_INET_PP(1);
     787                 :             : 
     788                 :        5126 :         PG_RETURN_BOOL(network_cmp_internal(a1, a2) >= 0);
     789                 :        2563 : }
     790                 :             : 
     791                 :             : Datum
     792                 :        3047 : network_gt(PG_FUNCTION_ARGS)
     793                 :             : {
     794                 :        3047 :         inet       *a1 = PG_GETARG_INET_PP(0);
     795                 :        3047 :         inet       *a2 = PG_GETARG_INET_PP(1);
     796                 :             : 
     797                 :        6094 :         PG_RETURN_BOOL(network_cmp_internal(a1, a2) > 0);
     798                 :        3047 : }
     799                 :             : 
     800                 :             : Datum
     801                 :          17 : network_ne(PG_FUNCTION_ARGS)
     802                 :             : {
     803                 :          17 :         inet       *a1 = PG_GETARG_INET_PP(0);
     804                 :          17 :         inet       *a2 = PG_GETARG_INET_PP(1);
     805                 :             : 
     806                 :          34 :         PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
     807                 :          17 : }
     808                 :             : 
     809                 :             : /*
     810                 :             :  * MIN/MAX support functions.
     811                 :             :  */
     812                 :             : Datum
     813                 :          32 : network_smaller(PG_FUNCTION_ARGS)
     814                 :             : {
     815                 :          32 :         inet       *a1 = PG_GETARG_INET_PP(0);
     816                 :          32 :         inet       *a2 = PG_GETARG_INET_PP(1);
     817                 :             : 
     818         [ +  + ]:          32 :         if (network_cmp_internal(a1, a2) < 0)
     819                 :          19 :                 PG_RETURN_INET_P(a1);
     820                 :             :         else
     821                 :          13 :                 PG_RETURN_INET_P(a2);
     822                 :          32 : }
     823                 :             : 
     824                 :             : Datum
     825                 :          32 : network_larger(PG_FUNCTION_ARGS)
     826                 :             : {
     827                 :          32 :         inet       *a1 = PG_GETARG_INET_PP(0);
     828                 :          32 :         inet       *a2 = PG_GETARG_INET_PP(1);
     829                 :             : 
     830         [ +  + ]:          32 :         if (network_cmp_internal(a1, a2) > 0)
     831                 :          26 :                 PG_RETURN_INET_P(a1);
     832                 :             :         else
     833                 :           6 :                 PG_RETURN_INET_P(a2);
     834                 :          32 : }
     835                 :             : 
     836                 :             : /*
     837                 :             :  * Support function for hash indexes on inet/cidr.
     838                 :             :  */
     839                 :             : Datum
     840                 :        1012 : hashinet(PG_FUNCTION_ARGS)
     841                 :             : {
     842                 :        1012 :         inet       *addr = PG_GETARG_INET_PP(0);
     843                 :        1012 :         int                     addrsize = ip_addrsize(addr);
     844                 :             : 
     845                 :             :         /* XXX this assumes there are no pad bytes in the data structure */
     846                 :        2024 :         return hash_any((unsigned char *) VARDATA_ANY(addr), addrsize + 2);
     847                 :        1012 : }
     848                 :             : 
     849                 :             : Datum
     850                 :          10 : hashinetextended(PG_FUNCTION_ARGS)
     851                 :             : {
     852                 :          10 :         inet       *addr = PG_GETARG_INET_PP(0);
     853                 :          10 :         int                     addrsize = ip_addrsize(addr);
     854                 :             : 
     855                 :          30 :         return hash_any_extended((unsigned char *) VARDATA_ANY(addr), addrsize + 2,
     856                 :          10 :                                                          PG_GETARG_INT64(1));
     857                 :          10 : }
     858                 :             : 
     859                 :             : /*
     860                 :             :  *      Boolean network-inclusion tests.
     861                 :             :  */
     862                 :             : Datum
     863                 :        1022 : network_sub(PG_FUNCTION_ARGS)
     864                 :             : {
     865                 :        1022 :         inet       *a1 = PG_GETARG_INET_PP(0);
     866                 :        1022 :         inet       *a2 = PG_GETARG_INET_PP(1);
     867                 :             : 
     868         [ +  + ]:        1022 :         if (ip_family(a1) == ip_family(a2))
     869                 :             :         {
     870         [ +  + ]:         822 :                 PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2) &&
     871                 :             :                                            bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
     872                 :             :         }
     873                 :             : 
     874                 :         200 :         PG_RETURN_BOOL(false);
     875                 :        1022 : }
     876                 :             : 
     877                 :             : Datum
     878                 :        1651 : network_subeq(PG_FUNCTION_ARGS)
     879                 :             : {
     880                 :        1651 :         inet       *a1 = PG_GETARG_INET_PP(0);
     881                 :        1651 :         inet       *a2 = PG_GETARG_INET_PP(1);
     882                 :             : 
     883         [ +  + ]:        1651 :         if (ip_family(a1) == ip_family(a2))
     884                 :             :         {
     885         [ +  + ]:        1023 :                 PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2) &&
     886                 :             :                                            bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
     887                 :             :         }
     888                 :             : 
     889                 :         628 :         PG_RETURN_BOOL(false);
     890                 :        1651 : }
     891                 :             : 
     892                 :             : Datum
     893                 :        1030 : network_sup(PG_FUNCTION_ARGS)
     894                 :             : {
     895                 :        1030 :         inet       *a1 = PG_GETARG_INET_PP(0);
     896                 :        1030 :         inet       *a2 = PG_GETARG_INET_PP(1);
     897                 :             : 
     898         [ +  + ]:        1030 :         if (ip_family(a1) == ip_family(a2))
     899                 :             :         {
     900         [ +  + ]:         830 :                 PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2) &&
     901                 :             :                                            bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
     902                 :             :         }
     903                 :             : 
     904                 :         200 :         PG_RETURN_BOOL(false);
     905                 :        1030 : }
     906                 :             : 
     907                 :             : Datum
     908                 :        3098 : network_supeq(PG_FUNCTION_ARGS)
     909                 :             : {
     910                 :        3098 :         inet       *a1 = PG_GETARG_INET_PP(0);
     911                 :        3098 :         inet       *a2 = PG_GETARG_INET_PP(1);
     912                 :             : 
     913         [ +  + ]:        3098 :         if (ip_family(a1) == ip_family(a2))
     914                 :             :         {
     915         [ +  + ]:        1708 :                 PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2) &&
     916                 :             :                                            bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
     917                 :             :         }
     918                 :             : 
     919                 :        1390 :         PG_RETURN_BOOL(false);
     920                 :        3098 : }
     921                 :             : 
     922                 :             : Datum
     923                 :        3505 : network_overlap(PG_FUNCTION_ARGS)
     924                 :             : {
     925                 :        3505 :         inet       *a1 = PG_GETARG_INET_PP(0);
     926                 :        3505 :         inet       *a2 = PG_GETARG_INET_PP(1);
     927                 :             : 
     928         [ +  + ]:        3505 :         if (ip_family(a1) == ip_family(a2))
     929                 :             :         {
     930         [ +  + ]:        2133 :                 PG_RETURN_BOOL(bitncmp(ip_addr(a1), ip_addr(a2),
     931                 :             :                                                            Min(ip_bits(a1), ip_bits(a2))) == 0);
     932                 :             :         }
     933                 :             : 
     934                 :        1372 :         PG_RETURN_BOOL(false);
     935                 :        3505 : }
     936                 :             : 
     937                 :             : /*
     938                 :             :  * Planner support function for network subset/superset operators
     939                 :             :  */
     940                 :             : Datum
     941                 :         248 : network_subset_support(PG_FUNCTION_ARGS)
     942                 :             : {
     943                 :         248 :         Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
     944                 :         248 :         Node       *ret = NULL;
     945                 :             : 
     946         [ +  + ]:         248 :         if (IsA(rawreq, SupportRequestIndexCondition))
     947                 :             :         {
     948                 :             :                 /* Try to convert operator/function call to index conditions */
     949                 :           8 :                 SupportRequestIndexCondition *req = (SupportRequestIndexCondition *) rawreq;
     950                 :             : 
     951         [ +  - ]:           8 :                 if (is_opclause(req->node))
     952                 :             :                 {
     953                 :           8 :                         OpExpr     *clause = (OpExpr *) req->node;
     954                 :             : 
     955         [ +  - ]:           8 :                         Assert(list_length(clause->args) == 2);
     956                 :           8 :                         ret = (Node *)
     957                 :          16 :                                 match_network_function((Node *) linitial(clause->args),
     958                 :           8 :                                                                            (Node *) lsecond(clause->args),
     959                 :           8 :                                                                            req->indexarg,
     960                 :           8 :                                                                            req->funcid,
     961                 :           8 :                                                                            req->opfamily);
     962                 :           8 :                 }
     963         [ #  # ]:           0 :                 else if (is_funcclause(req->node))   /* be paranoid */
     964                 :             :                 {
     965                 :           0 :                         FuncExpr   *clause = (FuncExpr *) req->node;
     966                 :             : 
     967         [ #  # ]:           0 :                         Assert(list_length(clause->args) == 2);
     968                 :           0 :                         ret = (Node *)
     969                 :           0 :                                 match_network_function((Node *) linitial(clause->args),
     970                 :           0 :                                                                            (Node *) lsecond(clause->args),
     971                 :           0 :                                                                            req->indexarg,
     972                 :           0 :                                                                            req->funcid,
     973                 :           0 :                                                                            req->opfamily);
     974                 :           0 :                 }
     975                 :           8 :         }
     976                 :             : 
     977                 :         496 :         PG_RETURN_POINTER(ret);
     978                 :         248 : }
     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                 :           8 : match_network_function(Node *leftop,
     989                 :             :                                            Node *rightop,
     990                 :             :                                            int indexarg,
     991                 :             :                                            Oid funcid,
     992                 :             :                                            Oid opfamily)
     993                 :             : {
     994   [ -  +  +  +  :           8 :         switch (funcid)
                      + ]
     995                 :             :         {
     996                 :             :                 case F_NETWORK_SUB:
     997                 :             :                         /* indexkey must be on the left */
     998         [ -  + ]:           2 :                         if (indexarg != 0)
     999                 :           0 :                                 return NIL;
    1000                 :           2 :                         return match_network_subset(leftop, rightop, false, opfamily);
    1001                 :             : 
    1002                 :             :                 case F_NETWORK_SUBEQ:
    1003                 :             :                         /* indexkey must be on the left */
    1004         [ -  + ]:           2 :                         if (indexarg != 0)
    1005                 :           0 :                                 return NIL;
    1006                 :           2 :                         return match_network_subset(leftop, rightop, true, opfamily);
    1007                 :             : 
    1008                 :             :                 case F_NETWORK_SUP:
    1009                 :             :                         /* indexkey must be on the right */
    1010         [ -  + ]:           2 :                         if (indexarg != 1)
    1011                 :           0 :                                 return NIL;
    1012                 :           2 :                         return match_network_subset(rightop, leftop, false, opfamily);
    1013                 :             : 
    1014                 :             :                 case F_NETWORK_SUPEQ:
    1015                 :             :                         /* indexkey must be on the right */
    1016         [ -  + ]:           2 :                         if (indexarg != 1)
    1017                 :           0 :                                 return NIL;
    1018                 :           2 :                         return match_network_subset(rightop, leftop, true, opfamily);
    1019                 :             : 
    1020                 :             :                 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                 :           8 : }
    1030                 :             : 
    1031                 :             : /*
    1032                 :             :  * match_network_subset
    1033                 :             :  *        Try to generate an indexqual for a network subset function.
    1034                 :             :  */
    1035                 :             : static List *
    1036                 :           8 : match_network_subset(Node *leftop,
    1037                 :             :                                          Node *rightop,
    1038                 :             :                                          bool is_eq,
    1039                 :             :                                          Oid opfamily)
    1040                 :             : {
    1041                 :           8 :         List       *result;
    1042                 :           8 :         Datum           rightopval;
    1043                 :           8 :         Oid                     datatype = INETOID;
    1044                 :           8 :         Oid                     opr1oid;
    1045                 :           8 :         Oid                     opr2oid;
    1046                 :           8 :         Datum           opr1right;
    1047                 :           8 :         Datum           opr2right;
    1048                 :           8 :         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   [ +  -  -  + ]:           8 :         if (!IsA(rightop, Const) ||
    1058                 :           8 :                 ((Const *) rightop)->constisnull)
    1059                 :           0 :                 return NIL;
    1060                 :           8 :         rightopval = ((Const *) rightop)->constvalue;
    1061                 :             : 
    1062                 :             :         /*
    1063                 :             :          * create clause "key >= network_scan_first( rightopval )", or ">" if the
    1064                 :             :          * operator disallows equality.
    1065                 :             :          */
    1066                 :           8 :         opr1oid = get_opfamily_member_for_cmptype(opfamily, datatype, datatype, is_eq ? COMPARE_GE : COMPARE_GT);
    1067         [ +  - ]:           8 :         if (opr1oid == InvalidOid)
    1068                 :           0 :                 return NIL;
    1069                 :             : 
    1070                 :           8 :         opr1right = network_scan_first(rightopval);
    1071                 :             : 
    1072                 :          16 :         expr = make_opclause(opr1oid, BOOLOID, false,
    1073                 :           8 :                                                  (Expr *) leftop,
    1074                 :          16 :                                                  (Expr *) makeConst(datatype, -1,
    1075                 :             :                                                                                         InvalidOid, /* not collatable */
    1076                 :           8 :                                                                                         -1, opr1right,
    1077                 :             :                                                                                         false, false),
    1078                 :             :                                                  InvalidOid, InvalidOid);
    1079                 :           8 :         result = list_make1(expr);
    1080                 :             : 
    1081                 :             :         /* create clause "key <= network_scan_last( rightopval )" */
    1082                 :             : 
    1083                 :           8 :         opr2oid = get_opfamily_member_for_cmptype(opfamily, datatype, datatype, COMPARE_LE);
    1084         [ +  - ]:           8 :         if (opr2oid == InvalidOid)
    1085                 :           0 :                 return NIL;
    1086                 :             : 
    1087                 :           8 :         opr2right = network_scan_last(rightopval);
    1088                 :             : 
    1089                 :          16 :         expr = make_opclause(opr2oid, BOOLOID, false,
    1090                 :           8 :                                                  (Expr *) leftop,
    1091                 :          16 :                                                  (Expr *) makeConst(datatype, -1,
    1092                 :             :                                                                                         InvalidOid, /* not collatable */
    1093                 :           8 :                                                                                         -1, opr2right,
    1094                 :             :                                                                                         false, false),
    1095                 :             :                                                  InvalidOid, InvalidOid);
    1096                 :           8 :         result = lappend(result, expr);
    1097                 :             : 
    1098                 :           8 :         return result;
    1099                 :           8 : }
    1100                 :             : 
    1101                 :             : 
    1102                 :             : /*
    1103                 :             :  * Extract data from a network datatype.
    1104                 :             :  */
    1105                 :             : Datum
    1106                 :          17 : network_host(PG_FUNCTION_ARGS)
    1107                 :             : {
    1108                 :          17 :         inet       *ip = PG_GETARG_INET_PP(0);
    1109                 :          17 :         char       *ptr;
    1110                 :          17 :         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                 :          34 :         if (pg_inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
    1114   [ +  -  +  - ]:          34 :                                                  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         [ +  - ]:          17 :         if ((ptr = strchr(tmp, '/')) != NULL)
    1121                 :           0 :                 *ptr = '\0';
    1122                 :             : 
    1123                 :          34 :         PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1124                 :          17 : }
    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                 :          87 : network_show(PG_FUNCTION_ARGS)
    1133                 :             : {
    1134                 :          87 :         inet       *ip = PG_GETARG_INET_PP(0);
    1135                 :          87 :         int                     len;
    1136                 :          87 :         char            tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
    1137                 :             : 
    1138                 :         174 :         if (pg_inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
    1139   [ +  -  +  - ]:         174 :                                                  tmp, sizeof(tmp)) == NULL)
    1140   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    1141                 :             :                                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    1142                 :             :                                  errmsg("could not format inet value: %m")));
    1143                 :             : 
    1144                 :             :         /* Add /n if not present (which it won't be) */
    1145         [ -  + ]:          87 :         if (strchr(tmp, '/') == NULL)
    1146                 :             :         {
    1147                 :          87 :                 len = strlen(tmp);
    1148                 :          87 :                 snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
    1149                 :          87 :         }
    1150                 :             : 
    1151                 :         174 :         PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1152                 :          87 : }
    1153                 :             : 
    1154                 :             : Datum
    1155                 :          17 : inet_abbrev(PG_FUNCTION_ARGS)
    1156                 :             : {
    1157                 :          17 :         inet       *ip = PG_GETARG_INET_PP(0);
    1158                 :          17 :         char       *dst;
    1159                 :          17 :         char            tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
    1160                 :             : 
    1161                 :          34 :         dst = pg_inet_net_ntop(ip_family(ip), ip_addr(ip),
    1162                 :          17 :                                                    ip_bits(ip), tmp, sizeof(tmp));
    1163                 :             : 
    1164         [ +  - ]:          17 :         if (dst == NULL)
    1165   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    1166                 :             :                                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    1167                 :             :                                  errmsg("could not format inet value: %m")));
    1168                 :             : 
    1169                 :          34 :         PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1170                 :          17 : }
    1171                 :             : 
    1172                 :             : Datum
    1173                 :          17 : cidr_abbrev(PG_FUNCTION_ARGS)
    1174                 :             : {
    1175                 :          17 :         inet       *ip = PG_GETARG_INET_PP(0);
    1176                 :          17 :         char       *dst;
    1177                 :          17 :         char            tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
    1178                 :             : 
    1179                 :          34 :         dst = pg_inet_cidr_ntop(ip_family(ip), ip_addr(ip),
    1180                 :          17 :                                                         ip_bits(ip), tmp, sizeof(tmp));
    1181                 :             : 
    1182         [ +  - ]:          17 :         if (dst == NULL)
    1183   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    1184                 :             :                                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
    1185                 :             :                                  errmsg("could not format cidr value: %m")));
    1186                 :             : 
    1187                 :          34 :         PG_RETURN_TEXT_P(cstring_to_text(tmp));
    1188                 :          17 : }
    1189                 :             : 
    1190                 :             : Datum
    1191                 :          59 : network_masklen(PG_FUNCTION_ARGS)
    1192                 :             : {
    1193                 :          59 :         inet       *ip = PG_GETARG_INET_PP(0);
    1194                 :             : 
    1195                 :         118 :         PG_RETURN_INT32(ip_bits(ip));
    1196                 :          59 : }
    1197                 :             : 
    1198                 :             : Datum
    1199                 :          17 : network_family(PG_FUNCTION_ARGS)
    1200                 :             : {
    1201                 :          17 :         inet       *ip = PG_GETARG_INET_PP(0);
    1202                 :             : 
    1203      [ +  -  + ]:          17 :         switch (ip_family(ip))
    1204                 :             :         {
    1205                 :             :                 case PGSQL_AF_INET:
    1206                 :          14 :                         PG_RETURN_INT32(4);
    1207                 :             :                         break;
    1208                 :             :                 case PGSQL_AF_INET6:
    1209                 :           3 :                         PG_RETURN_INT32(6);
    1210                 :             :                         break;
    1211                 :             :                 default:
    1212                 :           0 :                         PG_RETURN_INT32(0);
    1213                 :             :                         break;
    1214                 :             :         }
    1215                 :          17 : }
    1216                 :             : 
    1217                 :             : Datum
    1218                 :          42 : network_broadcast(PG_FUNCTION_ARGS)
    1219                 :             : {
    1220                 :          42 :         inet       *ip = PG_GETARG_INET_PP(0);
    1221                 :          42 :         inet       *dst;
    1222                 :          42 :         int                     byte;
    1223                 :          42 :         int                     bits;
    1224                 :          42 :         int                     maxbytes;
    1225                 :          42 :         unsigned char mask;
    1226                 :          42 :         unsigned char *a,
    1227                 :             :                            *b;
    1228                 :             : 
    1229                 :             :         /* make sure any unused bits are zeroed */
    1230                 :          42 :         dst = palloc0_object(inet);
    1231                 :             : 
    1232                 :          42 :         maxbytes = ip_addrsize(ip);
    1233                 :          42 :         bits = ip_bits(ip);
    1234                 :          42 :         a = ip_addr(ip);
    1235                 :          42 :         b = ip_addr(dst);
    1236                 :             : 
    1237         [ +  + ]:         282 :         for (byte = 0; byte < maxbytes; byte++)
    1238                 :             :         {
    1239         [ +  + ]:         240 :                 if (bits >= 8)
    1240                 :             :                 {
    1241                 :         165 :                         mask = 0x00;
    1242                 :         165 :                         bits -= 8;
    1243                 :         165 :                 }
    1244         [ +  + ]:          75 :                 else if (bits == 0)
    1245                 :          71 :                         mask = 0xff;
    1246                 :             :                 else
    1247                 :             :                 {
    1248                 :           4 :                         mask = 0xff >> bits;
    1249                 :           4 :                         bits = 0;
    1250                 :             :                 }
    1251                 :             : 
    1252                 :         240 :                 b[byte] = a[byte] | mask;
    1253                 :         240 :         }
    1254                 :             : 
    1255                 :          42 :         ip_family(dst) = ip_family(ip);
    1256                 :          42 :         ip_bits(dst) = ip_bits(ip);
    1257                 :          42 :         SET_INET_VARSIZE(dst);
    1258                 :             : 
    1259                 :          84 :         PG_RETURN_INET_P(dst);
    1260                 :          42 : }
    1261                 :             : 
    1262                 :             : Datum
    1263                 :          42 : network_network(PG_FUNCTION_ARGS)
    1264                 :             : {
    1265                 :          42 :         inet       *ip = PG_GETARG_INET_PP(0);
    1266                 :          42 :         inet       *dst;
    1267                 :          42 :         int                     byte;
    1268                 :          42 :         int                     bits;
    1269                 :          42 :         unsigned char mask;
    1270                 :          42 :         unsigned char *a,
    1271                 :             :                            *b;
    1272                 :             : 
    1273                 :             :         /* make sure any unused bits are zeroed */
    1274                 :          42 :         dst = palloc0_object(inet);
    1275                 :             : 
    1276                 :          42 :         bits = ip_bits(ip);
    1277                 :          42 :         a = ip_addr(ip);
    1278                 :          42 :         b = ip_addr(dst);
    1279                 :             : 
    1280                 :          42 :         byte = 0;
    1281                 :             : 
    1282         [ +  + ]:         211 :         while (bits)
    1283                 :             :         {
    1284         [ +  + ]:         169 :                 if (bits >= 8)
    1285                 :             :                 {
    1286                 :         165 :                         mask = 0xff;
    1287                 :         165 :                         bits -= 8;
    1288                 :         165 :                 }
    1289                 :             :                 else
    1290                 :             :                 {
    1291                 :           4 :                         mask = 0xff << (8 - bits);
    1292                 :           4 :                         bits = 0;
    1293                 :             :                 }
    1294                 :             : 
    1295                 :         169 :                 b[byte] = a[byte] & mask;
    1296                 :         169 :                 byte++;
    1297                 :             :         }
    1298                 :             : 
    1299                 :          42 :         ip_family(dst) = ip_family(ip);
    1300                 :          42 :         ip_bits(dst) = ip_bits(ip);
    1301                 :          42 :         SET_INET_VARSIZE(dst);
    1302                 :             : 
    1303                 :          84 :         PG_RETURN_INET_P(dst);
    1304                 :          42 : }
    1305                 :             : 
    1306                 :             : Datum
    1307                 :          17 : network_netmask(PG_FUNCTION_ARGS)
    1308                 :             : {
    1309                 :          17 :         inet       *ip = PG_GETARG_INET_PP(0);
    1310                 :          17 :         inet       *dst;
    1311                 :          17 :         int                     byte;
    1312                 :          17 :         int                     bits;
    1313                 :          17 :         unsigned char mask;
    1314                 :          17 :         unsigned char *b;
    1315                 :             : 
    1316                 :             :         /* make sure any unused bits are zeroed */
    1317                 :          17 :         dst = palloc0_object(inet);
    1318                 :             : 
    1319                 :          17 :         bits = ip_bits(ip);
    1320                 :          17 :         b = ip_addr(dst);
    1321                 :             : 
    1322                 :          17 :         byte = 0;
    1323                 :             : 
    1324         [ +  + ]:          79 :         while (bits)
    1325                 :             :         {
    1326         [ +  + ]:          62 :                 if (bits >= 8)
    1327                 :             :                 {
    1328                 :          60 :                         mask = 0xff;
    1329                 :          60 :                         bits -= 8;
    1330                 :          60 :                 }
    1331                 :             :                 else
    1332                 :             :                 {
    1333                 :           2 :                         mask = 0xff << (8 - bits);
    1334                 :           2 :                         bits = 0;
    1335                 :             :                 }
    1336                 :             : 
    1337                 :          62 :                 b[byte] = mask;
    1338                 :          62 :                 byte++;
    1339                 :             :         }
    1340                 :             : 
    1341                 :          17 :         ip_family(dst) = ip_family(ip);
    1342                 :          17 :         ip_bits(dst) = ip_maxbits(ip);
    1343                 :          17 :         SET_INET_VARSIZE(dst);
    1344                 :             : 
    1345                 :          34 :         PG_RETURN_INET_P(dst);
    1346                 :          17 : }
    1347                 :             : 
    1348                 :             : Datum
    1349                 :          17 : network_hostmask(PG_FUNCTION_ARGS)
    1350                 :             : {
    1351                 :          17 :         inet       *ip = PG_GETARG_INET_PP(0);
    1352                 :          17 :         inet       *dst;
    1353                 :          17 :         int                     byte;
    1354                 :          17 :         int                     bits;
    1355                 :          17 :         int                     maxbytes;
    1356                 :          17 :         unsigned char mask;
    1357                 :          17 :         unsigned char *b;
    1358                 :             : 
    1359                 :             :         /* make sure any unused bits are zeroed */
    1360                 :          17 :         dst = palloc0_object(inet);
    1361                 :             : 
    1362                 :          17 :         maxbytes = ip_addrsize(ip);
    1363                 :          17 :         bits = ip_maxbits(ip) - ip_bits(ip);
    1364                 :          17 :         b = ip_addr(dst);
    1365                 :             : 
    1366                 :          17 :         byte = maxbytes - 1;
    1367                 :             : 
    1368         [ +  + ]:          61 :         while (bits)
    1369                 :             :         {
    1370         [ +  + ]:          44 :                 if (bits >= 8)
    1371                 :             :                 {
    1372                 :          42 :                         mask = 0xff;
    1373                 :          42 :                         bits -= 8;
    1374                 :          42 :                 }
    1375                 :             :                 else
    1376                 :             :                 {
    1377                 :           2 :                         mask = 0xff >> (8 - bits);
    1378                 :           2 :                         bits = 0;
    1379                 :             :                 }
    1380                 :             : 
    1381                 :          44 :                 b[byte] = mask;
    1382                 :          44 :                 byte--;
    1383                 :             :         }
    1384                 :             : 
    1385                 :          17 :         ip_family(dst) = ip_family(ip);
    1386                 :          17 :         ip_bits(dst) = ip_maxbits(ip);
    1387                 :          17 :         SET_INET_VARSIZE(dst);
    1388                 :             : 
    1389                 :          34 :         PG_RETURN_INET_P(dst);
    1390                 :          17 : }
    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                 :          40 : inet_same_family(PG_FUNCTION_ARGS)
    1398                 :             : {
    1399                 :          40 :         inet       *a1 = PG_GETARG_INET_PP(0);
    1400                 :          40 :         inet       *a2 = PG_GETARG_INET_PP(1);
    1401                 :             : 
    1402                 :          80 :         PG_RETURN_BOOL(ip_family(a1) == ip_family(a2));
    1403                 :          40 : }
    1404                 :             : 
    1405                 :             : /*
    1406                 :             :  * Returns the smallest CIDR which contains both of the inputs.
    1407                 :             :  */
    1408                 :             : Datum
    1409                 :          39 : inet_merge(PG_FUNCTION_ARGS)
    1410                 :             : {
    1411                 :          39 :         inet       *a1 = PG_GETARG_INET_PP(0),
    1412                 :          39 :                            *a2 = PG_GETARG_INET_PP(1);
    1413                 :          39 :         int                     commonbits;
    1414                 :             : 
    1415         [ +  + ]:          39 :         if (ip_family(a1) != ip_family(a2))
    1416   [ +  -  +  - ]:           1 :                 ereport(ERROR,
    1417                 :             :                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1418                 :             :                                  errmsg("cannot merge addresses from different families")));
    1419                 :             : 
    1420                 :          76 :         commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
    1421         [ +  + ]:          38 :                                                         Min(ip_bits(a1), ip_bits(a2)));
    1422                 :             : 
    1423                 :          76 :         PG_RETURN_INET_P(cidr_set_masklen_internal(a1, commonbits));
    1424                 :          38 : }
    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                 :           0 : convert_network_to_scalar(Datum value, Oid typid, bool *failure)
    1436                 :             : {
    1437   [ #  #  #  # ]:           0 :         switch (typid)
    1438                 :             :         {
    1439                 :             :                 case INETOID:
    1440                 :             :                 case CIDROID:
    1441                 :             :                         {
    1442                 :           0 :                                 inet       *ip = DatumGetInetPP(value);
    1443                 :           0 :                                 int                     len;
    1444                 :           0 :                                 double          res;
    1445                 :           0 :                                 int                     i;
    1446                 :             : 
    1447                 :             :                                 /*
    1448                 :             :                                  * Note that we don't use the full address for IPv6.
    1449                 :             :                                  */
    1450         [ #  # ]:           0 :                                 if (ip_family(ip) == PGSQL_AF_INET)
    1451                 :           0 :                                         len = 4;
    1452                 :             :                                 else
    1453                 :           0 :                                         len = 5;
    1454                 :             : 
    1455                 :           0 :                                 res = ip_family(ip);
    1456         [ #  # ]:           0 :                                 for (i = 0; i < len; i++)
    1457                 :             :                                 {
    1458                 :           0 :                                         res *= 256;
    1459                 :           0 :                                         res += ip_addr(ip)[i];
    1460                 :           0 :                                 }
    1461                 :           0 :                                 return res;
    1462                 :           0 :                         }
    1463                 :             :                 case MACADDROID:
    1464                 :             :                         {
    1465                 :           0 :                                 macaddr    *mac = DatumGetMacaddrP(value);
    1466                 :           0 :                                 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                 :           0 :                         }
    1473                 :             :                 case MACADDR8OID:
    1474                 :             :                         {
    1475                 :           0 :                                 macaddr8   *mac = DatumGetMacaddr8P(value);
    1476                 :           0 :                                 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                 :           0 :                         }
    1483                 :             :         }
    1484                 :             : 
    1485                 :           0 :         *failure = true;
    1486                 :           0 :         return 0;
    1487                 :           0 : }
    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                 :       59690 : bitncmp(const unsigned char *l, const unsigned char *r, int n)
    1503                 :             : {
    1504                 :       59690 :         unsigned int lb,
    1505                 :             :                                 rb;
    1506                 :       59690 :         int                     x,
    1507                 :             :                                 b;
    1508                 :             : 
    1509                 :       59690 :         b = n / 8;
    1510                 :       59690 :         x = memcmp(l, r, b);
    1511   [ +  +  +  + ]:       59690 :         if (x || (n % 8) == 0)
    1512                 :       59650 :                 return x;
    1513                 :             : 
    1514                 :          40 :         lb = l[b];
    1515                 :          40 :         rb = r[b];
    1516         [ +  + ]:          71 :         for (b = n % 8; b > 0; b--)
    1517                 :             :         {
    1518         [ +  + ]:          49 :                 if (IS_HIGHBIT_SET(lb) != IS_HIGHBIT_SET(rb))
    1519                 :             :                 {
    1520         [ +  + ]:          18 :                         if (IS_HIGHBIT_SET(lb))
    1521                 :          10 :                                 return 1;
    1522                 :           8 :                         return -1;
    1523                 :             :                 }
    1524                 :          31 :                 lb <<= 1;
    1525                 :          31 :                 rb <<= 1;
    1526                 :          31 :         }
    1527                 :          22 :         return 0;
    1528                 :       59690 : }
    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                 :          38 : bitncommon(const unsigned char *l, const unsigned char *r, int n)
    1537                 :             : {
    1538                 :          38 :         int                     byte,
    1539                 :             :                                 nbits;
    1540                 :             : 
    1541                 :             :         /* number of bits to examine in last byte */
    1542                 :          38 :         nbits = n % 8;
    1543                 :             : 
    1544                 :             :         /* check whole bytes */
    1545         [ +  + ]:         204 :         for (byte = 0; byte < n / 8; byte++)
    1546                 :             :         {
    1547         [ +  + ]:         172 :                 if (l[byte] != r[byte])
    1548                 :             :                 {
    1549                 :             :                         /* at least one bit in the last byte is not common */
    1550                 :           6 :                         nbits = 7;
    1551                 :           6 :                         break;
    1552                 :             :                 }
    1553                 :         166 :         }
    1554                 :             : 
    1555                 :             :         /* check bits in last partial byte */
    1556         [ +  + ]:          38 :         if (nbits != 0)
    1557                 :             :         {
    1558                 :             :                 /* calculate diff of first non-matching bytes */
    1559                 :          12 :                 unsigned int diff = l[byte] ^ r[byte];
    1560                 :             : 
    1561                 :             :                 /* compare the bits from the most to the least */
    1562         [ +  + ]:          28 :                 while ((diff >> (8 - nbits)) != 0)
    1563                 :          16 :                         nbits--;
    1564                 :          12 :         }
    1565                 :             : 
    1566                 :          76 :         return (8 * byte) + nbits;
    1567                 :          38 : }
    1568                 :             : 
    1569                 :             : 
    1570                 :             : /*
    1571                 :             :  * Verify a CIDR address is OK (doesn't have bits set past the masklen)
    1572                 :             :  */
    1573                 :             : static bool
    1574                 :         258 : addressOK(unsigned char *a, int bits, int family)
    1575                 :             : {
    1576                 :         258 :         int                     byte;
    1577                 :         258 :         int                     nbits;
    1578                 :         258 :         int                     maxbits;
    1579                 :         258 :         int                     maxbytes;
    1580                 :         258 :         unsigned char mask;
    1581                 :             : 
    1582         [ +  + ]:         258 :         if (family == PGSQL_AF_INET)
    1583                 :             :         {
    1584                 :         205 :                 maxbits = 32;
    1585                 :         205 :                 maxbytes = 4;
    1586                 :         205 :         }
    1587                 :             :         else
    1588                 :             :         {
    1589                 :          53 :                 maxbits = 128;
    1590                 :          53 :                 maxbytes = 16;
    1591                 :             :         }
    1592         [ +  - ]:         258 :         Assert(bits <= maxbits);
    1593                 :             : 
    1594         [ +  + ]:         258 :         if (bits == maxbits)
    1595                 :         103 :                 return true;
    1596                 :             : 
    1597                 :         155 :         byte = bits / 8;
    1598                 :             : 
    1599                 :         155 :         nbits = bits % 8;
    1600                 :         155 :         mask = 0xff;
    1601         [ +  + ]:         155 :         if (bits != 0)
    1602                 :         147 :                 mask >>= nbits;
    1603                 :             : 
    1604         [ +  + ]:         571 :         while (byte < maxbytes)
    1605                 :             :         {
    1606         [ +  + ]:         421 :                 if ((a[byte] & mask) != 0)
    1607                 :           5 :                         return false;
    1608                 :         416 :                 mask = 0xff;
    1609                 :         416 :                 byte++;
    1610                 :             :         }
    1611                 :             : 
    1612                 :         150 :         return true;
    1613                 :         258 : }
    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                 :           8 : network_scan_first(Datum in)
    1624                 :             : {
    1625                 :           8 :         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                 :           8 : network_scan_last(Datum in)
    1638                 :             : {
    1639                 :           8 :         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                 :           0 :         char            remote_host[NI_MAXHOST];
    1653                 :           0 :         int                     ret;
    1654                 :             : 
    1655         [ #  # ]:           0 :         if (port == NULL)
    1656                 :           0 :                 PG_RETURN_NULL();
    1657                 :             : 
    1658         [ #  # ]:           0 :         switch (port->raddr.addr.ss_family)
    1659                 :             :         {
    1660                 :             :                 case AF_INET:
    1661                 :             :                 case AF_INET6:
    1662                 :           0 :                         break;
    1663                 :             :                 default:
    1664                 :           0 :                         PG_RETURN_NULL();
    1665                 :           0 :         }
    1666                 :             : 
    1667                 :           0 :         remote_host[0] = '\0';
    1668                 :             : 
    1669                 :           0 :         ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
    1670                 :           0 :                                                          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                 :           0 : }
    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                 :           0 :         char            remote_port[NI_MAXSERV];
    1690                 :           0 :         int                     ret;
    1691                 :             : 
    1692         [ #  # ]:           0 :         if (port == NULL)
    1693                 :           0 :                 PG_RETURN_NULL();
    1694                 :             : 
    1695         [ #  # ]:           0 :         switch (port->raddr.addr.ss_family)
    1696                 :             :         {
    1697                 :             :                 case AF_INET:
    1698                 :             :                 case AF_INET6:
    1699                 :           0 :                         break;
    1700                 :             :                 default:
    1701                 :           0 :                         PG_RETURN_NULL();
    1702                 :           0 :         }
    1703                 :             : 
    1704                 :           0 :         remote_port[0] = '\0';
    1705                 :             : 
    1706                 :           0 :         ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
    1707                 :             :                                                          NULL, 0,
    1708                 :           0 :                                                          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                 :           0 : }
    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                 :           0 :         char            local_host[NI_MAXHOST];
    1725                 :           0 :         int                     ret;
    1726                 :             : 
    1727         [ #  # ]:           0 :         if (port == NULL)
    1728                 :           0 :                 PG_RETURN_NULL();
    1729                 :             : 
    1730         [ #  # ]:           0 :         switch (port->laddr.addr.ss_family)
    1731                 :             :         {
    1732                 :             :                 case AF_INET:
    1733                 :             :                 case AF_INET6:
    1734                 :           0 :                         break;
    1735                 :             :                 default:
    1736                 :           0 :                         PG_RETURN_NULL();
    1737                 :           0 :         }
    1738                 :             : 
    1739                 :           0 :         local_host[0] = '\0';
    1740                 :             : 
    1741                 :           0 :         ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
    1742                 :           0 :                                                          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                 :           0 : }
    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                 :           0 :         char            local_port[NI_MAXSERV];
    1762                 :           0 :         int                     ret;
    1763                 :             : 
    1764         [ #  # ]:           0 :         if (port == NULL)
    1765                 :           0 :                 PG_RETURN_NULL();
    1766                 :             : 
    1767         [ #  # ]:           0 :         switch (port->laddr.addr.ss_family)
    1768                 :             :         {
    1769                 :             :                 case AF_INET:
    1770                 :             :                 case AF_INET6:
    1771                 :           0 :                         break;
    1772                 :             :                 default:
    1773                 :           0 :                         PG_RETURN_NULL();
    1774                 :           0 :         }
    1775                 :             : 
    1776                 :           0 :         local_port[0] = '\0';
    1777                 :             : 
    1778                 :           0 :         ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
    1779                 :             :                                                          NULL, 0,
    1780                 :           0 :                                                          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                 :           0 : }
    1787                 :             : 
    1788                 :             : 
    1789                 :             : Datum
    1790                 :          17 : inetnot(PG_FUNCTION_ARGS)
    1791                 :             : {
    1792                 :          17 :         inet       *ip = PG_GETARG_INET_PP(0);
    1793                 :          17 :         inet       *dst;
    1794                 :             : 
    1795                 :          17 :         dst = palloc0_object(inet);
    1796                 :             : 
    1797                 :             :         {
    1798                 :          17 :                 int                     nb = ip_addrsize(ip);
    1799                 :          17 :                 unsigned char *pip = ip_addr(ip);
    1800                 :          17 :                 unsigned char *pdst = ip_addr(dst);
    1801                 :             : 
    1802         [ +  + ]:         121 :                 while (--nb >= 0)
    1803                 :         104 :                         pdst[nb] = ~pip[nb];
    1804                 :          17 :         }
    1805                 :          17 :         ip_bits(dst) = ip_bits(ip);
    1806                 :             : 
    1807                 :          17 :         ip_family(dst) = ip_family(ip);
    1808                 :          17 :         SET_INET_VARSIZE(dst);
    1809                 :             : 
    1810                 :          34 :         PG_RETURN_INET_P(dst);
    1811                 :          17 : }
    1812                 :             : 
    1813                 :             : 
    1814                 :             : Datum
    1815                 :          17 : inetand(PG_FUNCTION_ARGS)
    1816                 :             : {
    1817                 :          17 :         inet       *ip = PG_GETARG_INET_PP(0);
    1818                 :          17 :         inet       *ip2 = PG_GETARG_INET_PP(1);
    1819                 :          17 :         inet       *dst;
    1820                 :             : 
    1821                 :          17 :         dst = palloc0_object(inet);
    1822                 :             : 
    1823         [ +  - ]:          17 :         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                 :          17 :                 int                     nb = ip_addrsize(ip);
    1830                 :          17 :                 unsigned char *pip = ip_addr(ip);
    1831                 :          17 :                 unsigned char *pip2 = ip_addr(ip2);
    1832                 :          17 :                 unsigned char *pdst = ip_addr(dst);
    1833                 :             : 
    1834         [ +  + ]:         121 :                 while (--nb >= 0)
    1835                 :         104 :                         pdst[nb] = pip[nb] & pip2[nb];
    1836                 :          17 :         }
    1837         [ +  + ]:          17 :         ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
    1838                 :             : 
    1839                 :          17 :         ip_family(dst) = ip_family(ip);
    1840                 :          17 :         SET_INET_VARSIZE(dst);
    1841                 :             : 
    1842                 :          34 :         PG_RETURN_INET_P(dst);
    1843                 :          17 : }
    1844                 :             : 
    1845                 :             : 
    1846                 :             : Datum
    1847                 :          17 : inetor(PG_FUNCTION_ARGS)
    1848                 :             : {
    1849                 :          17 :         inet       *ip = PG_GETARG_INET_PP(0);
    1850                 :          17 :         inet       *ip2 = PG_GETARG_INET_PP(1);
    1851                 :          17 :         inet       *dst;
    1852                 :             : 
    1853                 :          17 :         dst = palloc0_object(inet);
    1854                 :             : 
    1855         [ +  - ]:          17 :         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                 :          17 :                 int                     nb = ip_addrsize(ip);
    1862                 :          17 :                 unsigned char *pip = ip_addr(ip);
    1863                 :          17 :                 unsigned char *pip2 = ip_addr(ip2);
    1864                 :          17 :                 unsigned char *pdst = ip_addr(dst);
    1865                 :             : 
    1866         [ +  + ]:         121 :                 while (--nb >= 0)
    1867                 :         104 :                         pdst[nb] = pip[nb] | pip2[nb];
    1868                 :          17 :         }
    1869         [ +  + ]:          17 :         ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
    1870                 :             : 
    1871                 :          17 :         ip_family(dst) = ip_family(ip);
    1872                 :          17 :         SET_INET_VARSIZE(dst);
    1873                 :             : 
    1874                 :          34 :         PG_RETURN_INET_P(dst);
    1875                 :          17 : }
    1876                 :             : 
    1877                 :             : 
    1878                 :             : static inet *
    1879                 :         857 : internal_inetpl(inet *ip, int64 addend)
    1880                 :             : {
    1881                 :         857 :         inet       *dst;
    1882                 :             : 
    1883                 :         857 :         dst = palloc0_object(inet);
    1884                 :             : 
    1885                 :             :         {
    1886                 :         857 :                 int                     nb = ip_addrsize(ip);
    1887                 :         857 :                 unsigned char *pip = ip_addr(ip);
    1888                 :         857 :                 unsigned char *pdst = ip_addr(dst);
    1889                 :         857 :                 int                     carry = 0;
    1890                 :             : 
    1891         [ +  + ]:        6229 :                 while (--nb >= 0)
    1892                 :             :                 {
    1893                 :        5372 :                         carry = pip[nb] + (int) (addend & 0xFF) + carry;
    1894                 :        5372 :                         pdst[nb] = (unsigned char) (carry & 0xFF);
    1895                 :        5372 :                         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                 :        5372 :                         addend &= ~((int64) 0xFF);
    1907                 :        5372 :                         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   [ +  +  -  + ]:         878 :                 if (!((addend == 0 && carry == 0) ||
    1916         [ +  + ]:          23 :                           (addend == -1 && carry == 1)))
    1917   [ +  -  +  - ]:           2 :                         ereport(ERROR,
    1918                 :             :                                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1919                 :             :                                          errmsg("result is out of range")));
    1920                 :         855 :         }
    1921                 :             : 
    1922                 :         855 :         ip_bits(dst) = ip_bits(ip);
    1923                 :         855 :         ip_family(dst) = ip_family(ip);
    1924                 :         855 :         SET_INET_VARSIZE(dst);
    1925                 :             : 
    1926                 :        1710 :         return dst;
    1927                 :         855 : }
    1928                 :             : 
    1929                 :             : 
    1930                 :             : Datum
    1931                 :         835 : inetpl(PG_FUNCTION_ARGS)
    1932                 :             : {
    1933                 :         835 :         inet       *ip = PG_GETARG_INET_PP(0);
    1934                 :         835 :         int64           addend = PG_GETARG_INT64(1);
    1935                 :             : 
    1936                 :        1670 :         PG_RETURN_INET_P(internal_inetpl(ip, addend));
    1937                 :         835 : }
    1938                 :             : 
    1939                 :             : 
    1940                 :             : Datum
    1941                 :          22 : inetmi_int8(PG_FUNCTION_ARGS)
    1942                 :             : {
    1943                 :          22 :         inet       *ip = PG_GETARG_INET_PP(0);
    1944                 :          22 :         int64           addend = PG_GETARG_INT64(1);
    1945                 :             : 
    1946                 :          44 :         PG_RETURN_INET_P(internal_inetpl(ip, -addend));
    1947                 :          22 : }
    1948                 :             : 
    1949                 :             : 
    1950                 :             : Datum
    1951                 :          24 : inetmi(PG_FUNCTION_ARGS)
    1952                 :             : {
    1953                 :          24 :         inet       *ip = PG_GETARG_INET_PP(0);
    1954                 :          24 :         inet       *ip2 = PG_GETARG_INET_PP(1);
    1955                 :          24 :         int64           res = 0;
    1956                 :             : 
    1957         [ +  - ]:          24 :         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                 :          24 :                 int                     nb = ip_addrsize(ip);
    1970                 :          24 :                 int                     byte = 0;
    1971                 :          24 :                 unsigned char *pip = ip_addr(ip);
    1972                 :          24 :                 unsigned char *pip2 = ip_addr(ip2);
    1973                 :          24 :                 int                     carry = 1;
    1974                 :             : 
    1975         [ +  + ]:         212 :                 while (--nb >= 0)
    1976                 :             :                 {
    1977                 :         190 :                         int                     lobyte;
    1978                 :             : 
    1979                 :         190 :                         carry = pip[nb] + (~pip2[nb] & 0xFF) + carry;
    1980                 :         190 :                         lobyte = carry & 0xFF;
    1981         [ +  + ]:         190 :                         if (byte < sizeof(int64))
    1982                 :             :                         {
    1983                 :         128 :                                 res |= ((int64) lobyte) << (byte * 8);
    1984                 :         128 :                         }
    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   [ +  +  +  + ]:          62 :                                 if ((res < 0) ? (lobyte != 0xFF) : (lobyte != 0))
    1993   [ +  -  +  - ]:           2 :                                         ereport(ERROR,
    1994                 :             :                                                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1995                 :             :                                                          errmsg("result is out of range")));
    1996                 :             :                         }
    1997                 :         188 :                         carry >>= 8;
    1998                 :         188 :                         byte++;
    1999                 :         188 :                 }
    2000                 :             : 
    2001                 :             :                 /*
    2002                 :             :                  * If input is narrower than int64, overflow is not possible, but we
    2003                 :             :                  * have to do proper sign extension.
    2004                 :             :                  */
    2005   [ +  +  +  + ]:          22 :                 if (carry == 0 && byte < sizeof(int64))
    2006                 :           2 :                         res |= ((uint64) (int64) -1) << (byte * 8);
    2007                 :          22 :         }
    2008                 :             : 
    2009                 :          44 :         PG_RETURN_INT64(res);
    2010                 :          22 : }
    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                 :           8 : clean_ipv6_addr(int addr_family, char *addr)
    2029                 :             : {
    2030         [ +  + ]:           8 :         if (addr_family == AF_INET6)
    2031                 :             :         {
    2032                 :           4 :                 char       *pct = strchr(addr, '%');
    2033                 :             : 
    2034         [ +  - ]:           4 :                 if (pct)
    2035                 :           0 :                         *pct = '\0';
    2036                 :           4 :         }
    2037                 :           8 : }
        

Generated by: LCOV version 2.3.2-1