⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 network.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	PostgreSQL type definitions for the INET and CIDR types. * *	$PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.56 2005/10/17 16:24:19 tgl Exp $ * *	Jon Postel RIP 16 Oct 1998 */#include "postgres.h"#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include "access/hash.h"#include "catalog/pg_type.h"#include "libpq/ip.h"#include "libpq/libpq-be.h"#include "libpq/pqformat.h"#include "miscadmin.h"#include "utils/builtins.h"#include "utils/inet.h"static Datum text_network(text *src, int type);static int32 network_cmp_internal(inet *a1, inet *a2);static int	bitncmp(void *l, void *r, int n);static bool addressOK(unsigned char *a, int bits, int family);static int	ip_addrsize(inet *inetptr);/* *	Access macros. */#define ip_family(inetptr) \	(((inet_struct *)VARDATA(inetptr))->family)#define ip_bits(inetptr) \	(((inet_struct *)VARDATA(inetptr))->bits)#define ip_type(inetptr) \	(((inet_struct *)VARDATA(inetptr))->type)#define ip_addr(inetptr) \	(((inet_struct *)VARDATA(inetptr))->ipaddr)#define ip_maxbits(inetptr) \	(ip_family(inetptr) == PGSQL_AF_INET ? 32 : 128)/* * Return the number of bytes of storage needed for this data type. */static intip_addrsize(inet *inetptr){	switch (ip_family(inetptr))	{		case PGSQL_AF_INET:			return 4;		case PGSQL_AF_INET6:			return 16;		default:			return 0;	}}/* Common input routine */static inet *network_in(char *src, int type){	int			bits;	inet	   *dst;	dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));	/*	 * First, check to see if this is an IPv6 or IPv4 address.	IPv6 addresses	 * will have a : somewhere in them (several, in fact) so if there is one	 * present, assume it's V6, otherwise assume it's V4.	 */	if (strchr(src, ':') != NULL)		ip_family(dst) = PGSQL_AF_INET6;	else		ip_family(dst) = PGSQL_AF_INET;	bits = inet_net_pton(ip_family(dst), src, ip_addr(dst),						 type ? ip_addrsize(dst) : -1);	if ((bits < 0) || (bits > ip_maxbits(dst)))		ereport(ERROR,				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),		/* translator: first %s is inet or cidr */				 errmsg("invalid input syntax for type %s: \"%s\"",						type ? "cidr" : "inet", src)));	/*	 * Error check: CIDR values must not have any bits set beyond the masklen.	 */	if (type)	{		if (!addressOK(ip_addr(dst), bits, ip_family(dst)))			ereport(ERROR,					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),					 errmsg("invalid cidr value: \"%s\"", src),					 errdetail("Value has bits set to right of mask.")));	}	VARATT_SIZEP(dst) = VARHDRSZ		+ ((char *) ip_addr(dst) - (char *) VARDATA(dst))		+ ip_addrsize(dst);	ip_bits(dst) = bits;	ip_type(dst) = type;	return dst;}/* INET address reader.  */Datuminet_in(PG_FUNCTION_ARGS){	char	   *src = PG_GETARG_CSTRING(0);	PG_RETURN_INET_P(network_in(src, 0));}/* CIDR address reader.  */Datumcidr_in(PG_FUNCTION_ARGS){	char	   *src = PG_GETARG_CSTRING(0);	PG_RETURN_INET_P(network_in(src, 1));}/* *	INET address output function. */Datuminet_out(PG_FUNCTION_ARGS){	inet	   *src = PG_GETARG_INET_P(0);	char		tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];	char	   *dst;	int			len;	dst = inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),						tmp, sizeof(tmp));	if (dst == NULL)		ereport(ERROR,				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),				 errmsg("could not format inet value: %m")));	/* For CIDR, add /n if not present */	if (ip_type(src) && strchr(tmp, '/') == NULL)	{		len = strlen(tmp);		snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));	}	PG_RETURN_CSTRING(pstrdup(tmp));}/* share code with INET case */Datumcidr_out(PG_FUNCTION_ARGS){	return inet_out(fcinfo);}/* *		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. */Datuminet_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) != PGSQL_AF_INET &&		ip_family(addr) != PGSQL_AF_INET6)		ereport(ERROR,				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),			   errmsg("invalid address family in external \"inet\" value")));	bits = pq_getmsgbyte(buf);	if (bits < 0 || bits > ip_maxbits(addr))		ereport(ERROR,				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),				 errmsg("invalid bits in external \"inet\" value")));	ip_bits(addr) = bits;	ip_type(addr) = pq_getmsgbyte(buf);	if (ip_type(addr) != 0 && ip_type(addr) != 1)		ereport(ERROR,				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),				 errmsg("invalid type in external \"inet\" value")));	nb = pq_getmsgbyte(buf);	if (nb != ip_addrsize(addr))		ereport(ERROR,				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),				 errmsg("invalid length in external \"inet\" value")));	VARATT_SIZEP(addr) = VARHDRSZ		+ ((char *) ip_addr(addr) - (char *) VARDATA(addr))		+ ip_addrsize(addr);	addrptr = (char *) ip_addr(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.	 */	if (ip_type(addr))	{		if (!addressOK(ip_addr(addr), bits, ip_family(addr)))			ereport(ERROR,					(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),					 errmsg("invalid external \"cidr\" value"),					 errdetail("Value has bits set to right of mask.")));	}	PG_RETURN_INET_P(addr);}/* share code with INET case */Datumcidr_recv(PG_FUNCTION_ARGS){	return inet_recv(fcinfo);}/* *		inet_send			- converts inet to binary format */Datuminet_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_addr(addr);	for (i = 0; i < nb; i++)		pq_sendbyte(&buf, addrptr[i]);	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* share code with INET case */Datumcidr_send(PG_FUNCTION_ARGS){	return inet_send(fcinfo);}static Datumtext_network(text *src, int type){	int			len = VARSIZE(src) - VARHDRSZ;	char	   *str = palloc(len + 1);	memcpy(str, VARDATA(src), len);	*(str + len) = '\0';	PG_RETURN_INET_P(network_in(str, type));}Datumtext_cidr(PG_FUNCTION_ARGS){	return text_network(PG_GETARG_TEXT_P(0), 1);}Datumtext_inet(PG_FUNCTION_ARGS){	return text_network(PG_GETARG_TEXT_P(0), 0);}Datuminet_set_masklen(PG_FUNCTION_ARGS){	inet	   *src = PG_GETARG_INET_P(0);	int			bits = PG_GETARG_INT32(1);	inet	   *dst;	if (bits == -1)		bits = ip_maxbits(src);	if ((bits < 0) || (bits > ip_maxbits(src)))		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("invalid mask length: %d", bits)));	/* clone the original data */	dst = (inet *) palloc(VARSIZE(src));	memcpy(dst, src, VARSIZE(src));	ip_bits(dst) = bits;	PG_RETURN_INET_P(dst);}/* *	Basic comparison function for sorting and inet/cidr comparisons. * * Comparison is first on the common bits of the network part, then on * the length of the network part, and then on the whole unmasked address. * The effect is that the network part is the major sort key, and for * equal network parts we sort on the host part.  Note this is only sane * for CIDR if address bits to the right of the mask are guaranteed zero; * otherwise logically-equal CIDRs might compare different. */static int32network_cmp_internal(inet *a1, inet *a2){	if (ip_family(a1) == ip_family(a2))	{		int			order;		order = bitncmp(ip_addr(a1), ip_addr(a2),						Min(ip_bits(a1), ip_bits(a2)));		if (order != 0)			return order;		order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));		if (order != 0)			return order;		return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));	}	return ip_family(a1) - ip_family(a2);}Datumnetwork_cmp(PG_FUNCTION_ARGS){	inet	   *a1 = PG_GETARG_INET_P(0);	inet	   *a2 = PG_GETARG_INET_P(1);	PG_RETURN_INT32(network_cmp_internal(a1, a2));}/* *	Boolean ordering tests. */Datumnetwork_lt(PG_FUNCTION_ARGS){	inet	   *a1 = PG_GETARG_INET_P(0);	inet	   *a2 = PG_GETARG_INET_P(1);	PG_RETURN_BOOL(network_cmp_internal(a1, a2) < 0);}Datumnetwork_le(PG_FUNCTION_ARGS){	inet	   *a1 = PG_GETARG_INET_P(0);	inet	   *a2 = PG_GETARG_INET_P(1);	PG_RETURN_BOOL(network_cmp_internal(a1, a2) <= 0);}Datumnetwork_eq(PG_FUNCTION_ARGS){	inet	   *a1 = PG_GETARG_INET_P(0);	inet	   *a2 = PG_GETARG_INET_P(1);	PG_RETURN_BOOL(network_cmp_internal(a1, a2) == 0);}Datumnetwork_ge(PG_FUNCTION_ARGS){	inet	   *a1 = PG_GETARG_INET_P(0);	inet	   *a2 = PG_GETARG_INET_P(1);	PG_RETURN_BOOL(network_cmp_internal(a1, a2) >= 0);}Datumnetwork_gt(PG_FUNCTION_ARGS){	inet	   *a1 = PG_GETARG_INET_P(0);	inet	   *a2 = PG_GETARG_INET_P(1);	PG_RETURN_BOOL(network_cmp_internal(a1, a2) > 0);}Datumnetwork_ne(PG_FUNCTION_ARGS){	inet	   *a1 = PG_GETARG_INET_P(0);	inet	   *a2 = PG_GETARG_INET_P(1);	PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);}/* * Support function for hash indexes on inet/cidr. * * Since network_cmp considers only ip_family, ip_bits, and ip_addr, * only these fields may be used in the hash; in particular don't use type. */Datumhashinet(PG_FUNCTION_ARGS){	inet	   *addr = PG_GETARG_INET_P(0);	int			addrsize = ip_addrsize(addr);	unsigned char key[sizeof(inet_struct)];	Assert(addrsize + 2 <= sizeof(key));	key[0] = ip_family(addr);	key[1] = ip_bits(addr);	memcpy(key + 2, ip_addr(addr), addrsize);	return hash_any(key, addrsize + 2);}/* *	Boolean network-inclusion tests. */Datumnetwork_sub(PG_FUNCTION_ARGS){	inet	   *a1 = PG_GETARG_INET_P(0);	inet	   *a2 = PG_GETARG_INET_P(1);	if (ip_family(a1) == ip_family(a2))	{		PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2)					 && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);	}	PG_RETURN_BOOL(false);}Datumnetwork_subeq(PG_FUNCTION_ARGS){	inet	   *a1 = PG_GETARG_INET_P(0);	inet	   *a2 = PG_GETARG_INET_P(1);	if (ip_family(a1) == ip_family(a2))	{		PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2)					 && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);	}	PG_RETURN_BOOL(false);}Datumnetwork_sup(PG_FUNCTION_ARGS){	inet	   *a1 = PG_GETARG_INET_P(0);	inet	   *a2 = PG_GETARG_INET_P(1);	if (ip_family(a1) == ip_family(a2))	{		PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2)					 && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);	}	PG_RETURN_BOOL(false);}Datumnetwork_supeq(PG_FUNCTION_ARGS){	inet	   *a1 = PG_GETARG_INET_P(0);	inet	   *a2 = PG_GETARG_INET_P(1);	if (ip_family(a1) == ip_family(a2))	{		PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2)					 && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);	}	PG_RETURN_BOOL(false);}/* * Extract data from a network datatype. */Datumnetwork_host(PG_FUNCTION_ARGS){	inet	   *ip = PG_GETARG_INET_P(0);	text	   *ret;	int			len;	char	   *ptr;	char		tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];	/* force display of max bits, regardless of masklen... */	if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),					  tmp, sizeof(tmp)) == NULL)		ereport(ERROR,				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),				 errmsg("could not format inet value: %m")));	/* Suppress /n if present (shouldn't happen now) */	if ((ptr = strchr(tmp, '/')) != NULL)		*ptr = '\0';	/* 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);}Datumnetwork_show(PG_FUNCTION_ARGS){	inet	   *ip = PG_GETARG_INET_P(0);	text	   *ret;	int			len;	char		tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];	if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),					  tmp, sizeof(tmp)) == NULL)		ereport(ERROR,				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),				 errmsg("could not format inet value: %m")));	/* Add /n if not present (which it won't be) */	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);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -