📄 network.c
字号:
Datumnetwork_abbrev(PG_FUNCTION_ARGS){ inet *ip = PG_GETARG_INET_P(0); text *ret; char *dst; int len; char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")]; if (ip_type(ip)) dst = inet_cidr_ntop(ip_family(ip), ip_addr(ip), ip_bits(ip), tmp, sizeof(tmp)); else dst = inet_net_ntop(ip_family(ip), ip_addr(ip), ip_bits(ip), tmp, sizeof(tmp)); if (dst == NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("could not format inet value: %m"))); /* 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_masklen(PG_FUNCTION_ARGS){ inet *ip = PG_GETARG_INET_P(0); PG_RETURN_INT32(ip_bits(ip));}Datumnetwork_family(PG_FUNCTION_ARGS){ inet *ip = PG_GETARG_INET_P(0); switch (ip_family(ip)) { case PGSQL_AF_INET: PG_RETURN_INT32(4); break; case PGSQL_AF_INET6: PG_RETURN_INT32(6); break; default: PG_RETURN_INT32(0); break; }}Datumnetwork_broadcast(PG_FUNCTION_ARGS){ inet *ip = PG_GETARG_INET_P(0); inet *dst; int byte; int bits; int maxbytes; unsigned char mask; unsigned char *a, *b; /* make sure any unused bits are zeroed */ dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct)); if (ip_family(ip) == PGSQL_AF_INET) maxbytes = 4; else maxbytes = 16; bits = ip_bits(ip); a = ip_addr(ip); b = ip_addr(dst); for (byte = 0; byte < maxbytes; byte++) { if (bits >= 8) { mask = 0x00; bits -= 8; } else if (bits == 0) mask = 0xff; else { mask = 0xff >> bits; bits = 0; } b[byte] = a[byte] | mask; } ip_family(dst) = ip_family(ip); ip_bits(dst) = ip_bits(ip); ip_type(dst) = 0; VARATT_SIZEP(dst) = VARHDRSZ + ((char *) ip_addr(dst) - (char *) VARDATA(dst)) + ip_addrsize(dst); PG_RETURN_INET_P(dst);}Datumnetwork_network(PG_FUNCTION_ARGS){ inet *ip = PG_GETARG_INET_P(0); inet *dst; int byte; int bits; unsigned char mask; unsigned char *a, *b; /* make sure any unused bits are zeroed */ dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct)); bits = ip_bits(ip); a = ip_addr(ip); b = ip_addr(dst); byte = 0; while (bits) { if (bits >= 8) { mask = 0xff; bits -= 8; } else { mask = 0xff << (8 - bits); bits = 0; } b[byte] = a[byte] & mask; byte++; } ip_family(dst) = ip_family(ip); ip_bits(dst) = ip_bits(ip); ip_type(dst) = 1; VARATT_SIZEP(dst) = VARHDRSZ + ((char *) ip_addr(dst) - (char *) VARDATA(dst)) + ip_addrsize(dst); PG_RETURN_INET_P(dst);}Datumnetwork_netmask(PG_FUNCTION_ARGS){ inet *ip = PG_GETARG_INET_P(0); inet *dst; int byte; int bits; unsigned char mask; unsigned char *b; /* make sure any unused bits are zeroed */ dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct)); bits = ip_bits(ip); b = ip_addr(dst); byte = 0; while (bits) { if (bits >= 8) { mask = 0xff; bits -= 8; } else { mask = 0xff << (8 - bits); bits = 0; } b[byte] = mask; byte++; } ip_family(dst) = ip_family(ip); ip_bits(dst) = ip_maxbits(ip); ip_type(dst) = 0; VARATT_SIZEP(dst) = VARHDRSZ + ((char *) ip_addr(dst) - (char *) VARDATA(dst)) + ip_addrsize(dst); PG_RETURN_INET_P(dst);}Datumnetwork_hostmask(PG_FUNCTION_ARGS){ inet *ip = PG_GETARG_INET_P(0); inet *dst; int byte; int bits; int maxbytes; unsigned char mask; unsigned char *b; /* make sure any unused bits are zeroed */ dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct)); if (ip_family(ip) == PGSQL_AF_INET) maxbytes = 4; else maxbytes = 16; bits = ip_maxbits(ip) - ip_bits(ip); b = ip_addr(dst); byte = maxbytes - 1; while (bits) { if (bits >= 8) { mask = 0xff; bits -= 8; } else { mask = 0xff >> (8 - bits); bits = 0; } b[byte] = mask; byte--; } ip_family(dst) = ip_family(ip); ip_bits(dst) = ip_maxbits(ip); ip_type(dst) = 0; VARATT_SIZEP(dst) = VARHDRSZ + ((char *) ip_addr(dst) - (char *) VARDATA(dst)) + ip_addrsize(dst); PG_RETURN_INET_P(dst);}/* * Convert a value of a network datatype to an approximate scalar value. * This is used for estimating selectivities of inequality operators * involving network types. * * Currently, inet/cidr values are simply converted to the IPv4 address; * this will need more thought when IPv6 is supported too. MAC addresses * are converted to their numeric equivalent as well (OK since we have a * double to play in). */doubleconvert_network_to_scalar(Datum value, Oid typid){ switch (typid) { case INETOID: case CIDROID: { inet *ip = DatumGetInetP(value); int len; double res; int i; /* * Note that we don't use the full address here. */ if (ip_family(ip) == PGSQL_AF_INET) len = 4; else len = 5; res = ip_family(ip); for (i = 0; i < len; i++) { res *= 256; res += ip_addr(ip)[i]; } return res; break; } case MACADDROID: { macaddr *mac = DatumGetMacaddrP(value); double res; res = (mac->a << 16) | (mac->b << 8) | (mac->c); res *= 256 * 256 * 256; res += (mac->d << 16) | (mac->e << 8) | (mac->f); return res; } } /* * Can't get here unless someone tries to use scalarltsel/scalargtsel on * an operator with one network and one non-network operand. */ elog(ERROR, "unsupported type: %u", typid); return 0;}/* * int * bitncmp(l, r, n) * compare bit masks l and r, for n bits. * return: * -1, 1, or 0 in the libc tradition. * note: * network byte order assumed. this means 192.5.5.240/28 has * 0x11110000 in its fourth octet. * author: * Paul Vixie (ISC), June 1996 */static intbitncmp(void *l, void *r, int n){ u_int lb, rb; int x, b; b = n / 8; x = memcmp(l, r, b); if (x) return (x); lb = ((const u_char *) l)[b]; rb = ((const u_char *) r)[b]; for (b = n % 8; b > 0; b--) { if ((lb & 0x80) != (rb & 0x80)) { if (lb & 0x80) return (1); return (-1); } lb <<= 1; rb <<= 1; } return (0);}static booladdressOK(unsigned char *a, int bits, int family){ int byte; int nbits; int maxbits; int maxbytes; unsigned char mask; if (family == PGSQL_AF_INET) { maxbits = 32; maxbytes = 4; } else { maxbits = 128; maxbytes = 16; } Assert(bits <= maxbits); if (bits == maxbits) return true; byte = bits / 8; nbits = bits % 8; mask = 0xff; if (bits != 0) mask >>= nbits; while (byte < maxbytes) { if ((a[byte] & mask) != 0) return false; mask = 0xff; byte++; } return true;}/* * These functions are used by planner to generate indexscan limits * for clauses a << b and a <<= b *//* return the minimal value for an IP on a given network */Datumnetwork_scan_first(Datum in){ return DirectFunctionCall1(network_network, in);}/* * return "last" IP on a given network. It's the broadcast address, * however, masklen has to be set to its max btis, since * 192.168.0.255/24 is considered less than 192.168.0.255/32 * * inet_set_masklen() hacked to max out the masklength to 128 for IPv6 * and 32 for IPv4 when given '-1' as argument. */Datumnetwork_scan_last(Datum in){ return DirectFunctionCall2(inet_set_masklen, DirectFunctionCall1(network_broadcast, in), Int32GetDatum(-1));}/* * IP address that the client is connecting from (NULL if Unix socket) */Datuminet_client_addr(PG_FUNCTION_ARGS){ Port *port = MyProcPort; char remote_host[NI_MAXHOST]; int ret; if (port == NULL) PG_RETURN_NULL(); switch (port->raddr.addr.ss_family) { case AF_INET:#ifdef HAVE_IPV6 case AF_INET6:#endif break; default: PG_RETURN_NULL(); } remote_host[0] = '\0'; ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen, remote_host, sizeof(remote_host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); if (ret) PG_RETURN_NULL(); PG_RETURN_INET_P(network_in(remote_host, 0));}/* * port that the client is connecting from (NULL if Unix socket) */Datuminet_client_port(PG_FUNCTION_ARGS){ Port *port = MyProcPort; char remote_port[NI_MAXSERV]; int ret; if (port == NULL) PG_RETURN_NULL(); switch (port->raddr.addr.ss_family) { case AF_INET:#ifdef HAVE_IPV6 case AF_INET6:#endif break; default: PG_RETURN_NULL(); } remote_port[0] = '\0'; ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen, NULL, 0, remote_port, sizeof(remote_port), NI_NUMERICHOST | NI_NUMERICSERV); if (ret) PG_RETURN_NULL(); PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));}/* * IP address that the server accepted the connection on (NULL if Unix socket) */Datuminet_server_addr(PG_FUNCTION_ARGS){ Port *port = MyProcPort; char local_host[NI_MAXHOST]; int ret; if (port == NULL) PG_RETURN_NULL(); switch (port->laddr.addr.ss_family) { case AF_INET:#ifdef HAVE_IPV6 case AF_INET6:#endif break; default: PG_RETURN_NULL(); } local_host[0] = '\0'; ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen, local_host, sizeof(local_host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); if (ret) PG_RETURN_NULL(); PG_RETURN_INET_P(network_in(local_host, 0));}/* * port that the server accepted the connection on (NULL if Unix socket) */Datuminet_server_port(PG_FUNCTION_ARGS){ Port *port = MyProcPort; char local_port[NI_MAXSERV]; int ret; if (port == NULL) PG_RETURN_NULL(); switch (port->laddr.addr.ss_family) { case AF_INET:#ifdef HAVE_IPV6 case AF_INET6:#endif break; default: PG_RETURN_NULL(); } local_port[0] = '\0'; ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen, NULL, 0, local_port, sizeof(local_port), NI_NUMERICHOST | NI_NUMERICSERV); if (ret) PG_RETURN_NULL(); PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -