LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - network.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 69.8 % 708 494 214 494
Current Date: 2024-04-14 14:21:10 Functions: 80.0 % 70 56 14 56
Baseline: 16@8cea358b128 Branches: 58.0 % 880 510 370 510
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 69.8 % 708 494 214 494
Function coverage date bins:
(240..) days: 80.0 % 70 56 14 56
Branch coverage date bins:
(240..) days: 58.0 % 880 510 370 510

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

Generated by: LCOV version 2.1-beta2-3-g6141622