Index: network.c =================================================================== RCS file: /cvsroot/pgsql-server/src/backend/utils/adt/network.c,v retrieving revision 1.35 retrieving revision 1.41 diff -c -c -r1.35 -r1.41 *** network.c 2 Sep 2002 02:47:04 -0000 1.35 --- network.c 13 May 2003 18:03:07 -0000 1.41 *************** *** 3,9 **** * is for IP V4 CIDR notation, but prepared for V6: just * add the necessary bits where the comments indicate. * ! * $Header: /cvsroot/pgsql-server/src/backend/utils/adt/network.c,v 1.35 2002/09/02 02:47:04 momjian Exp $ * * Jon Postel RIP 16 Oct 1998 */ --- 3,9 ---- * is for IP V4 CIDR notation, but prepared for V6: just * add the necessary bits where the comments indicate. * ! * $Header: /cvsroot/pgsql-server/src/backend/utils/adt/network.c,v 1.41 2003/05/13 18:03:07 tgl Exp $ * * Jon Postel RIP 16 Oct 1998 */ *************** *** 16,21 **** --- 16,22 ---- #include #include "catalog/pg_type.h" + #include "libpq/pqformat.h" #include "utils/builtins.h" #include "utils/inet.h" *************** *** 51,59 **** int bits; inet *dst; - dst = (inet *) palloc(VARHDRSZ + sizeof(inet_struct)); /* make sure any unused bits in a CIDR value are zeroed */ ! MemSet(dst, 0, VARHDRSZ + sizeof(inet_struct)); /* First, try for an IP V4 address: */ ip_family(dst) = AF_INET; --- 52,59 ---- int bits; inet *dst; /* make sure any unused bits in a CIDR value are zeroed */ ! dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct)); /* First, try for an IP V4 address: */ ip_family(dst) = AF_INET; *************** *** 149,154 **** --- 149,249 ---- } + /* + * inet_recv - converts external binary format to inet + * + * The external representation is (one byte apiece for) + * family, bits, type, address length, address in network byte order. + */ + Datum + inet_recv(PG_FUNCTION_ARGS) + { + StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); + inet *addr; + char *addrptr; + int bits; + int nb, + i; + + /* make sure any unused bits in a CIDR value are zeroed */ + addr = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct)); + + ip_family(addr) = pq_getmsgbyte(buf); + if (ip_family(addr) != AF_INET) + elog(ERROR, "Invalid family in external inet"); + bits = pq_getmsgbyte(buf); + if (bits < 0 || bits > 32) + elog(ERROR, "Invalid bits in external inet"); + ip_bits(addr) = bits; + ip_type(addr) = pq_getmsgbyte(buf); + if (ip_type(addr) != 0 && ip_type(addr) != 1) + elog(ERROR, "Invalid type in external inet"); + nb = pq_getmsgbyte(buf); + if (nb != ip_addrsize(addr)) + elog(ERROR, "Invalid length in external inet"); + + VARATT_SIZEP(addr) = VARHDRSZ + + ((char *) &ip_v4addr(addr) - (char *) VARDATA(addr)) + + ip_addrsize(addr); + + addrptr = (char *) &ip_v4addr(addr); + for (i = 0; i < nb; i++) + addrptr[i] = pq_getmsgbyte(buf); + + /* + * Error check: CIDR values must not have any bits set beyond the + * masklen. XXX this code is not IPV6 ready. + */ + if (ip_type(addr)) + { + if (!v4addressOK(ip_v4addr(addr), bits)) + elog(ERROR, "invalid external CIDR value: has bits set to right of mask"); + } + + PG_RETURN_INET_P(addr); + } + + /* share code with INET case */ + Datum + cidr_recv(PG_FUNCTION_ARGS) + { + return inet_recv(fcinfo); + } + + /* + * inet_send - converts inet to binary format + */ + Datum + inet_send(PG_FUNCTION_ARGS) + { + inet *addr = PG_GETARG_INET_P(0); + StringInfoData buf; + char *addrptr; + int nb, + i; + + pq_begintypsend(&buf); + pq_sendbyte(&buf, ip_family(addr)); + pq_sendbyte(&buf, ip_bits(addr)); + pq_sendbyte(&buf, ip_type(addr)); + nb = ip_addrsize(addr); + if (nb < 0) + nb = 0; + pq_sendbyte(&buf, nb); + addrptr = (char *) &ip_v4addr(addr); + for (i = 0; i < nb; i++) + pq_sendbyte(&buf, addrptr[i]); + PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); + } + + /* share code with INET case */ + Datum + cidr_send(PG_FUNCTION_ARGS) + { + return inet_send(fcinfo); + } + + static Datum text_network(text *src, int type) { *************** *** 494,502 **** inet *ip = PG_GETARG_INET_P(0); 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) { --- 589,596 ---- inet *ip = PG_GETARG_INET_P(0); inet *dst; /* make sure any unused bits are zeroed */ ! dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct)); if (ip_family(ip) == AF_INET) { *************** *** 534,542 **** inet *ip = PG_GETARG_INET_P(0); 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) { --- 628,635 ---- inet *ip = PG_GETARG_INET_P(0); inet *dst; /* make sure any unused bits are zeroed */ ! dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct)); if (ip_family(ip) == AF_INET) { *************** *** 574,582 **** inet *ip = PG_GETARG_INET_P(0); 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) { --- 667,674 ---- inet *ip = PG_GETARG_INET_P(0); inet *dst; /* make sure any unused bits are zeroed */ ! dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct)); if (ip_family(ip) == AF_INET) { *************** *** 609,614 **** --- 701,745 ---- PG_RETURN_INET_P(dst); } + Datum + network_hostmask(PG_FUNCTION_ARGS) + { + inet *ip = PG_GETARG_INET_P(0); + inet *dst; + + /* make sure any unused bits are zeroed */ + dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct)); + + if (ip_family(ip) == AF_INET) + { + /* It's an IP V4 address: */ + unsigned long mask = 0xffffffff; + + /* + * Only shift if the mask len is < 32 bits .. + */ + + if (ip_bits(ip) < 32) + mask >>= ip_bits(ip); + else + mask = 0; + + 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)); + + ip_family(dst) = ip_family(ip); + ip_type(dst) = 0; + VARATT_SIZEP(dst) = VARHDRSZ + + ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst)) + + ip_addrsize(dst); + + PG_RETURN_INET_P(dst); + } /* * Convert a value of a network datatype to an approximate scalar value.