LCOV - code coverage report
Current view: top level - src/backend/utils/adt - network.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta1 Lines: 418 613 68.2 %
Date: 2019-06-16 15:06:48 Functions: 51 66 77.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  PostgreSQL type definitions for the INET and CIDR types.
       3             :  *
       4             :  *  src/backend/utils/adt/network.c
       5             :  *
       6             :  *  Jon Postel RIP 16 Oct 1998
       7             :  */
       8             : 
       9             : #include "postgres.h"
      10             : 
      11             : #include <sys/socket.h>
      12             : #include <netinet/in.h>
      13             : #include <arpa/inet.h>
      14             : 
      15             : #include "access/stratnum.h"
      16             : #include "catalog/pg_opfamily.h"
      17             : #include "catalog/pg_type.h"
      18             : #include "common/ip.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/hashutils.h"
      28             : #include "utils/inet.h"
      29             : #include "utils/lsyscache.h"
      30             : 
      31             : 
      32             : static int32 network_cmp_internal(inet *a1, inet *a2);
      33             : static List *match_network_function(Node *leftop,
      34             :                                     Node *rightop,
      35             :                                     int indexarg,
      36             :                                     Oid funcid,
      37             :                                     Oid opfamily);
      38             : static List *match_network_subset(Node *leftop,
      39             :                                   Node *rightop,
      40             :                                   bool is_eq,
      41             :                                   Oid opfamily);
      42             : static bool addressOK(unsigned char *a, int bits, int family);
      43             : static inet *internal_inetpl(inet *ip, int64 addend);
      44             : 
      45             : 
      46             : /*
      47             :  * Common INET/CIDR input routine
      48             :  */
      49             : static inet *
      50        2708 : network_in(char *src, bool is_cidr)
      51             : {
      52             :     int         bits;
      53             :     inet       *dst;
      54             : 
      55        2708 :     dst = (inet *) palloc0(sizeof(inet));
      56             : 
      57             :     /*
      58             :      * First, check to see if this is an IPv6 or IPv4 address.  IPv6 addresses
      59             :      * will have a : somewhere in them (several, in fact) so if there is one
      60             :      * present, assume it's V6, otherwise assume it's V4.
      61             :      */
      62             : 
      63        2708 :     if (strchr(src, ':') != NULL)
      64         368 :         ip_family(dst) = PGSQL_AF_INET6;
      65             :     else
      66        2340 :         ip_family(dst) = PGSQL_AF_INET;
      67             : 
      68        3418 :     bits = inet_net_pton(ip_family(dst), src, ip_addr(dst),
      69         710 :                          is_cidr ? ip_addrsize(dst) : -1);
      70        2708 :     if ((bits < 0) || (bits > ip_maxbits(dst)))
      71           4 :         ereport(ERROR,
      72             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      73             :         /* translator: first %s is inet or cidr */
      74             :                  errmsg("invalid input syntax for type %s: \"%s\"",
      75             :                         is_cidr ? "cidr" : "inet", src)));
      76             : 
      77             :     /*
      78             :      * Error check: CIDR values must not have any bits set beyond the masklen.
      79             :      */
      80        2704 :     if (is_cidr)
      81             :     {
      82         706 :         if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
      83          12 :             ereport(ERROR,
      84             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      85             :                      errmsg("invalid cidr value: \"%s\"", src),
      86             :                      errdetail("Value has bits set to right of mask.")));
      87             :     }
      88             : 
      89        2692 :     ip_bits(dst) = bits;
      90        2692 :     SET_INET_VARSIZE(dst);
      91             : 
      92        2692 :     return dst;
      93             : }
      94             : 
      95             : Datum
      96        1998 : inet_in(PG_FUNCTION_ARGS)
      97             : {
      98        1998 :     char       *src = PG_GETARG_CSTRING(0);
      99             : 
     100        1998 :     PG_RETURN_INET_P(network_in(src, false));
     101             : }
     102             : 
     103             : Datum
     104         710 : cidr_in(PG_FUNCTION_ARGS)
     105             : {
     106         710 :     char       *src = PG_GETARG_CSTRING(0);
     107             : 
     108         710 :     PG_RETURN_INET_P(network_in(src, true));
     109             : }
     110             : 
     111             : 
     112             : /*
     113             :  * Common INET/CIDR output routine
     114             :  */
     115             : static char *
     116        5496 : network_out(inet *src, bool is_cidr)
     117             : {
     118             :     char        tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
     119             :     char       *dst;
     120             :     int         len;
     121             : 
     122        5496 :     dst = inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),
     123             :                         tmp, sizeof(tmp));
     124        5496 :     if (dst == NULL)
     125           0 :         ereport(ERROR,
     126             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     127             :                  errmsg("could not format inet value: %m")));
     128             : 
     129             :     /* For CIDR, add /n if not present */
     130        5496 :     if (is_cidr && strchr(tmp, '/') == NULL)
     131             :     {
     132         406 :         len = strlen(tmp);
     133         406 :         snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
     134             :     }
     135             : 
     136        5496 :     return pstrdup(tmp);
     137             : }
     138             : 
     139             : Datum
     140        3410 : inet_out(PG_FUNCTION_ARGS)
     141             : {
     142        3410 :     inet       *src = PG_GETARG_INET_PP(0);
     143             : 
     144        3410 :     PG_RETURN_CSTRING(network_out(src, false));
     145             : }
     146             : 
     147             : Datum
     148        2086 : cidr_out(PG_FUNCTION_ARGS)
     149             : {
     150        2086 :     inet       *src = PG_GETARG_INET_PP(0);
     151             : 
     152        2086 :     PG_RETURN_CSTRING(network_out(src, true));
     153             : }
     154             : 
     155             : 
     156             : /*
     157             :  *      network_recv        - converts external binary format to inet
     158             :  *
     159             :  * The external representation is (one byte apiece for)
     160             :  * family, bits, is_cidr, address length, address in network byte order.
     161             :  *
     162             :  * Presence of is_cidr is largely for historical reasons, though it might
     163             :  * allow some code-sharing on the client side.  We send it correctly on
     164             :  * output, but ignore the value on input.
     165             :  */
     166             : static inet *
     167           0 : network_recv(StringInfo buf, bool is_cidr)
     168             : {
     169             :     inet       *addr;
     170             :     char       *addrptr;
     171             :     int         bits;
     172             :     int         nb,
     173             :                 i;
     174             : 
     175             :     /* make sure any unused bits in a CIDR value are zeroed */
     176           0 :     addr = (inet *) palloc0(sizeof(inet));
     177             : 
     178           0 :     ip_family(addr) = pq_getmsgbyte(buf);
     179           0 :     if (ip_family(addr) != PGSQL_AF_INET &&
     180           0 :         ip_family(addr) != PGSQL_AF_INET6)
     181           0 :         ereport(ERROR,
     182             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     183             :         /* translator: %s is inet or cidr */
     184             :                  errmsg("invalid address family in external \"%s\" value",
     185             :                         is_cidr ? "cidr" : "inet")));
     186           0 :     bits = pq_getmsgbyte(buf);
     187           0 :     if (bits < 0 || bits > ip_maxbits(addr))
     188           0 :         ereport(ERROR,
     189             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     190             :         /* translator: %s is inet or cidr */
     191             :                  errmsg("invalid bits in external \"%s\" value",
     192             :                         is_cidr ? "cidr" : "inet")));
     193           0 :     ip_bits(addr) = bits;
     194           0 :     i = pq_getmsgbyte(buf);     /* ignore is_cidr */
     195           0 :     nb = pq_getmsgbyte(buf);
     196           0 :     if (nb != ip_addrsize(addr))
     197           0 :         ereport(ERROR,
     198             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     199             :         /* translator: %s is inet or cidr */
     200             :                  errmsg("invalid length in external \"%s\" value",
     201             :                         is_cidr ? "cidr" : "inet")));
     202             : 
     203           0 :     addrptr = (char *) ip_addr(addr);
     204           0 :     for (i = 0; i < nb; i++)
     205           0 :         addrptr[i] = pq_getmsgbyte(buf);
     206             : 
     207             :     /*
     208             :      * Error check: CIDR values must not have any bits set beyond the masklen.
     209             :      */
     210           0 :     if (is_cidr)
     211             :     {
     212           0 :         if (!addressOK(ip_addr(addr), bits, ip_family(addr)))
     213           0 :             ereport(ERROR,
     214             :                     (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     215             :                      errmsg("invalid external \"cidr\" value"),
     216             :                      errdetail("Value has bits set to right of mask.")));
     217             :     }
     218             : 
     219           0 :     SET_INET_VARSIZE(addr);
     220             : 
     221           0 :     return addr;
     222             : }
     223             : 
     224             : Datum
     225           0 : inet_recv(PG_FUNCTION_ARGS)
     226             : {
     227           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     228             : 
     229           0 :     PG_RETURN_INET_P(network_recv(buf, false));
     230             : }
     231             : 
     232             : Datum
     233           0 : cidr_recv(PG_FUNCTION_ARGS)
     234             : {
     235           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     236             : 
     237           0 :     PG_RETURN_INET_P(network_recv(buf, true));
     238             : }
     239             : 
     240             : 
     241             : /*
     242             :  *      network_send        - converts inet to binary format
     243             :  */
     244             : static bytea *
     245           0 : network_send(inet *addr, bool is_cidr)
     246             : {
     247             :     StringInfoData buf;
     248             :     char       *addrptr;
     249             :     int         nb,
     250             :                 i;
     251             : 
     252           0 :     pq_begintypsend(&buf);
     253           0 :     pq_sendbyte(&buf, ip_family(addr));
     254           0 :     pq_sendbyte(&buf, ip_bits(addr));
     255           0 :     pq_sendbyte(&buf, is_cidr);
     256           0 :     nb = ip_addrsize(addr);
     257           0 :     if (nb < 0)
     258           0 :         nb = 0;
     259           0 :     pq_sendbyte(&buf, nb);
     260           0 :     addrptr = (char *) ip_addr(addr);
     261           0 :     for (i = 0; i < nb; i++)
     262           0 :         pq_sendbyte(&buf, addrptr[i]);
     263           0 :     return pq_endtypsend(&buf);
     264             : }
     265             : 
     266             : Datum
     267           0 : inet_send(PG_FUNCTION_ARGS)
     268             : {
     269           0 :     inet       *addr = PG_GETARG_INET_PP(0);
     270             : 
     271           0 :     PG_RETURN_BYTEA_P(network_send(addr, false));
     272             : }
     273             : 
     274             : Datum
     275           0 : cidr_send(PG_FUNCTION_ARGS)
     276             : {
     277           0 :     inet       *addr = PG_GETARG_INET_PP(0);
     278             : 
     279           0 :     PG_RETURN_BYTEA_P(network_send(addr, true));
     280             : }
     281             : 
     282             : 
     283             : Datum
     284        1720 : inet_to_cidr(PG_FUNCTION_ARGS)
     285             : {
     286        1720 :     inet       *src = PG_GETARG_INET_PP(0);
     287             :     int         bits;
     288             : 
     289        1720 :     bits = ip_bits(src);
     290             : 
     291             :     /* safety check */
     292        1720 :     if ((bits < 0) || (bits > ip_maxbits(src)))
     293           0 :         elog(ERROR, "invalid inet bit length: %d", bits);
     294             : 
     295        1720 :     PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
     296             : }
     297             : 
     298             : Datum
     299         100 : inet_set_masklen(PG_FUNCTION_ARGS)
     300             : {
     301         100 :     inet       *src = PG_GETARG_INET_PP(0);
     302         100 :     int         bits = PG_GETARG_INT32(1);
     303             :     inet       *dst;
     304             : 
     305         100 :     if (bits == -1)
     306          32 :         bits = ip_maxbits(src);
     307             : 
     308         100 :     if ((bits < 0) || (bits > ip_maxbits(src)))
     309           0 :         ereport(ERROR,
     310             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     311             :                  errmsg("invalid mask length: %d", bits)));
     312             : 
     313             :     /* clone the original data */
     314         100 :     dst = (inet *) palloc(VARSIZE_ANY(src));
     315         100 :     memcpy(dst, src, VARSIZE_ANY(src));
     316             : 
     317         100 :     ip_bits(dst) = bits;
     318             : 
     319         100 :     PG_RETURN_INET_P(dst);
     320             : }
     321             : 
     322             : Datum
     323           0 : cidr_set_masklen(PG_FUNCTION_ARGS)
     324             : {
     325           0 :     inet       *src = PG_GETARG_INET_PP(0);
     326           0 :     int         bits = PG_GETARG_INT32(1);
     327             : 
     328           0 :     if (bits == -1)
     329           0 :         bits = ip_maxbits(src);
     330             : 
     331           0 :     if ((bits < 0) || (bits > ip_maxbits(src)))
     332           0 :         ereport(ERROR,
     333             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     334             :                  errmsg("invalid mask length: %d", bits)));
     335             : 
     336           0 :     PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
     337             : }
     338             : 
     339             : /*
     340             :  * Copy src and set mask length to 'bits' (which must be valid for the family)
     341             :  */
     342             : inet *
     343        1856 : cidr_set_masklen_internal(const inet *src, int bits)
     344             : {
     345        1856 :     inet       *dst = (inet *) palloc0(sizeof(inet));
     346             : 
     347        1856 :     ip_family(dst) = ip_family(src);
     348        1856 :     ip_bits(dst) = bits;
     349             : 
     350        1856 :     if (bits > 0)
     351             :     {
     352             :         Assert(bits <= ip_maxbits(dst));
     353             : 
     354             :         /* Clone appropriate bytes of the address, leaving the rest 0 */
     355        1856 :         memcpy(ip_addr(dst), ip_addr(src), (bits + 7) / 8);
     356             : 
     357             :         /* Clear any unwanted bits in the last partial byte */
     358        1856 :         if (bits % 8)
     359          24 :             ip_addr(dst)[bits / 8] &= ~(0xFF >> (bits % 8));
     360             :     }
     361             : 
     362             :     /* Set varlena header correctly */
     363        1856 :     SET_INET_VARSIZE(dst);
     364             : 
     365        1856 :     return dst;
     366             : }
     367             : 
     368             : /*
     369             :  *  Basic comparison function for sorting and inet/cidr comparisons.
     370             :  *
     371             :  * Comparison is first on the common bits of the network part, then on
     372             :  * the length of the network part, and then on the whole unmasked address.
     373             :  * The effect is that the network part is the major sort key, and for
     374             :  * equal network parts we sort on the host part.  Note this is only sane
     375             :  * for CIDR if address bits to the right of the mask are guaranteed zero;
     376             :  * otherwise logically-equal CIDRs might compare different.
     377             :  */
     378             : 
     379             : static int32
     380       81292 : network_cmp_internal(inet *a1, inet *a2)
     381             : {
     382       81292 :     if (ip_family(a1) == ip_family(a2))
     383             :     {
     384             :         int         order;
     385             : 
     386      144272 :         order = bitncmp(ip_addr(a1), ip_addr(a2),
     387      144272 :                         Min(ip_bits(a1), ip_bits(a2)));
     388       72136 :         if (order != 0)
     389       64222 :             return order;
     390        7914 :         order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
     391        7914 :         if (order != 0)
     392        1444 :             return order;
     393        6470 :         return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));
     394             :     }
     395             : 
     396        9156 :     return ip_family(a1) - ip_family(a2);
     397             : }
     398             : 
     399             : Datum
     400       32800 : network_cmp(PG_FUNCTION_ARGS)
     401             : {
     402       32800 :     inet       *a1 = PG_GETARG_INET_PP(0);
     403       32800 :     inet       *a2 = PG_GETARG_INET_PP(1);
     404             : 
     405       32800 :     PG_RETURN_INT32(network_cmp_internal(a1, a2));
     406             : }
     407             : 
     408             : /*
     409             :  *  Boolean ordering tests.
     410             :  */
     411             : Datum
     412       11034 : network_lt(PG_FUNCTION_ARGS)
     413             : {
     414       11034 :     inet       *a1 = PG_GETARG_INET_PP(0);
     415       11034 :     inet       *a2 = PG_GETARG_INET_PP(1);
     416             : 
     417       11034 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) < 0);
     418             : }
     419             : 
     420             : Datum
     421        9182 : network_le(PG_FUNCTION_ARGS)
     422             : {
     423        9182 :     inet       *a1 = PG_GETARG_INET_PP(0);
     424        9182 :     inet       *a2 = PG_GETARG_INET_PP(1);
     425             : 
     426        9182 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) <= 0);
     427             : }
     428             : 
     429             : Datum
     430        6968 : network_eq(PG_FUNCTION_ARGS)
     431             : {
     432        6968 :     inet       *a1 = PG_GETARG_INET_PP(0);
     433        6968 :     inet       *a2 = PG_GETARG_INET_PP(1);
     434             : 
     435        6968 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) == 0);
     436             : }
     437             : 
     438             : Datum
     439        9518 : network_ge(PG_FUNCTION_ARGS)
     440             : {
     441        9518 :     inet       *a1 = PG_GETARG_INET_PP(0);
     442        9518 :     inet       *a2 = PG_GETARG_INET_PP(1);
     443             : 
     444        9518 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) >= 0);
     445             : }
     446             : 
     447             : Datum
     448       11466 : network_gt(PG_FUNCTION_ARGS)
     449             : {
     450       11466 :     inet       *a1 = PG_GETARG_INET_PP(0);
     451       11466 :     inet       *a2 = PG_GETARG_INET_PP(1);
     452             : 
     453       11466 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) > 0);
     454             : }
     455             : 
     456             : Datum
     457          68 : network_ne(PG_FUNCTION_ARGS)
     458             : {
     459          68 :     inet       *a1 = PG_GETARG_INET_PP(0);
     460          68 :     inet       *a2 = PG_GETARG_INET_PP(1);
     461             : 
     462          68 :     PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
     463             : }
     464             : 
     465             : /*
     466             :  * MIN/MAX support functions.
     467             :  */
     468             : Datum
     469         128 : network_smaller(PG_FUNCTION_ARGS)
     470             : {
     471         128 :     inet       *a1 = PG_GETARG_INET_PP(0);
     472         128 :     inet       *a2 = PG_GETARG_INET_PP(1);
     473             : 
     474         128 :     if (network_cmp_internal(a1, a2) < 0)
     475          76 :         PG_RETURN_INET_P(a1);
     476             :     else
     477          52 :         PG_RETURN_INET_P(a2);
     478             : }
     479             : 
     480             : Datum
     481         128 : network_larger(PG_FUNCTION_ARGS)
     482             : {
     483         128 :     inet       *a1 = PG_GETARG_INET_PP(0);
     484         128 :     inet       *a2 = PG_GETARG_INET_PP(1);
     485             : 
     486         128 :     if (network_cmp_internal(a1, a2) > 0)
     487         104 :         PG_RETURN_INET_P(a1);
     488             :     else
     489          24 :         PG_RETURN_INET_P(a2);
     490             : }
     491             : 
     492             : /*
     493             :  * Support function for hash indexes on inet/cidr.
     494             :  */
     495             : Datum
     496          40 : hashinet(PG_FUNCTION_ARGS)
     497             : {
     498          40 :     inet       *addr = PG_GETARG_INET_PP(0);
     499          40 :     int         addrsize = ip_addrsize(addr);
     500             : 
     501             :     /* XXX this assumes there are no pad bytes in the data structure */
     502          40 :     return hash_any((unsigned char *) VARDATA_ANY(addr), addrsize + 2);
     503             : }
     504             : 
     505             : Datum
     506          40 : hashinetextended(PG_FUNCTION_ARGS)
     507             : {
     508          40 :     inet       *addr = PG_GETARG_INET_PP(0);
     509          40 :     int         addrsize = ip_addrsize(addr);
     510             : 
     511          40 :     return hash_any_extended((unsigned char *) VARDATA_ANY(addr), addrsize + 2,
     512          40 :                              PG_GETARG_INT64(1));
     513             : }
     514             : 
     515             : /*
     516             :  *  Boolean network-inclusion tests.
     517             :  */
     518             : Datum
     519        4088 : network_sub(PG_FUNCTION_ARGS)
     520             : {
     521        4088 :     inet       *a1 = PG_GETARG_INET_PP(0);
     522        4088 :     inet       *a2 = PG_GETARG_INET_PP(1);
     523             : 
     524        4088 :     if (ip_family(a1) == ip_family(a2))
     525             :     {
     526        3288 :         PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2) &&
     527             :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
     528             :     }
     529             : 
     530         800 :     PG_RETURN_BOOL(false);
     531             : }
     532             : 
     533             : Datum
     534        6604 : network_subeq(PG_FUNCTION_ARGS)
     535             : {
     536        6604 :     inet       *a1 = PG_GETARG_INET_PP(0);
     537        6604 :     inet       *a2 = PG_GETARG_INET_PP(1);
     538             : 
     539        6604 :     if (ip_family(a1) == ip_family(a2))
     540             :     {
     541        4092 :         PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2) &&
     542             :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
     543             :     }
     544             : 
     545        2512 :     PG_RETURN_BOOL(false);
     546             : }
     547             : 
     548             : Datum
     549        4120 : network_sup(PG_FUNCTION_ARGS)
     550             : {
     551        4120 :     inet       *a1 = PG_GETARG_INET_PP(0);
     552        4120 :     inet       *a2 = PG_GETARG_INET_PP(1);
     553             : 
     554        4120 :     if (ip_family(a1) == ip_family(a2))
     555             :     {
     556        3320 :         PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2) &&
     557             :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
     558             :     }
     559             : 
     560         800 :     PG_RETURN_BOOL(false);
     561             : }
     562             : 
     563             : Datum
     564       12376 : network_supeq(PG_FUNCTION_ARGS)
     565             : {
     566       12376 :     inet       *a1 = PG_GETARG_INET_PP(0);
     567       12376 :     inet       *a2 = PG_GETARG_INET_PP(1);
     568             : 
     569       12376 :     if (ip_family(a1) == ip_family(a2))
     570             :     {
     571        6816 :         PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2) &&
     572             :                        bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
     573             :     }
     574             : 
     575        5560 :     PG_RETURN_BOOL(false);
     576             : }
     577             : 
     578             : Datum
     579       14020 : network_overlap(PG_FUNCTION_ARGS)
     580             : {
     581       14020 :     inet       *a1 = PG_GETARG_INET_PP(0);
     582       14020 :     inet       *a2 = PG_GETARG_INET_PP(1);
     583             : 
     584       14020 :     if (ip_family(a1) == ip_family(a2))
     585             :     {
     586        8532 :         PG_RETURN_BOOL(bitncmp(ip_addr(a1), ip_addr(a2),
     587             :                                Min(ip_bits(a1), ip_bits(a2))) == 0);
     588             :     }
     589             : 
     590        5488 :     PG_RETURN_BOOL(false);
     591             : }
     592             : 
     593             : /*
     594             :  * Planner support function for network subset/superset operators
     595             :  */
     596             : Datum
     597         992 : network_subset_support(PG_FUNCTION_ARGS)
     598             : {
     599         992 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
     600         992 :     Node       *ret = NULL;
     601             : 
     602         992 :     if (IsA(rawreq, SupportRequestIndexCondition))
     603             :     {
     604             :         /* Try to convert operator/function call to index conditions */
     605          32 :         SupportRequestIndexCondition *req = (SupportRequestIndexCondition *) rawreq;
     606             : 
     607          32 :         if (is_opclause(req->node))
     608             :         {
     609          32 :             OpExpr     *clause = (OpExpr *) req->node;
     610             : 
     611             :             Assert(list_length(clause->args) == 2);
     612          32 :             ret = (Node *)
     613          64 :                 match_network_function((Node *) linitial(clause->args),
     614          32 :                                        (Node *) lsecond(clause->args),
     615             :                                        req->indexarg,
     616             :                                        req->funcid,
     617             :                                        req->opfamily);
     618             :         }
     619           0 :         else if (is_funcclause(req->node))   /* be paranoid */
     620             :         {
     621           0 :             FuncExpr   *clause = (FuncExpr *) req->node;
     622             : 
     623             :             Assert(list_length(clause->args) == 2);
     624           0 :             ret = (Node *)
     625           0 :                 match_network_function((Node *) linitial(clause->args),
     626           0 :                                        (Node *) lsecond(clause->args),
     627             :                                        req->indexarg,
     628             :                                        req->funcid,
     629             :                                        req->opfamily);
     630             :         }
     631             :     }
     632             : 
     633         992 :     PG_RETURN_POINTER(ret);
     634             : }
     635             : 
     636             : /*
     637             :  * match_network_function
     638             :  *    Try to generate an indexqual for a network subset/superset function.
     639             :  *
     640             :  * This layer is just concerned with identifying the function and swapping
     641             :  * the arguments if necessary.
     642             :  */
     643             : static List *
     644          32 : match_network_function(Node *leftop,
     645             :                        Node *rightop,
     646             :                        int indexarg,
     647             :                        Oid funcid,
     648             :                        Oid opfamily)
     649             : {
     650          32 :     switch (funcid)
     651             :     {
     652             :         case F_NETWORK_SUB:
     653             :             /* indexkey must be on the left */
     654           8 :             if (indexarg != 0)
     655           0 :                 return NIL;
     656           8 :             return match_network_subset(leftop, rightop, false, opfamily);
     657             : 
     658             :         case F_NETWORK_SUBEQ:
     659             :             /* indexkey must be on the left */
     660           8 :             if (indexarg != 0)
     661           0 :                 return NIL;
     662           8 :             return match_network_subset(leftop, rightop, true, opfamily);
     663             : 
     664             :         case F_NETWORK_SUP:
     665             :             /* indexkey must be on the right */
     666           8 :             if (indexarg != 1)
     667           0 :                 return NIL;
     668           8 :             return match_network_subset(rightop, leftop, false, opfamily);
     669             : 
     670             :         case F_NETWORK_SUPEQ:
     671             :             /* indexkey must be on the right */
     672           8 :             if (indexarg != 1)
     673           0 :                 return NIL;
     674           8 :             return match_network_subset(rightop, leftop, true, opfamily);
     675             : 
     676             :         default:
     677             : 
     678             :             /*
     679             :              * We'd only get here if somebody attached this support function
     680             :              * to an unexpected function.  Maybe we should complain, but for
     681             :              * now, do nothing.
     682             :              */
     683           0 :             return NIL;
     684             :     }
     685             : }
     686             : 
     687             : /*
     688             :  * match_network_subset
     689             :  *    Try to generate an indexqual for a network subset function.
     690             :  */
     691             : static List *
     692          32 : match_network_subset(Node *leftop,
     693             :                      Node *rightop,
     694             :                      bool is_eq,
     695             :                      Oid opfamily)
     696             : {
     697             :     List       *result;
     698             :     Datum       rightopval;
     699          32 :     Oid         datatype = INETOID;
     700             :     Oid         opr1oid;
     701             :     Oid         opr2oid;
     702             :     Datum       opr1right;
     703             :     Datum       opr2right;
     704             :     Expr       *expr;
     705             : 
     706             :     /*
     707             :      * Can't do anything with a non-constant or NULL comparison value.
     708             :      *
     709             :      * Note that since we restrict ourselves to cases with a hard constant on
     710             :      * the RHS, it's a-fortiori a pseudoconstant, and we don't need to worry
     711             :      * about verifying that.
     712             :      */
     713          64 :     if (!IsA(rightop, Const) ||
     714          32 :         ((Const *) rightop)->constisnull)
     715           0 :         return NIL;
     716          32 :     rightopval = ((Const *) rightop)->constvalue;
     717             : 
     718             :     /*
     719             :      * Must check that index's opfamily supports the operators we will want to
     720             :      * apply.
     721             :      *
     722             :      * We insist on the opfamily being the specific one we expect, else we'd
     723             :      * do the wrong thing if someone were to make a reverse-sort opfamily with
     724             :      * the same operators.
     725             :      */
     726          32 :     if (opfamily != NETWORK_BTREE_FAM_OID)
     727           0 :         return NIL;
     728             : 
     729             :     /*
     730             :      * create clause "key >= network_scan_first( rightopval )", or ">" if the
     731             :      * operator disallows equality.
     732             :      *
     733             :      * Note: seeing that this function supports only fixed values for opfamily
     734             :      * and datatype, we could just hard-wire the operator OIDs instead of
     735             :      * looking them up.  But for now it seems better to be general.
     736             :      */
     737          32 :     if (is_eq)
     738             :     {
     739          16 :         opr1oid = get_opfamily_member(opfamily, datatype, datatype,
     740             :                                       BTGreaterEqualStrategyNumber);
     741          16 :         if (opr1oid == InvalidOid)
     742           0 :             elog(ERROR, "no >= operator for opfamily %u", opfamily);
     743             :     }
     744             :     else
     745             :     {
     746          16 :         opr1oid = get_opfamily_member(opfamily, datatype, datatype,
     747             :                                       BTGreaterStrategyNumber);
     748          16 :         if (opr1oid == InvalidOid)
     749           0 :             elog(ERROR, "no > operator for opfamily %u", opfamily);
     750             :     }
     751             : 
     752          32 :     opr1right = network_scan_first(rightopval);
     753             : 
     754          32 :     expr = make_opclause(opr1oid, BOOLOID, false,
     755             :                          (Expr *) leftop,
     756          32 :                          (Expr *) makeConst(datatype, -1,
     757             :                                             InvalidOid, /* not collatable */
     758             :                                             -1, opr1right,
     759             :                                             false, false),
     760             :                          InvalidOid, InvalidOid);
     761          32 :     result = list_make1(expr);
     762             : 
     763             :     /* create clause "key <= network_scan_last( rightopval )" */
     764             : 
     765          32 :     opr2oid = get_opfamily_member(opfamily, datatype, datatype,
     766             :                                   BTLessEqualStrategyNumber);
     767          32 :     if (opr2oid == InvalidOid)
     768           0 :         elog(ERROR, "no <= operator for opfamily %u", opfamily);
     769             : 
     770          32 :     opr2right = network_scan_last(rightopval);
     771             : 
     772          32 :     expr = make_opclause(opr2oid, BOOLOID, false,
     773             :                          (Expr *) leftop,
     774          32 :                          (Expr *) makeConst(datatype, -1,
     775             :                                             InvalidOid, /* not collatable */
     776             :                                             -1, opr2right,
     777             :                                             false, false),
     778             :                          InvalidOid, InvalidOid);
     779          32 :     result = lappend(result, expr);
     780             : 
     781          32 :     return result;
     782             : }
     783             : 
     784             : 
     785             : /*
     786             :  * Extract data from a network datatype.
     787             :  */
     788             : Datum
     789          68 : network_host(PG_FUNCTION_ARGS)
     790             : {
     791          68 :     inet       *ip = PG_GETARG_INET_PP(0);
     792             :     char       *ptr;
     793             :     char        tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
     794             : 
     795             :     /* force display of max bits, regardless of masklen... */
     796          68 :     if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
     797             :                       tmp, sizeof(tmp)) == NULL)
     798           0 :         ereport(ERROR,
     799             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     800             :                  errmsg("could not format inet value: %m")));
     801             : 
     802             :     /* Suppress /n if present (shouldn't happen now) */
     803          68 :     if ((ptr = strchr(tmp, '/')) != NULL)
     804           0 :         *ptr = '\0';
     805             : 
     806          68 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
     807             : }
     808             : 
     809             : /*
     810             :  * network_show implements the inet and cidr casts to text.  This is not
     811             :  * quite the same behavior as network_out, hence we can't drop it in favor
     812             :  * of CoerceViaIO.
     813             :  */
     814             : Datum
     815         144 : network_show(PG_FUNCTION_ARGS)
     816             : {
     817         144 :     inet       *ip = PG_GETARG_INET_PP(0);
     818             :     int         len;
     819             :     char        tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
     820             : 
     821         144 :     if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
     822             :                       tmp, sizeof(tmp)) == NULL)
     823           0 :         ereport(ERROR,
     824             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     825             :                  errmsg("could not format inet value: %m")));
     826             : 
     827             :     /* Add /n if not present (which it won't be) */
     828         144 :     if (strchr(tmp, '/') == NULL)
     829             :     {
     830         144 :         len = strlen(tmp);
     831         144 :         snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
     832             :     }
     833             : 
     834         144 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
     835             : }
     836             : 
     837             : Datum
     838           0 : inet_abbrev(PG_FUNCTION_ARGS)
     839             : {
     840           0 :     inet       *ip = PG_GETARG_INET_PP(0);
     841             :     char       *dst;
     842             :     char        tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
     843             : 
     844           0 :     dst = inet_net_ntop(ip_family(ip), ip_addr(ip),
     845           0 :                         ip_bits(ip), tmp, sizeof(tmp));
     846             : 
     847           0 :     if (dst == NULL)
     848           0 :         ereport(ERROR,
     849             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     850             :                  errmsg("could not format inet value: %m")));
     851             : 
     852           0 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
     853             : }
     854             : 
     855             : Datum
     856           0 : cidr_abbrev(PG_FUNCTION_ARGS)
     857             : {
     858           0 :     inet       *ip = PG_GETARG_INET_PP(0);
     859             :     char       *dst;
     860             :     char        tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
     861             : 
     862           0 :     dst = inet_cidr_ntop(ip_family(ip), ip_addr(ip),
     863           0 :                          ip_bits(ip), tmp, sizeof(tmp));
     864             : 
     865           0 :     if (dst == NULL)
     866           0 :         ereport(ERROR,
     867             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     868             :                  errmsg("could not format cidr value: %m")));
     869             : 
     870           0 :     PG_RETURN_TEXT_P(cstring_to_text(tmp));
     871             : }
     872             : 
     873             : Datum
     874         236 : network_masklen(PG_FUNCTION_ARGS)
     875             : {
     876         236 :     inet       *ip = PG_GETARG_INET_PP(0);
     877             : 
     878         236 :     PG_RETURN_INT32(ip_bits(ip));
     879             : }
     880             : 
     881             : Datum
     882          68 : network_family(PG_FUNCTION_ARGS)
     883             : {
     884          68 :     inet       *ip = PG_GETARG_INET_PP(0);
     885             : 
     886          68 :     switch (ip_family(ip))
     887             :     {
     888             :         case PGSQL_AF_INET:
     889          56 :             PG_RETURN_INT32(4);
     890             :             break;
     891             :         case PGSQL_AF_INET6:
     892          12 :             PG_RETURN_INT32(6);
     893             :             break;
     894             :         default:
     895           0 :             PG_RETURN_INT32(0);
     896             :             break;
     897             :     }
     898             : }
     899             : 
     900             : Datum
     901         168 : network_broadcast(PG_FUNCTION_ARGS)
     902             : {
     903         168 :     inet       *ip = PG_GETARG_INET_PP(0);
     904             :     inet       *dst;
     905             :     int         byte;
     906             :     int         bits;
     907             :     int         maxbytes;
     908             :     unsigned char mask;
     909             :     unsigned char *a,
     910             :                *b;
     911             : 
     912             :     /* make sure any unused bits are zeroed */
     913         168 :     dst = (inet *) palloc0(sizeof(inet));
     914             : 
     915         168 :     maxbytes = ip_addrsize(ip);
     916         168 :     bits = ip_bits(ip);
     917         168 :     a = ip_addr(ip);
     918         168 :     b = ip_addr(dst);
     919             : 
     920        1128 :     for (byte = 0; byte < maxbytes; byte++)
     921             :     {
     922         960 :         if (bits >= 8)
     923             :         {
     924         660 :             mask = 0x00;
     925         660 :             bits -= 8;
     926             :         }
     927         300 :         else if (bits == 0)
     928         284 :             mask = 0xff;
     929             :         else
     930             :         {
     931          16 :             mask = 0xff >> bits;
     932          16 :             bits = 0;
     933             :         }
     934             : 
     935         960 :         b[byte] = a[byte] | mask;
     936             :     }
     937             : 
     938         168 :     ip_family(dst) = ip_family(ip);
     939         168 :     ip_bits(dst) = ip_bits(ip);
     940         168 :     SET_INET_VARSIZE(dst);
     941             : 
     942         168 :     PG_RETURN_INET_P(dst);
     943             : }
     944             : 
     945             : Datum
     946         168 : network_network(PG_FUNCTION_ARGS)
     947             : {
     948         168 :     inet       *ip = PG_GETARG_INET_PP(0);
     949             :     inet       *dst;
     950             :     int         byte;
     951             :     int         bits;
     952             :     unsigned char mask;
     953             :     unsigned char *a,
     954             :                *b;
     955             : 
     956             :     /* make sure any unused bits are zeroed */
     957         168 :     dst = (inet *) palloc0(sizeof(inet));
     958             : 
     959         168 :     bits = ip_bits(ip);
     960         168 :     a = ip_addr(ip);
     961         168 :     b = ip_addr(dst);
     962             : 
     963         168 :     byte = 0;
     964             : 
     965        1012 :     while (bits)
     966             :     {
     967         676 :         if (bits >= 8)
     968             :         {
     969         660 :             mask = 0xff;
     970         660 :             bits -= 8;
     971             :         }
     972             :         else
     973             :         {
     974          16 :             mask = 0xff << (8 - bits);
     975          16 :             bits = 0;
     976             :         }
     977             : 
     978         676 :         b[byte] = a[byte] & mask;
     979         676 :         byte++;
     980             :     }
     981             : 
     982         168 :     ip_family(dst) = ip_family(ip);
     983         168 :     ip_bits(dst) = ip_bits(ip);
     984         168 :     SET_INET_VARSIZE(dst);
     985             : 
     986         168 :     PG_RETURN_INET_P(dst);
     987             : }
     988             : 
     989             : Datum
     990           0 : network_netmask(PG_FUNCTION_ARGS)
     991             : {
     992           0 :     inet       *ip = PG_GETARG_INET_PP(0);
     993             :     inet       *dst;
     994             :     int         byte;
     995             :     int         bits;
     996             :     unsigned char mask;
     997             :     unsigned char *b;
     998             : 
     999             :     /* make sure any unused bits are zeroed */
    1000           0 :     dst = (inet *) palloc0(sizeof(inet));
    1001             : 
    1002           0 :     bits = ip_bits(ip);
    1003           0 :     b = ip_addr(dst);
    1004             : 
    1005           0 :     byte = 0;
    1006             : 
    1007           0 :     while (bits)
    1008             :     {
    1009           0 :         if (bits >= 8)
    1010             :         {
    1011           0 :             mask = 0xff;
    1012           0 :             bits -= 8;
    1013             :         }
    1014             :         else
    1015             :         {
    1016           0 :             mask = 0xff << (8 - bits);
    1017           0 :             bits = 0;
    1018             :         }
    1019             : 
    1020           0 :         b[byte] = mask;
    1021           0 :         byte++;
    1022             :     }
    1023             : 
    1024           0 :     ip_family(dst) = ip_family(ip);
    1025           0 :     ip_bits(dst) = ip_maxbits(ip);
    1026           0 :     SET_INET_VARSIZE(dst);
    1027             : 
    1028           0 :     PG_RETURN_INET_P(dst);
    1029             : }
    1030             : 
    1031             : Datum
    1032           0 : network_hostmask(PG_FUNCTION_ARGS)
    1033             : {
    1034           0 :     inet       *ip = PG_GETARG_INET_PP(0);
    1035             :     inet       *dst;
    1036             :     int         byte;
    1037             :     int         bits;
    1038             :     int         maxbytes;
    1039             :     unsigned char mask;
    1040             :     unsigned char *b;
    1041             : 
    1042             :     /* make sure any unused bits are zeroed */
    1043           0 :     dst = (inet *) palloc0(sizeof(inet));
    1044             : 
    1045           0 :     maxbytes = ip_addrsize(ip);
    1046           0 :     bits = ip_maxbits(ip) - ip_bits(ip);
    1047           0 :     b = ip_addr(dst);
    1048             : 
    1049           0 :     byte = maxbytes - 1;
    1050             : 
    1051           0 :     while (bits)
    1052             :     {
    1053           0 :         if (bits >= 8)
    1054             :         {
    1055           0 :             mask = 0xff;
    1056           0 :             bits -= 8;
    1057             :         }
    1058             :         else
    1059             :         {
    1060           0 :             mask = 0xff >> (8 - bits);
    1061           0 :             bits = 0;
    1062             :         }
    1063             : 
    1064           0 :         b[byte] = mask;
    1065           0 :         byte--;
    1066             :     }
    1067             : 
    1068           0 :     ip_family(dst) = ip_family(ip);
    1069           0 :     ip_bits(dst) = ip_maxbits(ip);
    1070           0 :     SET_INET_VARSIZE(dst);
    1071             : 
    1072           0 :     PG_RETURN_INET_P(dst);
    1073             : }
    1074             : 
    1075             : /*
    1076             :  * Returns true if the addresses are from the same family, or false.  Used to
    1077             :  * check that we can create a network which contains both of the networks.
    1078             :  */
    1079             : Datum
    1080         144 : inet_same_family(PG_FUNCTION_ARGS)
    1081             : {
    1082         144 :     inet       *a1 = PG_GETARG_INET_PP(0);
    1083         144 :     inet       *a2 = PG_GETARG_INET_PP(1);
    1084             : 
    1085         144 :     PG_RETURN_BOOL(ip_family(a1) == ip_family(a2));
    1086             : }
    1087             : 
    1088             : /*
    1089             :  * Returns the smallest CIDR which contains both of the inputs.
    1090             :  */
    1091             : Datum
    1092         140 : inet_merge(PG_FUNCTION_ARGS)
    1093             : {
    1094         140 :     inet       *a1 = PG_GETARG_INET_PP(0),
    1095         140 :                *a2 = PG_GETARG_INET_PP(1);
    1096             :     int         commonbits;
    1097             : 
    1098         140 :     if (ip_family(a1) != ip_family(a2))
    1099           4 :         ereport(ERROR,
    1100             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1101             :                  errmsg("cannot merge addresses from different families")));
    1102             : 
    1103         272 :     commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
    1104         272 :                             Min(ip_bits(a1), ip_bits(a2)));
    1105             : 
    1106         136 :     PG_RETURN_INET_P(cidr_set_masklen_internal(a1, commonbits));
    1107             : }
    1108             : 
    1109             : /*
    1110             :  * Convert a value of a network datatype to an approximate scalar value.
    1111             :  * This is used for estimating selectivities of inequality operators
    1112             :  * involving network types.
    1113             :  *
    1114             :  * On failure (e.g., unsupported typid), set *failure to true;
    1115             :  * otherwise, that variable is not changed.
    1116             :  */
    1117             : double
    1118       10880 : convert_network_to_scalar(Datum value, Oid typid, bool *failure)
    1119             : {
    1120       10880 :     switch (typid)
    1121             :     {
    1122             :         case INETOID:
    1123             :         case CIDROID:
    1124             :             {
    1125       10880 :                 inet       *ip = DatumGetInetPP(value);
    1126             :                 int         len;
    1127             :                 double      res;
    1128             :                 int         i;
    1129             : 
    1130             :                 /*
    1131             :                  * Note that we don't use the full address for IPv6.
    1132             :                  */
    1133       10880 :                 if (ip_family(ip) == PGSQL_AF_INET)
    1134       10880 :                     len = 4;
    1135             :                 else
    1136           0 :                     len = 5;
    1137             : 
    1138       10880 :                 res = ip_family(ip);
    1139       54400 :                 for (i = 0; i < len; i++)
    1140             :                 {
    1141       43520 :                     res *= 256;
    1142       43520 :                     res += ip_addr(ip)[i];
    1143             :                 }
    1144       10880 :                 return res;
    1145             :             }
    1146             :         case MACADDROID:
    1147             :             {
    1148           0 :                 macaddr    *mac = DatumGetMacaddrP(value);
    1149             :                 double      res;
    1150             : 
    1151           0 :                 res = (mac->a << 16) | (mac->b << 8) | (mac->c);
    1152           0 :                 res *= 256 * 256 * 256;
    1153           0 :                 res += (mac->d << 16) | (mac->e << 8) | (mac->f);
    1154           0 :                 return res;
    1155             :             }
    1156             :         case MACADDR8OID:
    1157             :             {
    1158           0 :                 macaddr8   *mac = DatumGetMacaddr8P(value);
    1159             :                 double      res;
    1160             : 
    1161           0 :                 res = (mac->a << 24) | (mac->b << 16) | (mac->c << 8) | (mac->d);
    1162           0 :                 res *= ((double) 256) * 256 * 256 * 256;
    1163           0 :                 res += (mac->e << 24) | (mac->f << 16) | (mac->g << 8) | (mac->h);
    1164           0 :                 return res;
    1165             :             }
    1166             :     }
    1167             : 
    1168           0 :     *failure = true;
    1169           0 :     return 0;
    1170             : }
    1171             : 
    1172             : /*
    1173             :  * int
    1174             :  * bitncmp(l, r, n)
    1175             :  *      compare bit masks l and r, for n bits.
    1176             :  * return:
    1177             :  *      <0, >0, or 0 in the libc tradition.
    1178             :  * note:
    1179             :  *      network byte order assumed.  this means 192.5.5.240/28 has
    1180             :  *      0x11110000 in its fourth octet.
    1181             :  * author:
    1182             :  *      Paul Vixie (ISC), June 1996
    1183             :  */
    1184             : int
    1185      105630 : bitncmp(const unsigned char *l, const unsigned char *r, int n)
    1186             : {
    1187             :     unsigned int lb,
    1188             :                 rb;
    1189             :     int         x,
    1190             :                 b;
    1191             : 
    1192      105630 :     b = n / 8;
    1193      105630 :     x = memcmp(l, r, b);
    1194      105630 :     if (x || (n % 8) == 0)
    1195      105298 :         return x;
    1196             : 
    1197         332 :     lb = l[b];
    1198         332 :     rb = r[b];
    1199         460 :     for (b = n % 8; b > 0; b--)
    1200             :     {
    1201         332 :         if (IS_HIGHBIT_SET(lb) != IS_HIGHBIT_SET(rb))
    1202             :         {
    1203         204 :             if (IS_HIGHBIT_SET(lb))
    1204         112 :                 return 1;
    1205          92 :             return -1;
    1206             :         }
    1207         128 :         lb <<= 1;
    1208         128 :         rb <<= 1;
    1209             :     }
    1210         128 :     return 0;
    1211             : }
    1212             : 
    1213             : /*
    1214             :  * bitncommon: compare bit masks l and r, for up to n bits.
    1215             :  *
    1216             :  * Returns the number of leading bits that match (0 to n).
    1217             :  */
    1218             : int
    1219        3228 : bitncommon(const unsigned char *l, const unsigned char *r, int n)
    1220             : {
    1221             :     int         byte,
    1222             :                 nbits;
    1223             : 
    1224             :     /* number of bits to examine in last byte */
    1225        3228 :     nbits = n % 8;
    1226             : 
    1227             :     /* check whole bytes */
    1228        3682 :     for (byte = 0; byte < n / 8; byte++)
    1229             :     {
    1230         490 :         if (l[byte] != r[byte])
    1231             :         {
    1232             :             /* at least one bit in the last byte is not common */
    1233          36 :             nbits = 7;
    1234          36 :             break;
    1235             :         }
    1236             :     }
    1237             : 
    1238             :     /* check bits in last partial byte */
    1239        3228 :     if (nbits != 0)
    1240             :     {
    1241             :         /* calculate diff of first non-matching bytes */
    1242        2524 :         unsigned int diff = l[byte] ^ r[byte];
    1243             : 
    1244             :         /* compare the bits from the most to the least */
    1245        5436 :         while ((diff >> (8 - nbits)) != 0)
    1246         388 :             nbits--;
    1247             :     }
    1248             : 
    1249        3228 :     return (8 * byte) + nbits;
    1250             : }
    1251             : 
    1252             : 
    1253             : /*
    1254             :  * Verify a CIDR address is OK (doesn't have bits set past the masklen)
    1255             :  */
    1256             : static bool
    1257         706 : addressOK(unsigned char *a, int bits, int family)
    1258             : {
    1259             :     int         byte;
    1260             :     int         nbits;
    1261             :     int         maxbits;
    1262             :     int         maxbytes;
    1263             :     unsigned char mask;
    1264             : 
    1265         706 :     if (family == PGSQL_AF_INET)
    1266             :     {
    1267         558 :         maxbits = 32;
    1268         558 :         maxbytes = 4;
    1269             :     }
    1270             :     else
    1271             :     {
    1272         148 :         maxbits = 128;
    1273         148 :         maxbytes = 16;
    1274             :     }
    1275             :     Assert(bits <= maxbits);
    1276             : 
    1277         706 :     if (bits == maxbits)
    1278         244 :         return true;
    1279             : 
    1280         462 :     byte = bits / 8;
    1281             : 
    1282         462 :     nbits = bits % 8;
    1283         462 :     mask = 0xff;
    1284         462 :     if (bits != 0)
    1285         430 :         mask >>= nbits;
    1286             : 
    1287        2350 :     while (byte < maxbytes)
    1288             :     {
    1289        1438 :         if ((a[byte] & mask) != 0)
    1290          12 :             return false;
    1291        1426 :         mask = 0xff;
    1292        1426 :         byte++;
    1293             :     }
    1294             : 
    1295         450 :     return true;
    1296             : }
    1297             : 
    1298             : 
    1299             : /*
    1300             :  * These functions are used by planner to generate indexscan limits
    1301             :  * for clauses a << b and a <<= b
    1302             :  */
    1303             : 
    1304             : /* return the minimal value for an IP on a given network */
    1305             : Datum
    1306          32 : network_scan_first(Datum in)
    1307             : {
    1308          32 :     return DirectFunctionCall1(network_network, in);
    1309             : }
    1310             : 
    1311             : /*
    1312             :  * return "last" IP on a given network. It's the broadcast address,
    1313             :  * however, masklen has to be set to its max bits, since
    1314             :  * 192.168.0.255/24 is considered less than 192.168.0.255/32
    1315             :  *
    1316             :  * inet_set_masklen() hacked to max out the masklength to 128 for IPv6
    1317             :  * and 32 for IPv4 when given '-1' as argument.
    1318             :  */
    1319             : Datum
    1320          32 : network_scan_last(Datum in)
    1321             : {
    1322          32 :     return DirectFunctionCall2(inet_set_masklen,
    1323             :                                DirectFunctionCall1(network_broadcast, in),
    1324             :                                Int32GetDatum(-1));
    1325             : }
    1326             : 
    1327             : 
    1328             : /*
    1329             :  * IP address that the client is connecting from (NULL if Unix socket)
    1330             :  */
    1331             : Datum
    1332           0 : inet_client_addr(PG_FUNCTION_ARGS)
    1333             : {
    1334           0 :     Port       *port = MyProcPort;
    1335             :     char        remote_host[NI_MAXHOST];
    1336             :     int         ret;
    1337             : 
    1338           0 :     if (port == NULL)
    1339           0 :         PG_RETURN_NULL();
    1340             : 
    1341           0 :     switch (port->raddr.addr.ss_family)
    1342             :     {
    1343             :         case AF_INET:
    1344             : #ifdef HAVE_IPV6
    1345             :         case AF_INET6:
    1346             : #endif
    1347           0 :             break;
    1348             :         default:
    1349           0 :             PG_RETURN_NULL();
    1350             :     }
    1351             : 
    1352           0 :     remote_host[0] = '\0';
    1353             : 
    1354           0 :     ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
    1355             :                              remote_host, sizeof(remote_host),
    1356             :                              NULL, 0,
    1357             :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1358           0 :     if (ret != 0)
    1359           0 :         PG_RETURN_NULL();
    1360             : 
    1361           0 :     clean_ipv6_addr(port->raddr.addr.ss_family, remote_host);
    1362             : 
    1363           0 :     PG_RETURN_INET_P(network_in(remote_host, false));
    1364             : }
    1365             : 
    1366             : 
    1367             : /*
    1368             :  * port that the client is connecting from (NULL if Unix socket)
    1369             :  */
    1370             : Datum
    1371           0 : inet_client_port(PG_FUNCTION_ARGS)
    1372             : {
    1373           0 :     Port       *port = MyProcPort;
    1374             :     char        remote_port[NI_MAXSERV];
    1375             :     int         ret;
    1376             : 
    1377           0 :     if (port == NULL)
    1378           0 :         PG_RETURN_NULL();
    1379             : 
    1380           0 :     switch (port->raddr.addr.ss_family)
    1381             :     {
    1382             :         case AF_INET:
    1383             : #ifdef HAVE_IPV6
    1384             :         case AF_INET6:
    1385             : #endif
    1386           0 :             break;
    1387             :         default:
    1388           0 :             PG_RETURN_NULL();
    1389             :     }
    1390             : 
    1391           0 :     remote_port[0] = '\0';
    1392             : 
    1393           0 :     ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
    1394             :                              NULL, 0,
    1395             :                              remote_port, sizeof(remote_port),
    1396             :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1397           0 :     if (ret != 0)
    1398           0 :         PG_RETURN_NULL();
    1399             : 
    1400           0 :     PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
    1401             : }
    1402             : 
    1403             : 
    1404             : /*
    1405             :  * IP address that the server accepted the connection on (NULL if Unix socket)
    1406             :  */
    1407             : Datum
    1408           0 : inet_server_addr(PG_FUNCTION_ARGS)
    1409             : {
    1410           0 :     Port       *port = MyProcPort;
    1411             :     char        local_host[NI_MAXHOST];
    1412             :     int         ret;
    1413             : 
    1414           0 :     if (port == NULL)
    1415           0 :         PG_RETURN_NULL();
    1416             : 
    1417           0 :     switch (port->laddr.addr.ss_family)
    1418             :     {
    1419             :         case AF_INET:
    1420             : #ifdef HAVE_IPV6
    1421             :         case AF_INET6:
    1422             : #endif
    1423           0 :             break;
    1424             :         default:
    1425           0 :             PG_RETURN_NULL();
    1426             :     }
    1427             : 
    1428           0 :     local_host[0] = '\0';
    1429             : 
    1430           0 :     ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
    1431             :                              local_host, sizeof(local_host),
    1432             :                              NULL, 0,
    1433             :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1434           0 :     if (ret != 0)
    1435           0 :         PG_RETURN_NULL();
    1436             : 
    1437           0 :     clean_ipv6_addr(port->laddr.addr.ss_family, local_host);
    1438             : 
    1439           0 :     PG_RETURN_INET_P(network_in(local_host, false));
    1440             : }
    1441             : 
    1442             : 
    1443             : /*
    1444             :  * port that the server accepted the connection on (NULL if Unix socket)
    1445             :  */
    1446             : Datum
    1447           0 : inet_server_port(PG_FUNCTION_ARGS)
    1448             : {
    1449           0 :     Port       *port = MyProcPort;
    1450             :     char        local_port[NI_MAXSERV];
    1451             :     int         ret;
    1452             : 
    1453           0 :     if (port == NULL)
    1454           0 :         PG_RETURN_NULL();
    1455             : 
    1456           0 :     switch (port->laddr.addr.ss_family)
    1457             :     {
    1458             :         case AF_INET:
    1459             : #ifdef HAVE_IPV6
    1460             :         case AF_INET6:
    1461             : #endif
    1462           0 :             break;
    1463             :         default:
    1464           0 :             PG_RETURN_NULL();
    1465             :     }
    1466             : 
    1467           0 :     local_port[0] = '\0';
    1468             : 
    1469           0 :     ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
    1470             :                              NULL, 0,
    1471             :                              local_port, sizeof(local_port),
    1472             :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1473           0 :     if (ret != 0)
    1474           0 :         PG_RETURN_NULL();
    1475             : 
    1476           0 :     PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
    1477             : }
    1478             : 
    1479             : 
    1480             : Datum
    1481          68 : inetnot(PG_FUNCTION_ARGS)
    1482             : {
    1483          68 :     inet       *ip = PG_GETARG_INET_PP(0);
    1484             :     inet       *dst;
    1485             : 
    1486          68 :     dst = (inet *) palloc0(sizeof(inet));
    1487             : 
    1488             :     {
    1489          68 :         int         nb = ip_addrsize(ip);
    1490          68 :         unsigned char *pip = ip_addr(ip);
    1491          68 :         unsigned char *pdst = ip_addr(dst);
    1492             : 
    1493         552 :         while (nb-- > 0)
    1494         416 :             pdst[nb] = ~pip[nb];
    1495             :     }
    1496          68 :     ip_bits(dst) = ip_bits(ip);
    1497             : 
    1498          68 :     ip_family(dst) = ip_family(ip);
    1499          68 :     SET_INET_VARSIZE(dst);
    1500             : 
    1501          68 :     PG_RETURN_INET_P(dst);
    1502             : }
    1503             : 
    1504             : 
    1505             : Datum
    1506          68 : inetand(PG_FUNCTION_ARGS)
    1507             : {
    1508          68 :     inet       *ip = PG_GETARG_INET_PP(0);
    1509          68 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    1510             :     inet       *dst;
    1511             : 
    1512          68 :     dst = (inet *) palloc0(sizeof(inet));
    1513             : 
    1514          68 :     if (ip_family(ip) != ip_family(ip2))
    1515           0 :         ereport(ERROR,
    1516             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1517             :                  errmsg("cannot AND inet values of different sizes")));
    1518             :     else
    1519             :     {
    1520          68 :         int         nb = ip_addrsize(ip);
    1521          68 :         unsigned char *pip = ip_addr(ip);
    1522          68 :         unsigned char *pip2 = ip_addr(ip2);
    1523          68 :         unsigned char *pdst = ip_addr(dst);
    1524             : 
    1525         552 :         while (nb-- > 0)
    1526         416 :             pdst[nb] = pip[nb] & pip2[nb];
    1527             :     }
    1528          68 :     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
    1529             : 
    1530          68 :     ip_family(dst) = ip_family(ip);
    1531          68 :     SET_INET_VARSIZE(dst);
    1532             : 
    1533          68 :     PG_RETURN_INET_P(dst);
    1534             : }
    1535             : 
    1536             : 
    1537             : Datum
    1538          68 : inetor(PG_FUNCTION_ARGS)
    1539             : {
    1540          68 :     inet       *ip = PG_GETARG_INET_PP(0);
    1541          68 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    1542             :     inet       *dst;
    1543             : 
    1544          68 :     dst = (inet *) palloc0(sizeof(inet));
    1545             : 
    1546          68 :     if (ip_family(ip) != ip_family(ip2))
    1547           0 :         ereport(ERROR,
    1548             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1549             :                  errmsg("cannot OR inet values of different sizes")));
    1550             :     else
    1551             :     {
    1552          68 :         int         nb = ip_addrsize(ip);
    1553          68 :         unsigned char *pip = ip_addr(ip);
    1554          68 :         unsigned char *pip2 = ip_addr(ip2);
    1555          68 :         unsigned char *pdst = ip_addr(dst);
    1556             : 
    1557         552 :         while (nb-- > 0)
    1558         416 :             pdst[nb] = pip[nb] | pip2[nb];
    1559             :     }
    1560          68 :     ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
    1561             : 
    1562          68 :     ip_family(dst) = ip_family(ip);
    1563          68 :     SET_INET_VARSIZE(dst);
    1564             : 
    1565          68 :     PG_RETURN_INET_P(dst);
    1566             : }
    1567             : 
    1568             : 
    1569             : static inet *
    1570        1268 : internal_inetpl(inet *ip, int64 addend)
    1571             : {
    1572             :     inet       *dst;
    1573             : 
    1574        1268 :     dst = (inet *) palloc0(sizeof(inet));
    1575             : 
    1576             :     {
    1577        1268 :         int         nb = ip_addrsize(ip);
    1578        1268 :         unsigned char *pip = ip_addr(ip);
    1579        1268 :         unsigned char *pdst = ip_addr(dst);
    1580        1268 :         int         carry = 0;
    1581             : 
    1582       10584 :         while (nb-- > 0)
    1583             :         {
    1584        8048 :             carry = pip[nb] + (int) (addend & 0xFF) + carry;
    1585        8048 :             pdst[nb] = (unsigned char) (carry & 0xFF);
    1586        8048 :             carry >>= 8;
    1587             : 
    1588             :             /*
    1589             :              * We have to be careful about right-shifting addend because
    1590             :              * right-shift isn't portable for negative values, while simply
    1591             :              * dividing by 256 doesn't work (the standard rounding is in the
    1592             :              * wrong direction, besides which there may be machines out there
    1593             :              * that round the wrong way).  So, explicitly clear the low-order
    1594             :              * byte to remove any doubt about the correct result of the
    1595             :              * division, and then divide rather than shift.
    1596             :              */
    1597        8048 :             addend &= ~((int64) 0xFF);
    1598        8048 :             addend /= 0x100;
    1599             :         }
    1600             : 
    1601             :         /*
    1602             :          * At this point we should have addend and carry both zero if original
    1603             :          * addend was >= 0, or addend -1 and carry 1 if original addend was <
    1604             :          * 0.  Anything else means overflow.
    1605             :          */
    1606        1268 :         if (!((addend == 0 && carry == 0) ||
    1607          84 :               (addend == -1 && carry == 1)))
    1608           8 :             ereport(ERROR,
    1609             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1610             :                      errmsg("result is out of range")));
    1611             :     }
    1612             : 
    1613        1260 :     ip_bits(dst) = ip_bits(ip);
    1614        1260 :     ip_family(dst) = ip_family(ip);
    1615        1260 :     SET_INET_VARSIZE(dst);
    1616             : 
    1617        1260 :     return dst;
    1618             : }
    1619             : 
    1620             : 
    1621             : Datum
    1622        1180 : inetpl(PG_FUNCTION_ARGS)
    1623             : {
    1624        1180 :     inet       *ip = PG_GETARG_INET_PP(0);
    1625        1180 :     int64       addend = PG_GETARG_INT64(1);
    1626             : 
    1627        1180 :     PG_RETURN_INET_P(internal_inetpl(ip, addend));
    1628             : }
    1629             : 
    1630             : 
    1631             : Datum
    1632          88 : inetmi_int8(PG_FUNCTION_ARGS)
    1633             : {
    1634          88 :     inet       *ip = PG_GETARG_INET_PP(0);
    1635          88 :     int64       addend = PG_GETARG_INT64(1);
    1636             : 
    1637          88 :     PG_RETURN_INET_P(internal_inetpl(ip, -addend));
    1638             : }
    1639             : 
    1640             : 
    1641             : Datum
    1642          96 : inetmi(PG_FUNCTION_ARGS)
    1643             : {
    1644          96 :     inet       *ip = PG_GETARG_INET_PP(0);
    1645          96 :     inet       *ip2 = PG_GETARG_INET_PP(1);
    1646          96 :     int64       res = 0;
    1647             : 
    1648          96 :     if (ip_family(ip) != ip_family(ip2))
    1649           0 :         ereport(ERROR,
    1650             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1651             :                  errmsg("cannot subtract inet values of different sizes")));
    1652             :     else
    1653             :     {
    1654             :         /*
    1655             :          * We form the difference using the traditional complement, increment,
    1656             :          * and add rule, with the increment part being handled by starting the
    1657             :          * carry off at 1.  If you don't think integer arithmetic is done in
    1658             :          * two's complement, too bad.
    1659             :          */
    1660          96 :         int         nb = ip_addrsize(ip);
    1661          96 :         int         byte = 0;
    1662          96 :         unsigned char *pip = ip_addr(ip);
    1663          96 :         unsigned char *pip2 = ip_addr(ip2);
    1664          96 :         int         carry = 1;
    1665             : 
    1666         944 :         while (nb-- > 0)
    1667             :         {
    1668             :             int         lobyte;
    1669             : 
    1670         760 :             carry = pip[nb] + (~pip2[nb] & 0xFF) + carry;
    1671         760 :             lobyte = carry & 0xFF;
    1672         760 :             if (byte < sizeof(int64))
    1673             :             {
    1674         512 :                 res |= ((int64) lobyte) << (byte * 8);
    1675             :             }
    1676             :             else
    1677             :             {
    1678             :                 /*
    1679             :                  * Input wider than int64: check for overflow.  All bytes to
    1680             :                  * the left of what will fit should be 0 or 0xFF, depending on
    1681             :                  * sign of the now-complete result.
    1682             :                  */
    1683         248 :                 if ((res < 0) ? (lobyte != 0xFF) : (lobyte != 0))
    1684           8 :                     ereport(ERROR,
    1685             :                             (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1686             :                              errmsg("result is out of range")));
    1687             :             }
    1688         752 :             carry >>= 8;
    1689         752 :             byte++;
    1690             :         }
    1691             : 
    1692             :         /*
    1693             :          * If input is narrower than int64, overflow is not possible, but we
    1694             :          * have to do proper sign extension.
    1695             :          */
    1696          88 :         if (carry == 0 && byte < sizeof(int64))
    1697           8 :             res |= ((uint64) (int64) -1) << (byte * 8);
    1698             :     }
    1699             : 
    1700          88 :     PG_RETURN_INT64(res);
    1701             : }
    1702             : 
    1703             : 
    1704             : /*
    1705             :  * clean_ipv6_addr --- remove any '%zone' part from an IPv6 address string
    1706             :  *
    1707             :  * XXX This should go away someday!
    1708             :  *
    1709             :  * This is a kluge needed because we don't yet support zones in stored inet
    1710             :  * values.  Since the result of getnameinfo() might include a zone spec,
    1711             :  * call this to remove it anywhere we want to feed getnameinfo's output to
    1712             :  * network_in.  Beats failing entirely.
    1713             :  *
    1714             :  * An alternative approach would be to let network_in ignore %-parts for
    1715             :  * itself, but that would mean we'd silently drop zone specs in user input,
    1716             :  * which seems not such a good idea.
    1717             :  */
    1718             : void
    1719          36 : clean_ipv6_addr(int addr_family, char *addr)
    1720             : {
    1721             : #ifdef HAVE_IPV6
    1722          36 :     if (addr_family == AF_INET6)
    1723             :     {
    1724          16 :         char       *pct = strchr(addr, '%');
    1725             : 
    1726          16 :         if (pct)
    1727           0 :             *pct = '\0';
    1728             :     }
    1729             : #endif
    1730          36 : }

Generated by: LCOV version 1.13