From 4bfd1ad9e04efcc196052477522e356e8c5194d7 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Fri, 6 Dec 2002 04:18:11 +0000 Subject: [PATCH] Add missing v6utils file. --- src/backend/libpq/v6util.c | 300 +++++++++++++++++++++++++++++++++++++ src/include/libpq/v6util.h | 17 +++ 2 files changed, 317 insertions(+) create mode 100644 src/backend/libpq/v6util.c create mode 100644 src/include/libpq/v6util.h diff --git a/src/backend/libpq/v6util.c b/src/backend/libpq/v6util.c new file mode 100644 index 0000000000..10bab95303 --- /dev/null +++ b/src/backend/libpq/v6util.c @@ -0,0 +1,300 @@ +#include "postgres.h" + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_NETINET_TCP_H +#include +#endif +#include +#include + +#include "libpq/libpq.h" +#include "miscadmin.h" + + + + + + +#ifdef HAVE_UNIX_SOCKETS +static int ga_unix(const char* path, const struct addrinfo* hintsp, + struct addrinfo** result); +#endif /* HAVE_UNIX_SOCKETS */ + + +int getaddrinfo2(const char* hostname, const char* servname, + const struct addrinfo* hintp, struct addrinfo **result) +{ +#ifdef HAVE_UNIX_SOCKETS + if( hintp != NULL && hintp->ai_family == AF_UNIX){ + return ga_unix(servname, hintp, result); + } + else { +#endif /* HAVE_UNIX_SOCKETS */ + return getaddrinfo(hostname, servname, hintp, result); +#ifdef HAVE_UNIX_SOCKETS + } +#endif /* HAVE_UNIX_SOCKETS */ +} + +void freeaddrinfo2(int hint_ai_family, struct addrinfo *ai) +{ +#ifdef HAVE_UNIX_SOCKETS + if(hint_ai_family == AF_UNIX){ + struct addrinfo *p; + while(ai != NULL){ + p = ai; + ai = ai->ai_next; + free(p->ai_addr); + free(p); + } + } + else { +#endif /* HAVE_UNIX_SOCKETS */ + freeaddrinfo(ai); +#ifdef HAVE_UNIX_SOCKETS + } +#endif /* HAVE_UNIX_SOCKETS */ +} + + +#ifdef HAVE_UNIX_SOCKETS +/** + * Bug: only one addrinfo is set even though hintsp is NULL or + * ai_socktype is 0 + * AI_CANNONNAME does not support. + */ +static int ga_unix(const char* path, const struct addrinfo* hintsp, + struct addrinfo** result) +{ + struct addrinfo hints; + struct addrinfo* aip; + struct sockaddr_un* unp; + memset(&hints, 0, sizeof(hints)); + + + if(hintsp == NULL){ + hints.ai_family = AF_UNIX; + hints.ai_socktype = SOCK_STREAM; + } + else { + memcpy(&hints, hintsp, sizeof(hints)); + } + if(hints.ai_socktype == 0){ + hints.ai_socktype = SOCK_STREAM; + } + + if(!(hints.ai_family == AF_UNIX)){ + printf("hints.ai_family is invalied ga_unix()\n"); + return EAI_ADDRFAMILY; + } + + + aip = calloc(1, sizeof(struct addrinfo)); + if(aip == NULL){ + return EAI_MEMORY; + } + + aip->ai_family = AF_UNIX; + aip->ai_socktype = hints.ai_socktype; + aip->ai_protocol = hints.ai_protocol; + aip->ai_next = NULL; + aip->ai_canonname = NULL; + *result = aip; + + unp = calloc(1, sizeof(struct sockaddr_un)); + if(aip == NULL){ + return EAI_MEMORY; + } + + unp->sun_family = AF_UNIX; + aip->ai_addr = (struct sockaddr*) unp; + aip->ai_addrlen = sizeof(struct sockaddr_un); + + if(strlen(path) >= sizeof(unp->sun_path)){ + return EAI_SERVICE; + } + strcpy(unp->sun_path, path); + +#if SALEN + unp->sun_len = sizeof(struct sockaddr_un); +#endif /* SALEN */ + + if(hints.ai_flags & AI_PASSIVE){ + unlink(unp->sun_path); + } + + return 0; +} +#endif /* HAVE_UNIX_SOCKETS */ + + + + + +/** + * SockAddr_ntop - set IP address string from SockAddr + * + * parameters... sa : SockAddr union + * dst : buffer for address string + * cnt : sizeof dst + * v4conv: non-zero: if address is IPv4 mapped IPv6 address then + * convert to IPv4 address. + * returns... pointer to dst + * if sa.sa_family is not AF_INET or AF_INET6 dst is set as empy string. + */ +char* SockAddr_ntop(const SockAddr* sa, char* dst, size_t cnt, int v4conv) +{ + switch(sa->sa.sa_family){ + case AF_INET: + inet_ntop(AF_INET, &sa->in.sin_addr, dst, cnt); + break; + case AF_INET6: + inet_ntop(AF_INET6, &sa->in6.sin6_addr, dst, cnt); + if(v4conv && IN6_IS_ADDR_V4MAPPED(&sa->in6.sin6_addr) ){ + strcpy(dst, dst + 7); + } + break; + default: + dst[0] = '\0'; + break; + } + return dst; +} + +int SockAddr_pton(SockAddr* sa, const char* src, size_t cnt) +{ + int i; + int family = AF_INET; + for(i = 0; i < cnt; i++){ + if(src[i] == ':'){ + family = AF_INET6; + break; + } + } + + sa->sa.sa_family = family; + switch(family){ + case AF_INET: + return inet_pton(AF_INET, src, &sa->in.sin_addr); + case AF_INET6: + return inet_pton(AF_INET6, src, &sa->in6.sin6_addr); + break; + default: + return -1; + } +} + + + + +/** + * isAF_INETx - check to see if sa is AF_INET or AF_INET6 + * + * parameters... sa : SockAddr union + * returns... + * if sa->sa.sa_famil is AF_INET or AF_INET6 then + * return 1 + * else + * return 0 + */ +int isAF_INETx(const SockAddr* sa) +{ + if(sa->sa.sa_family == AF_INET || + sa->sa.sa_family == AF_INET6 + ){ + return 1; + } + else { + return 0; + } +} + +int isAF_INETx2(int family) +{ + if(family == AF_INET || + family == AF_INET6 + ){ + return 1; + } + else { + return 0; + } +} + + +int rangeSockAddr(const SockAddr* addr, const SockAddr* netaddr, const SockAddr* netmask) +{ + if(addr->sa.sa_family == AF_INET){ + return rangeSockAddrAF_INET(addr, netaddr, netmask); + } + else if(addr->sa.sa_family == AF_INET6){ + return rangeSockAddrAF_INET6(addr, netaddr, netmask); + } + else { + return 0; + } +} + +int rangeSockAddrAF_INET(const SockAddr* addr, const SockAddr* netaddr, + const SockAddr* netmask) +{ + if(addr->sa.sa_family != AF_INET || + netaddr->sa.sa_family != AF_INET || + netmask->sa.sa_family != AF_INET ){ + return 0; + } + if( ((addr->in.sin_addr.s_addr ^ netaddr->in.sin_addr.s_addr ) & + netmask->in.sin_addr.s_addr) == 0){ + return 1; + } + else { + return 0; + } +} + +int rangeSockAddrAF_INET6(const SockAddr* addr, const SockAddr* netaddr, + const SockAddr* netmask) +{ + int i; + + if(IN6_IS_ADDR_V4MAPPED(&addr->in6.sin6_addr) ){ + SockAddr addr4; + convSockAddr6to4(addr, &addr4); + if(rangeSockAddrAF_INET(&addr4, netaddr, netmask)){ + return 1; + } + } + + if(netaddr->sa.sa_family != AF_INET6 || + netmask->sa.sa_family != AF_INET6 ){ + return 0; + } + + for( i = 0; i < 16; i++){ + if( ((addr->in6.sin6_addr.s6_addr[i] ^ netaddr->in6.sin6_addr.s6_addr[i] ) & + netmask->in6.sin6_addr.s6_addr[i] ) != 0){ + return 0; + } + } + + return 1; +} + +void convSockAddr6to4(const SockAddr* src, SockAddr* dst) +{ + char addr_str[INET6_ADDRSTRLEN]; + + dst->in.sin_family = AF_INET; + dst->in.sin_port = src->in6.sin6_port; + + dst->in.sin_addr.s_addr = src->in6.sin6_addr.s6_addr32[3]; + SockAddr_ntop(src, addr_str, INET6_ADDRSTRLEN, 0); +} + + diff --git a/src/include/libpq/v6util.h b/src/include/libpq/v6util.h new file mode 100644 index 0000000000..6e325d17c0 --- /dev/null +++ b/src/include/libpq/v6util.h @@ -0,0 +1,17 @@ +#ifndef V6UTIL_H +#define V6UTIL_H +void freeaddrinfo2(int hint_ai_family, struct addrinfo *ai); +int getaddrinfo2(const char* hostname, const char* servname, + const struct addrinfo* hintp, struct addrinfo **result); +char* SockAddr_ntop(const SockAddr* sa, char* dst, size_t cnt, int v4conv); +int SockAddr_pton(SockAddr* sa, const char* src, size_t cnt); +int isAF_INETx(const SockAddr* sa); +int isAF_INETx2(int family); +int rangeSockAddr(const SockAddr* addr, const SockAddr* netaddr, const SockAddr* netmask); +int rangeSockAddrAF_INET(const SockAddr* addr, const SockAddr* netaddr, + const SockAddr* netmask); +int rangeSockAddrAF_INET6(const SockAddr* addr, const SockAddr* netaddr, + const SockAddr* netmask); +void convSockAddr6to4(const SockAddr* src, SockAddr* dst); + +#endif /* V6UTIL_H */