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

Generated by: LCOV version 1.11