LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - network.c (source / functions) Coverage Total Hit LBC UBC GBC GNC CBC EUB ECB DCB
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 77.4 % 700 542 158 4 538 4
Current Date: 2025-09-06 07:49:51 +0900 Functions: 85.7 % 70 60 10 1 59
Baseline: lcov-20250906-005545-baseline Branches: 65.1 % 438 285 12 141 38 2 245 126 302
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 100.0 % 4 4 4
(30,360] days: 60.0 % 5 3 2 3
(360..) days: 77.4 % 691 535 156 535
Function coverage date bins:
(360..) days: 85.7 % 70 60 10 1 59
Branch coverage date bins:
(7,30] days: 100.0 % 2 2 2
(30,360] days: 75.0 % 4 3 1 3
(360..) days: 32.6 % 860 280 12 140 38 242 126 302

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

Generated by: LCOV version 2.4-beta