diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-11-10 20:13:27 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-11-10 20:13:27 +0000 |
commit | a2100230087b702e42d30a1e6a95e3192ffb16ff (patch) | |
tree | cb74c5df0cb0fbcbf02de45e87184c5c73ac161b /src/backend/utils/adt/network.c | |
parent | d7f8ffa781aeb33062d59541a497c2cacac73f0e (diff) |
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.
Diffstat (limited to 'src/backend/utils/adt/network.c')
-rw-r--r-- | src/backend/utils/adt/network.c | 142 |
1 files changed, 87 insertions, 55 deletions
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c index a3070f29e76..52f4e8ecd2f 100644 --- a/src/backend/utils/adt/network.c +++ b/src/backend/utils/adt/network.c @@ -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'; @@ -364,6 +362,40 @@ network_host(PG_FUNCTION_ARGS) } 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) { inet *ip = PG_GETARG_INET_P(0); @@ -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; + + mask <<= (32 - ip_bits(ip)); + + ip_v4addr(dst) = htonl(mask); - if (inet_net_ntop(AF_INET, &addr, 32, tmp, sizeof(tmp)) == NULL) - elog(ERROR, "unable to print netmask (%s)", strerror(errno)); + 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); } /* |