1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Adjust INET/CIDR display conventions and reimplement some INET/CIDR

functions, per recent discussions on pghackers.  For now, I have called
the verbose-display formatting function text(), but will reconsider if
enough people object.
initdb forced.
This commit is contained in:
Tom Lane
2000-11-10 20:13:27 +00:00
parent d7f8ffa781
commit a210023008
10 changed files with 272 additions and 254 deletions

View File

@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.8 1999/07/17 20:17:56 momjian Exp $";
static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.9 2000/11/10 20:13:25 tgl Exp $";
#endif
@ -56,7 +56,7 @@ inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size)
{
switch (af)
{
case AF_INET:
case AF_INET:
return (inet_cidr_ntop_ipv4(src, bits, dst, size));
default:
errno = EAFNOSUPPORT;
@ -102,15 +102,12 @@ inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
/* Format whole octets. */
for (b = bits / 8; b > 0; b--)
{
if (size < sizeof "255.")
if (size < sizeof ".255")
goto emsgsize;
t = dst;
dst += SPRINTF((dst, "%u", *src++));
if (b > 1)
{
if (dst != odst)
*dst++ = '.';
*dst = '\0';
}
dst += SPRINTF((dst, "%u", *src++));
size -= (size_t) (dst - t);
}
@ -132,6 +129,7 @@ inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
if (size < sizeof "/32")
goto emsgsize;
dst += SPRINTF((dst, "/%u", bits));
return (odst);
emsgsize:
@ -159,7 +157,7 @@ inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
{
switch (af)
{
case AF_INET:
case AF_INET:
return (inet_net_ntop_ipv4(src, bits, dst, size));
default:
errno = EAFNOSUPPORT;
@ -185,48 +183,34 @@ inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
{
char *odst = dst;
char *t;
size_t len = 4;
int b,
tb;
int len = 4;
int b;
if (bits < 0 || bits > 32)
{
errno = EINVAL;
return (NULL);
}
if (bits == 0)
{
if (size < sizeof "0")
goto emsgsize;
*dst++ = '0';
size--;
*dst = '\0';
}
/* Format whole octets plus nonzero trailing octets. */
tb = (bits == 32) ? 31 : bits;
for (b = 0; bits != 0 && (b <= (tb / 8) || (b < len && *src != 0)); b++)
/* Always format all four octets, regardless of mask length. */
for (b = len; b > 0; b--)
{
if (size < sizeof "255.")
if (size < sizeof ".255")
goto emsgsize;
t = dst;
dst += SPRINTF((dst, "%u", *src++));
if (b + 1 <= (tb / 8) || (b + 1 < len && *src != 0))
{
if (dst != odst)
*dst++ = '.';
*dst = '\0';
}
dst += SPRINTF((dst, "%u", *src++));
size -= (size_t) (dst - t);
}
/* don't print masklen if 32 bits */
if (bits == 32)
return odst;
/* Format CIDR /width. */
if (size < sizeof "/32")
goto emsgsize;
dst += SPRINTF((dst, "/%u", bits));
if (bits != 32)
{
if (size < sizeof "/32")
goto emsgsize;
dst += SPRINTF((dst, "/%u", bits));
}
return (odst);

View File

@ -3,7 +3,7 @@
* is for IP V4 CIDR notation, but prepared for V6: just
* add the necessary bits where the comments indicate.
*
* $Header: /cvsroot/pgsql/src/backend/utils/adt/network.c,v 1.25 2000/10/27 01:52:15 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/network.c,v 1.26 2000/11/10 20:13:25 tgl Exp $
*
* Jon Postel RIP 16 Oct 1998
*/
@ -67,12 +67,12 @@ network_in(char *src, int type)
/*
* Error check: CIDR values must not have any bits set beyond the masklen.
* XXX this code not IPV6 ready.
* XXX this code is not IPV6 ready.
*/
if (type)
{
if (! v4addressOK(ip_v4addr(dst), bits))
elog(ERROR, "invalid CIDR value '%s': width too small", src);
elog(ERROR, "invalid CIDR value '%s': has bits set to right of mask", src);
}
VARATT_SIZEP(dst) = VARHDRSZ
@ -338,12 +338,10 @@ network_host(PG_FUNCTION_ARGS)
char *ptr,
tmp[sizeof("255.255.255.255/32")];
if (ip_type(ip))
elog(ERROR, "CIDR type has no host part");
if (ip_family(ip) == AF_INET)
{
/* It's an IP V4 address: */
/* force display of 32 bits, regardless of masklen... */
if (inet_net_ntop(AF_INET, &ip_v4addr(ip), 32, tmp, sizeof(tmp)) == NULL)
elog(ERROR, "unable to print host (%s)", strerror(errno));
}
@ -351,7 +349,7 @@ network_host(PG_FUNCTION_ARGS)
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "unknown address family (%d)", ip_family(ip));
/* Suppress /n if present */
/* Suppress /n if present (shouldn't happen now) */
if ((ptr = strchr(tmp, '/')) != NULL)
*ptr = '\0';
@ -363,6 +361,40 @@ network_host(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(ret);
}
Datum
network_show(PG_FUNCTION_ARGS)
{
inet *ip = PG_GETARG_INET_P(0);
text *ret;
int len;
char tmp[sizeof("255.255.255.255/32")];
if (ip_family(ip) == AF_INET)
{
/* It's an IP V4 address: */
/* force display of 32 bits, regardless of masklen... */
if (inet_net_ntop(AF_INET, &ip_v4addr(ip), 32, tmp, sizeof(tmp)) == NULL)
elog(ERROR, "unable to print host (%s)", strerror(errno));
}
else
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "unknown address family (%d)", ip_family(ip));
/* Add /n if not present */
if (strchr(tmp, '/') == NULL)
{
len = strlen(tmp);
snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
}
/* Return string as a text datum */
len = strlen(tmp);
ret = (text *) palloc(len + VARHDRSZ);
VARATT_SIZEP(ret) = len + VARHDRSZ;
memcpy(VARDATA(ret), tmp, len);
PG_RETURN_TEXT_P(ret);
}
Datum
network_masklen(PG_FUNCTION_ARGS)
{
@ -375,100 +407,100 @@ Datum
network_broadcast(PG_FUNCTION_ARGS)
{
inet *ip = PG_GETARG_INET_P(0);
text *ret;
int len;
char *ptr,
tmp[sizeof("255.255.255.255/32")];
inet *dst;
dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
/* make sure any unused bits are zeroed */
MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct));
if (ip_family(ip) == AF_INET)
{
/* It's an IP V4 address: */
int addr;
unsigned long mask = 0xffffffff;
if (ip_bits(ip) < 32)
mask >>= ip_bits(ip);
addr = htonl(ntohl(ip_v4addr(ip)) | mask);
mask >>= ip_bits(ip);
if (inet_net_ntop(AF_INET, &addr, 32, tmp, sizeof(tmp)) == NULL)
elog(ERROR, "unable to print address (%s)", strerror(errno));
ip_v4addr(dst) = htonl(ntohl(ip_v4addr(ip)) | mask);
}
else
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "unknown address family (%d)", ip_family(ip));
/* Suppress /n if present */
if ((ptr = strchr(tmp, '/')) != NULL)
*ptr = '\0';
ip_family(dst) = ip_family(ip);
ip_bits(dst) = ip_bits(ip);
ip_type(dst) = 0;
VARATT_SIZEP(dst) = VARHDRSZ
+ ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst))
+ ip_addrsize(dst);
/* Return string as a text datum */
len = strlen(tmp);
ret = (text *) palloc(len + VARHDRSZ);
VARATT_SIZEP(ret) = len + VARHDRSZ;
memcpy(VARDATA(ret), tmp, len);
PG_RETURN_TEXT_P(ret);
PG_RETURN_INET_P(dst);
}
Datum
network_network(PG_FUNCTION_ARGS)
{
inet *ip = PG_GETARG_INET_P(0);
text *ret;
int len;
char tmp[sizeof("255.255.255.255/32")];
inet *dst;
dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
/* make sure any unused bits are zeroed */
MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct));
if (ip_family(ip) == AF_INET)
{
/* It's an IP V4 address: */
int addr = htonl(ntohl(ip_v4addr(ip)) & (0xffffffff << (32 - ip_bits(ip))));
unsigned long mask = 0xffffffff;
if (inet_cidr_ntop(AF_INET, &addr, ip_bits(ip), tmp, sizeof(tmp)) == NULL)
elog(ERROR, "unable to print network (%s)", strerror(errno));
mask <<= (32 - ip_bits(ip));
ip_v4addr(dst) = htonl(ntohl(ip_v4addr(ip)) & mask);
}
else
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "unknown address family (%d)", ip_family(ip));
/* Return string as a text datum */
len = strlen(tmp);
ret = (text *) palloc(len + VARHDRSZ);
VARATT_SIZEP(ret) = len + VARHDRSZ;
memcpy(VARDATA(ret), tmp, len);
PG_RETURN_TEXT_P(ret);
ip_family(dst) = ip_family(ip);
ip_bits(dst) = ip_bits(ip);
ip_type(dst) = 1;
VARATT_SIZEP(dst) = VARHDRSZ
+ ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst))
+ ip_addrsize(dst);
PG_RETURN_INET_P(dst);
}
Datum
network_netmask(PG_FUNCTION_ARGS)
{
inet *ip = PG_GETARG_INET_P(0);
text *ret;
int len;
char *ptr,
tmp[sizeof("255.255.255.255/32")];
inet *dst;
dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct));
/* make sure any unused bits are zeroed */
MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct));
if (ip_family(ip) == AF_INET)
{
/* It's an IP V4 address: */
int addr = htonl(ip_bits(ip) ?
(-1 << (32 - ip_bits(ip))) & 0xffffffff : 0x00000000);
unsigned long mask = 0xffffffff;
if (inet_net_ntop(AF_INET, &addr, 32, tmp, sizeof(tmp)) == NULL)
elog(ERROR, "unable to print netmask (%s)", strerror(errno));
mask <<= (32 - ip_bits(ip));
ip_v4addr(dst) = htonl(mask);
ip_bits(dst) = 32;
}
else
/* Go for an IPV6 address here, before faulting out: */
elog(ERROR, "unknown address family (%d)", ip_family(ip));
/* Suppress /n if present */
if ((ptr = strchr(tmp, '/')) != NULL)
*ptr = '\0';
ip_family(dst) = ip_family(ip);
ip_type(dst) = 0;
VARATT_SIZEP(dst) = VARHDRSZ
+ ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst))
+ ip_addrsize(dst);
/* Return string as a text datum */
len = strlen(tmp);
ret = (text *) palloc(len + VARHDRSZ);
VARATT_SIZEP(ret) = len + VARHDRSZ;
memcpy(VARDATA(ret), tmp, len);
PG_RETURN_TEXT_P(ret);
PG_RETURN_INET_P(dst);
}
/*

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: catversion.h,v 1.56 2000/11/08 16:59:50 petere Exp $
* $Id: catversion.h,v 1.57 2000/11/10 20:13:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200011080
#define CATALOG_VERSION_NO 200011101
#endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_proc.h,v 1.172 2000/11/06 15:58:46 thomas Exp $
* $Id: pg_proc.h,v 1.173 2000/11/10 20:13:26 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@ -2270,17 +2270,19 @@ DESCR("is-supernet");
DATA(insert OID = 930 ( network_supeq PGUID 12 f t t t 2 f 16 "869 869" 100 0 0 100 network_supeq - ));
DESCR("is-supernet-or-equal");
/* inet/cidr versions */
DATA(insert OID = 696 ( netmask PGUID 12 f t t t 1 f 25 "869" 100 0 0 100 network_netmask - ));
/* inet/cidr functions */
DATA(insert OID = 683 ( network PGUID 12 f t t t 1 f 650 "869" 100 0 0 100 network_network - ));
DESCR("network part of address");
DATA(insert OID = 696 ( netmask PGUID 12 f t t t 1 f 869 "869" 100 0 0 100 network_netmask - ));
DESCR("netmask of address");
DATA(insert OID = 697 ( masklen PGUID 12 f t t t 1 f 23 "869" 100 0 0 100 network_masklen - ));
DESCR("netmask length");
DATA(insert OID = 698 ( broadcast PGUID 12 f t t t 1 f 25 "869" 100 0 0 100 network_broadcast - ));
DESCR("broadcast address");
DATA(insert OID = 698 ( broadcast PGUID 12 f t t t 1 f 869 "869" 100 0 0 100 network_broadcast - ));
DESCR("broadcast address of network");
DATA(insert OID = 699 ( host PGUID 12 f t t t 1 f 25 "869" 100 0 0 100 network_host - ));
DESCR("host address");
DATA(insert OID = 683 ( network PGUID 12 f t t t 1 f 25 "869" 100 0 0 100 network_network - ));
DESCR("network address");
DESCR("show address octets only");
DATA(insert OID = 730 ( text PGUID 12 f t t t 1 f 25 "869" 100 0 0 100 network_show - ));
DESCR("show all parts of inet/cidr value");
DATA(insert OID = 1691 ( boolle PGUID 12 f t t t 2 f 16 "16 16" 100 0 0 100 boolle - ));
DESCR("less-than-or-equal");

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: builtins.h,v 1.140 2000/10/24 20:16:47 petere Exp $
* $Id: builtins.h,v 1.141 2000/11/10 20:13:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -504,6 +504,7 @@ extern Datum network_netmask(PG_FUNCTION_ARGS);
extern Datum network_masklen(PG_FUNCTION_ARGS);
extern Datum network_broadcast(PG_FUNCTION_ARGS);
extern Datum network_host(PG_FUNCTION_ARGS);
extern Datum network_show(PG_FUNCTION_ARGS);
/* mac.c */
extern Datum macaddr_in(PG_FUNCTION_ARGS);

View File

@ -17,7 +17,7 @@ INSERT INTO INET_TBL (c, i) VALUES ('10', '11.1.2.3/8');
INSERT INTO INET_TBL (c, i) VALUES ('10', '9.1.2.3/8');
-- check that CIDR rejects invalid input:
INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/24', '192.168.1.226');
ERROR: invalid CIDR value '192.168.1.2/24': width too small
ERROR: invalid CIDR value '192.168.1.2/24': has bits set to right of mask
SELECT '' AS ten, c AS cidr, i AS inet FROM INET_TBL;
ten | cidr | inet
-----+--------------+------------------
@ -34,35 +34,35 @@ SELECT '' AS ten, c AS cidr, i AS inet FROM INET_TBL;
(10 rows)
-- now test some support functions
SELECT '' AS ten, i AS inet, host(i) FROM INET_TBL;
ten | inet | host
-----+------------------+---------------
| 192.168.1.226/24 | 192.168.1.226
| 192.168.1.226 | 192.168.1.226
| 10.1.2.3/8 | 10.1.2.3
| 10.1.2.3/8 | 10.1.2.3
| 10.1.2.3 | 10.1.2.3
| 10.1.2.3/24 | 10.1.2.3
| 10.1.2.3/16 | 10.1.2.3
| 10.1.2.3/8 | 10.1.2.3
| 11.1.2.3/8 | 11.1.2.3
| 9.1.2.3/8 | 9.1.2.3
SELECT '' AS ten, i AS inet, host(i), text(i) FROM INET_TBL;
ten | inet | host | text
-----+------------------+---------------+------------------
| 192.168.1.226/24 | 192.168.1.226 | 192.168.1.226/24
| 192.168.1.226 | 192.168.1.226 | 192.168.1.226/32
| 10.1.2.3/8 | 10.1.2.3 | 10.1.2.3/8
| 10.1.2.3/8 | 10.1.2.3 | 10.1.2.3/8
| 10.1.2.3 | 10.1.2.3 | 10.1.2.3/32
| 10.1.2.3/24 | 10.1.2.3 | 10.1.2.3/24
| 10.1.2.3/16 | 10.1.2.3 | 10.1.2.3/16
| 10.1.2.3/8 | 10.1.2.3 | 10.1.2.3/8
| 11.1.2.3/8 | 11.1.2.3 | 11.1.2.3/8
| 9.1.2.3/8 | 9.1.2.3 | 9.1.2.3/8
(10 rows)
SELECT '' AS ten, c AS cidr, broadcast(c),
i AS inet, broadcast(i) FROM INET_TBL;
ten | cidr | broadcast | inet | broadcast
-----+--------------+-----------------+------------------+-----------------
| 192.168.1/24 | 192.168.1.255 | 192.168.1.226/24 | 192.168.1.255
| 192.168.1/24 | 192.168.1.255 | 192.168.1.226 | 255.255.255.255
| 10/8 | 10.255.255.255 | 10.1.2.3/8 | 10.255.255.255
| 10.0.0.0/32 | 255.255.255.255 | 10.1.2.3/8 | 10.255.255.255
| 10.1.2.3/32 | 255.255.255.255 | 10.1.2.3 | 255.255.255.255
| 10.1.2/24 | 10.1.2.255 | 10.1.2.3/24 | 10.1.2.255
| 10.1/16 | 10.1.255.255 | 10.1.2.3/16 | 10.1.255.255
| 10/8 | 10.255.255.255 | 10.1.2.3/8 | 10.255.255.255
| 10/8 | 10.255.255.255 | 11.1.2.3/8 | 11.255.255.255
| 10/8 | 10.255.255.255 | 9.1.2.3/8 | 9.255.255.255
ten | cidr | broadcast | inet | broadcast
-----+--------------+------------------+------------------+------------------
| 192.168.1/24 | 192.168.1.255/24 | 192.168.1.226/24 | 192.168.1.255/24
| 192.168.1/24 | 192.168.1.255/24 | 192.168.1.226 | 255.255.255.255
| 10/8 | 10.255.255.255/8 | 10.1.2.3/8 | 10.255.255.255/8
| 10.0.0.0/32 | 255.255.255.255 | 10.1.2.3/8 | 10.255.255.255/8
| 10.1.2.3/32 | 255.255.255.255 | 10.1.2.3 | 255.255.255.255
| 10.1.2/24 | 10.1.2.255/24 | 10.1.2.3/24 | 10.1.2.255/24
| 10.1/16 | 10.1.255.255/16 | 10.1.2.3/16 | 10.1.255.255/16
| 10/8 | 10.255.255.255/8 | 10.1.2.3/8 | 10.255.255.255/8
| 10/8 | 10.255.255.255/8 | 11.1.2.3/8 | 11.255.255.255/8
| 10/8 | 10.255.255.255/8 | 9.1.2.3/8 | 9.255.255.255/8
(10 rows)
SELECT '' AS ten, c AS cidr, network(c) AS "network(cidr)",

View File

@ -23,7 +23,7 @@ SELECT '' AS ten, c AS cidr, i AS inet FROM INET_TBL;
-- now test some support functions
SELECT '' AS ten, i AS inet, host(i) FROM INET_TBL;
SELECT '' AS ten, i AS inet, host(i), text(i) FROM INET_TBL;
SELECT '' AS ten, c AS cidr, broadcast(c),
i AS inet, broadcast(i) FROM INET_TBL;
SELECT '' AS ten, c AS cidr, network(c) AS "network(cidr)",