mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user