diff -c --new-file --recursive pgsql/configure.in pgsql_ipv6/configure.in *** pgsql/configure.in Mon Nov 4 23:36:13 2002 --- pgsql_ipv6/configure.in Fri Nov 29 10:53:38 2002 *************** *** 1182,1187 **** --- 1182,1188 ---- src/include/dynloader.h:src/backend/port/dynloader/${template}.h src/include/pg_config_os.h:src/include/port/${template}.h src/Makefile.port:src/makefiles/Makefile.${template} + src/interfaces/libpq/v6util.c:src/backend/libpq/v6util.c ]) AC_CONFIG_HEADERS([src/include/pg_config.h], diff -c --new-file --recursive pgsql/src/backend/libpq/Makefile pgsql_ipv6/src/backend/libpq/Makefile *** pgsql/src/backend/libpq/Makefile Fri Jun 14 06:23:17 2002 --- pgsql_ipv6/src/backend/libpq/Makefile Fri Nov 29 03:06:18 2002 *************** *** 15,21 **** # be-fsstubs is here for historical reasons, probably belongs elsewhere OBJS = be-fsstubs.o be-secure.o auth.o crypt.o hba.o md5.o pqcomm.o \ ! pqformat.o pqsignal.o all: SUBSYS.o --- 15,21 ---- # be-fsstubs is here for historical reasons, probably belongs elsewhere OBJS = be-fsstubs.o be-secure.o auth.o crypt.o hba.o md5.o pqcomm.o \ ! pqformat.o pqsignal.o v6util.o all: SUBSYS.o diff -c --new-file --recursive pgsql/src/backend/libpq/auth.c pgsql_ipv6/src/backend/libpq/auth.c *** pgsql/src/backend/libpq/auth.c Thu Sep 5 01:31:34 2002 --- pgsql_ipv6/src/backend/libpq/auth.c Fri Nov 29 11:27:26 2002 *************** *** 410,418 **** */ { const char *hostinfo = "localhost"; - if (port->raddr.sa.sa_family == AF_INET) - hostinfo = inet_ntoa(port->raddr.in.sin_addr); elog(FATAL, "No pg_hba.conf entry for host %s, user %s, database %s", hostinfo, port->user, port->database); --- 410,421 ---- */ { const char *hostinfo = "localhost"; + char ip_hostinfo[INET6_ADDRSTRLEN]; + if (isAF_INETx(&port->raddr.sa) ){ + hostinfo = SockAddr_ntop(&port->raddr, ip_hostinfo, + INET6_ADDRSTRLEN, 1); + } elog(FATAL, "No pg_hba.conf entry for host %s, user %s, database %s", hostinfo, port->user, port->database); diff -c --new-file --recursive pgsql/src/backend/libpq/hba.c pgsql_ipv6/src/backend/libpq/hba.c *** pgsql/src/backend/libpq/hba.c Wed Sep 4 22:31:19 2002 --- pgsql_ipv6/src/backend/libpq/hba.c Fri Nov 29 11:28:11 2002 *************** *** 582,590 **** } else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0) { ! struct in_addr file_ip_addr, ! mask; ! if (strcmp(token, "hostssl") == 0) { #ifdef USE_SSL --- 582,589 ---- } else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0) { ! SockAddr file_ip_addr, mask; ! if (strcmp(token, "hostssl") == 0) { #ifdef USE_SSL *************** *** 619,634 **** if (!line) goto hba_syntax; token = lfirst(line); ! if (!inet_aton(token, &file_ip_addr)) ! goto hba_syntax; /* Read the mask field. */ line = lnext(line); if (!line) goto hba_syntax; token = lfirst(line); ! if (!inet_aton(token, &mask)) ! goto hba_syntax; /* Read the rest of the line. */ line = lnext(line); --- 618,642 ---- if (!line) goto hba_syntax; token = lfirst(line); ! ! if(SockAddr_pton(&file_ip_addr, token, strlen(token)) < 0){ ! goto hba_syntax; ! } /* Read the mask field. */ line = lnext(line); if (!line) goto hba_syntax; token = lfirst(line); ! ! if(SockAddr_pton(&mask, token, strlen(token)) < 0){ ! goto hba_syntax; ! } ! ! ! if(file_ip_addr.sa.sa_family != mask.sa.sa_family){ ! goto hba_syntax; ! } /* Read the rest of the line. */ line = lnext(line); *************** *** 639,646 **** goto hba_syntax; /* Must meet network restrictions */ ! if (port->raddr.sa.sa_family != AF_INET || ! ((file_ip_addr.s_addr ^ port->raddr.in.sin_addr.s_addr) & mask.s_addr) != 0) return; } else --- 647,653 ---- goto hba_syntax; /* Must meet network restrictions */ ! if (!isAF_INETx(&port->raddr) || !rangeSockAddr(&port->raddr, &file_ip_addr, &mask)) return; } else diff -c --new-file --recursive pgsql/src/backend/libpq/pg_hba.conf.sample pgsql_ipv6/src/backend/libpq/pg_hba.conf.sample *** pgsql/src/backend/libpq/pg_hba.conf.sample Sat Sep 14 20:35:46 2002 --- pgsql_ipv6/src/backend/libpq/pg_hba.conf.sample Fri Nov 29 03:06:18 2002 *************** *** 44,48 **** # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD ! local all all trust ! host all all 127.0.0.1 255.255.255.255 trust --- 44,49 ---- # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD ! local all all trust ! host all all 127.0.0.1 255.255.255.255 trust ! host all all ::1 ffff:ffff:ffff:fff:ffff:ffff:ffff trust diff -c --new-file --recursive pgsql/src/backend/libpq/pqcomm.c pgsql_ipv6/src/backend/libpq/pqcomm.c *** pgsql/src/backend/libpq/pqcomm.c Thu Sep 5 01:31:34 2002 --- pgsql_ipv6/src/backend/libpq/pqcomm.c Fri Nov 29 12:37:58 2002 *************** *** 85,90 **** --- 85,95 ---- extern ssize_t secure_write(Port *, const void *, size_t); static void pq_close(void); + #ifdef HAVE_UNIX_SOCKETS + int StreamServerPortSubAFUNIX1(unsigned short portNumber, + char *unixSocketName ); + int StreamServerPortSubAFUNIX2(void); + #endif /* HAVE_UNIX_SOCKETS */ /* *************** *** 182,351 **** StreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int *fdP) { ! SockAddr saddr; ! int fd, ! err; ! int maxconn; ! size_t len = 0; ! int one = 1; ! ! Assert(family == AF_INET || family == AF_UNIX); ! if ((fd = socket(family, SOCK_STREAM, 0)) < 0) ! { ! elog(LOG, "StreamServerPort: socket() failed: %m"); ! return STATUS_ERROR; ! } ! ! if (family == AF_INET) ! { ! if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, ! sizeof(one))) == -1) ! { ! elog(LOG, "StreamServerPort: setsockopt(SO_REUSEADDR) failed: %m"); ! return STATUS_ERROR; ! } ! } ! ! MemSet((char *) &saddr, 0, sizeof(saddr)); ! saddr.sa.sa_family = family; #ifdef HAVE_UNIX_SOCKETS ! if (family == AF_UNIX) ! { ! UNIXSOCK_PATH(saddr.un, portNumber, unixSocketName); ! len = UNIXSOCK_LEN(saddr.un); ! strcpy(sock_path, saddr.un.sun_path); ! ! /* ! * Grab an interlock file associated with the socket file. ! */ ! if (!CreateSocketLockFile(sock_path, true)) ! return STATUS_ERROR; ! ! /* ! * Once we have the interlock, we can safely delete any ! * pre-existing socket file to avoid failure at bind() time. ! */ ! unlink(sock_path); ! } #endif /* HAVE_UNIX_SOCKETS */ - if (family == AF_INET) - { - /* TCP/IP socket */ - if (hostName[0] == '\0') - saddr.in.sin_addr.s_addr = htonl(INADDR_ANY); - else - { - struct hostent *hp; - hp = gethostbyname(hostName); - if ((hp == NULL) || (hp->h_addrtype != AF_INET)) - { - elog(LOG, "StreamServerPort: gethostbyname(%s) failed", - hostName); - return STATUS_ERROR; - } - memmove((char *) &(saddr.in.sin_addr), (char *) hp->h_addr, - hp->h_length); - } ! saddr.in.sin_port = htons(portNumber); ! len = sizeof(struct sockaddr_in); ! } ! ! err = bind(fd, (struct sockaddr *) & saddr.sa, len); ! if (err < 0) ! { ! if (family == AF_UNIX) ! elog(LOG, "StreamServerPort: bind() failed: %m\n" ! "\tIs another postmaster already running on port %d?\n" ! "\tIf not, remove socket node (%s) and retry.", ! (int) portNumber, sock_path); ! else ! elog(LOG, "StreamServerPort: bind() failed: %m\n" ! "\tIs another postmaster already running on port %d?\n" ! "\tIf not, wait a few seconds and retry.", ! (int) portNumber); ! return STATUS_ERROR; ! } #ifdef HAVE_UNIX_SOCKETS ! if (family == AF_UNIX) ! { ! /* Arrange to unlink the socket file at exit */ ! on_proc_exit(StreamDoUnlink, 0); ! ! /* ! * Fix socket ownership/permission if requested. Note we must do ! * this before we listen() to avoid a window where unwanted ! * connections could get accepted. ! */ ! Assert(Unix_socket_group); ! if (Unix_socket_group[0] != '\0') ! { ! char *endptr; ! unsigned long int val; ! gid_t gid; ! val = strtoul(Unix_socket_group, &endptr, 10); ! if (*endptr == '\0') ! { ! /* numeric group id */ ! gid = val; ! } ! else ! { ! /* convert group name to id */ ! struct group *gr; ! gr = getgrnam(Unix_socket_group); ! if (!gr) ! { ! elog(LOG, "No such group as '%s'", ! Unix_socket_group); ! return STATUS_ERROR; ! } ! gid = gr->gr_gid; ! } ! if (chown(sock_path, -1, gid) == -1) ! { ! elog(LOG, "Could not set group of %s: %m", ! sock_path); ! return STATUS_ERROR; ! } ! } ! ! if (chmod(sock_path, Unix_socket_permissions) == -1) ! { ! elog(LOG, "Could not set permissions on %s: %m", ! sock_path); ! return STATUS_ERROR; ! } ! } ! #endif /* HAVE_UNIX_SOCKETS */ ! /* ! * Select appropriate accept-queue length limit. PG_SOMAXCONN is only ! * intended to provide a clamp on the request on platforms where an ! * overly large request provokes a kernel error (are there any?). ! */ ! maxconn = MaxBackends * 2; ! if (maxconn > PG_SOMAXCONN) ! maxconn = PG_SOMAXCONN; ! err = listen(fd, maxconn); ! if (err < 0) ! { ! elog(LOG, "StreamServerPort: listen() failed: %m"); ! return STATUS_ERROR; ! } ! *fdP = fd; - return STATUS_OK; - } /* * StreamConnection -- create a new connection with client using --- 187,384 ---- StreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int *fdP) { ! int fd, ! err; ! int maxconn; ! int one = 1; ! ! int ret; ! struct addrinfo* addrs = NULL; ! struct addrinfo hint; ! char portNumberStr[64]; ! char* service = portNumberStr; ! char* hostn = (hostName[0] == '\0')? NULL : hostName; ! ! Assert(family == AF_INET6 || family == AF_INET || family == AF_UNIX); ! ! memset(&hint, 0, sizeof(hint)); ! hint.ai_family = family; ! hint.ai_flags = AI_PASSIVE; ! hint.ai_socktype = SOCK_STREAM; ! snprintf(portNumberStr, sizeof(portNumberStr)/sizeof(char), ! "%d", portNumber); #ifdef HAVE_UNIX_SOCKETS ! if (family == AF_UNIX) { ! if(StreamServerPortSubAFUNIX1(portNumber, unixSocketName) != STATUS_OK){ ! return STATUS_ERROR; ! } ! service = sock_path; ! } #endif /* HAVE_UNIX_SOCKETS */ ! ret = getaddrinfo2(hostn, service, &hint, &addrs); ! if(ret || addrs == NULL){ ! elog(LOG, "FATAL: StreamServerPort: getaddrinfo2() failed: %s\n", ! gai_strerror(ret)); ! freeaddrinfo2(hint.ai_family, addrs); ! return STATUS_ERROR; ! } ! ! ! /** YY DEBUG ! if(addrs->ai_family == AF_UNIX){ ! printf("%s-%s-%s \n", "debug: AF_UNIX!", unixSocketName, hostName); ! } ! else { ! printf("%s", "debug: NOT AF_UNIX!\n"); ! } ! fflush(stdout); ! **/ ! ! if( (fd = socket(addrs->ai_family, SOCK_STREAM, 0)) < 0){ ! elog(LOG, "FATAL: StreamServerPort: socket() failed: %s\n", ! strerror(errno)); ! freeaddrinfo2(hint.ai_family, addrs); ! return STATUS_ERROR; ! } ! ! if( isAF_INETx2(family) ){ ! if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, ! sizeof(one) )) == -1 ){ ! elog(LOG, "FATAL: StreamServerPort: setsockopt(SO_REUSEADDR) failed: %s\n", ! strerror(errno)); ! freeaddrinfo2(hint.ai_family, addrs); ! return STATUS_ERROR; ! } ! } ! ! ! err = bind(fd, addrs->ai_addr, addrs->ai_addrlen); ! if(err < 0){ ! elog(LOG, "FATAL: StreamServerPort: bind() failed: %s\n" ! "\tIs another postmaster already running on port %d?\n", ! strerror(errno), (int) portNumber); ! if (family == AF_UNIX) ! elog(LOG, "\tIf not, remove socket node (%s) and retry.\n", ! sock_path); ! else ! elog(LOG, "\tIf not, wait a few seconds and retry.\n"); ! freeaddrinfo2(hint.ai_family, addrs); ! return STATUS_ERROR; ! } #ifdef HAVE_UNIX_SOCKETS ! if (family == AF_UNIX){ ! if(StreamServerPortSubAFUNIX2() != STATUS_OK){ ! freeaddrinfo2(hint.ai_family, addrs); ! return STATUS_ERROR; ! } ! } ! #endif ! /* ! * Select appropriate accept-queue length limit. PG_SOMAXCONN is only ! * intended to provide a clamp on the request on platforms where an ! * overly large request provokes a kernel error (are there any?). ! */ ! maxconn = MaxBackends * 2; ! if (maxconn > PG_SOMAXCONN) ! maxconn = PG_SOMAXCONN; ! ! err = listen(fd, maxconn); ! if (err < 0) { ! elog(LOG, "FATAL: StreamServerPort: listen() failed: %s\n", ! strerror(errno)); ! freeaddrinfo2(hint.ai_family, addrs); ! return STATUS_ERROR; ! } ! ! *fdP = fd; ! freeaddrinfo2(hint.ai_family, addrs); ! return STATUS_OK; ! } ! #ifdef HAVE_UNIX_SOCKETS ! int StreamServerPortSubAFUNIX1(unsigned short portNumber, ! char *unixSocketName ) ! { ! SockAddr saddr; ! int len; ! MemSet((char *) &saddr, 0, sizeof(saddr)); ! ! UNIXSOCK_PATH(saddr.un, portNumber, unixSocketName); ! len = UNIXSOCK_LEN(saddr.un); ! strcpy(sock_path, saddr.un.sun_path); ! ! /* ! * Grab an interlock file associated with the socket file. ! */ ! if (!CreateSocketLockFile(sock_path, true)) ! return STATUS_ERROR; ! ! /* ! * Once we have the interlock, we can safely delete any ! * pre-existing socket file to avoid failure at bind() time. ! */ ! unlink(sock_path); ! ! return STATUS_OK; ! } ! ! ! int StreamServerPortSubAFUNIX2(void) ! { ! /* Arrange to unlink the socket file at exit */ ! on_proc_exit(StreamDoUnlink, 0); ! ! /* ! * Fix socket ownership/permission if requested. Note we must do ! * this before we listen() to avoid a window where unwanted ! * connections could get accepted. ! */ ! Assert(Unix_socket_group); ! if (Unix_socket_group[0] != '\0') { ! char *endptr; ! unsigned long int val; ! gid_t gid; ! ! val = strtoul(Unix_socket_group, &endptr, 10); ! if (*endptr == '\0'){ /* numeric group id */ ! gid = val; ! } ! else { /* convert group name to id */ ! struct group *gr; ! gr = getgrnam(Unix_socket_group); ! if (!gr) { ! elog(LOG, "FATAL: no such group '%s'\n", ! Unix_socket_group); ! return STATUS_ERROR; ! } ! gid = gr->gr_gid; ! } ! if (chown(sock_path, -1, gid) == -1){ ! elog(LOG, "FATAL: could not set group of %s: %s\n", ! sock_path, strerror(errno)); ! return STATUS_ERROR; ! } ! } ! ! if (chmod(sock_path, Unix_socket_permissions) == -1){ ! elog(LOG, "FATAL: could not set permissions on %s: %s\n", ! sock_path, strerror(errno)); ! return STATUS_ERROR; ! } ! return STATUS_OK; ! } ! #endif /* HAVE_UNIX_SOCKETS */ /* * StreamConnection -- create a new connection with client using *************** *** 391,398 **** return STATUS_ERROR; } /* select NODELAY and KEEPALIVE options if it's a TCP connection */ ! if (port->laddr.sa.sa_family == AF_INET) { int on = 1; --- 424,443 ---- return STATUS_ERROR; } + /* DEBUG YY + { + char l_hostinfo[INET6_ADDRSTRLEN]; + char r_hostinfo[INET6_ADDRSTRLEN]; + SockAddr_ntop(&port->laddr, l_hostinfo, INET6_ADDRSTRLEN, 1); + SockAddr_ntop(&port->raddr, r_hostinfo, INET6_ADDRSTRLEN, 1); + printf("StreamConnect() l: %s r: %s\n", l_hostinfo, r_hostinfo); + printf("StreamConnect() l: %d r: %d\n", port->laddr.sa.sa_family, + port->raddr.sa.sa_family); + } + */ + /* select NODELAY and KEEPALIVE options if it's a TCP connection */ ! if ( isAF_INETx(&port->laddr) ) { int on = 1; diff -c --new-file --recursive pgsql/src/backend/libpq/v6util.c pgsql_ipv6/src/backend/libpq/v6util.c *** pgsql/src/backend/libpq/v6util.c Thu Jan 1 02:00:00 1970 --- pgsql_ipv6/src/backend/libpq/v6util.c Fri Nov 29 11:05:11 2002 *************** *** 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 -c --new-file --recursive pgsql/src/backend/postmaster/postmaster.c pgsql_ipv6/src/backend/postmaster/postmaster.c *** pgsql/src/backend/postmaster/postmaster.c Thu Nov 21 08:36:08 2002 --- pgsql_ipv6/src/backend/postmaster/postmaster.c Fri Nov 29 11:29:37 2002 *************** *** 669,675 **** */ if (NetServer) { ! status = StreamServerPort(AF_INET, VirtualHost, (unsigned short) PostPortNumber, UnixSocketDir, &ServerSock_INET); --- 669,675 ---- */ if (NetServer) { ! status = StreamServerPort(AF_INET6, VirtualHost, (unsigned short) PostPortNumber, UnixSocketDir, &ServerSock_INET); *************** *** 2091,2103 **** /* * Get the remote host name and port for logging and status display. */ ! if (port->raddr.sa.sa_family == AF_INET) { unsigned short remote_port; char *host_addr; remote_port = ntohs(port->raddr.in.sin_port); ! host_addr = inet_ntoa(port->raddr.in.sin_addr); remote_host = NULL; --- 2091,2104 ---- /* * Get the remote host name and port for logging and status display. */ ! if (isAF_INETx(&port->raddr)) { unsigned short remote_port; char *host_addr; + char ip_hostinfo[INET6_ADDRSTRLEN]; remote_port = ntohs(port->raddr.in.sin_port); ! host_addr = SockAddr_ntop(&port->raddr, ip_hostinfo, INET6_ADDRSTRLEN, 1); remote_host = NULL; diff -c --new-file --recursive pgsql/src/include/libpq/libpq.h pgsql_ipv6/src/include/libpq/libpq.h *** pgsql/src/include/libpq/libpq.h Thu Sep 5 01:31:35 2002 --- pgsql_ipv6/src/include/libpq/libpq.h Fri Nov 29 03:06:18 2002 *************** *** 19,24 **** --- 19,25 ---- #include "lib/stringinfo.h" #include "libpq/libpq-be.h" + #include "libpq/v6util.h" /* ---------------- * PQArgBlock diff -c --new-file --recursive pgsql/src/include/libpq/pqcomm.h pgsql_ipv6/src/include/libpq/pqcomm.h *** pgsql/src/include/libpq/pqcomm.h Wed Sep 4 22:31:42 2002 --- pgsql_ipv6/src/include/libpq/pqcomm.h Fri Nov 29 11:30:51 2002 *************** *** 47,52 **** --- 47,53 ---- { struct sockaddr sa; struct sockaddr_in in; + struct sockaddr_in6 in6; struct sockaddr_un un; } SockAddr; diff -c --new-file --recursive pgsql/src/include/libpq/v6util.h pgsql_ipv6/src/include/libpq/v6util.h *** pgsql/src/include/libpq/v6util.h Thu Jan 1 02:00:00 1970 --- pgsql_ipv6/src/include/libpq/v6util.h Fri Nov 29 03:06:18 2002 *************** *** 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 */ diff -c --new-file --recursive pgsql/src/interfaces/libpq/Makefile pgsql_ipv6/src/interfaces/libpq/Makefile *** pgsql/src/interfaces/libpq/Makefile Tue Sep 3 23:45:44 2002 --- pgsql_ipv6/src/interfaces/libpq/Makefile Fri Nov 29 03:06:18 2002 *************** *** 23,28 **** --- 23,29 ---- OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \ pqexpbuffer.o dllist.o md5.o pqsignal.o fe-secure.o \ wchar.o encnames.o \ + v6util.o \ $(filter inet_aton.o snprintf.o strerror.o, $(LIBOBJS)) diff -c --new-file --recursive pgsql/src/interfaces/libpq/fe-connect.c pgsql_ipv6/src/interfaces/libpq/fe-connect.c *** pgsql/src/interfaces/libpq/fe-connect.c Fri Oct 25 01:35:55 2002 --- pgsql_ipv6/src/interfaces/libpq/fe-connect.c Fri Nov 29 11:31:40 2002 *************** *** 39,44 **** --- 39,47 ---- #include #endif + #include "libpq/v6util.h" + + #ifndef HAVE_STRDUP #include "strdup.h" #endif *************** *** 786,791 **** --- 789,803 ---- { int portno, family; + struct addrinfo* addrs = NULL; + struct addrinfo* addr_cur = NULL; + struct addrinfo hint; + const char* node = NULL; + const char* unix_node = "unix"; + char portNoStr[64]; + int ret; + int sockfd; + #ifdef USE_SSL StartupPacket np; /* Used to negotiate SSL connection */ *************** *** 815,915 **** MemSet((char *) &conn->raddr, 0, sizeof(conn->raddr)); ! if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0') ! { ! /* Using pghostaddr avoids a hostname lookup */ ! /* Note that this supports IPv4 only */ ! struct in_addr addr; ! ! if (!inet_aton(conn->pghostaddr, &addr)) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("invalid host address: %s\n"), ! conn->pghostaddr); ! goto connect_errReturn; ! } ! ! family = AF_INET; ! ! memmove((char *) &(conn->raddr.in.sin_addr), ! (char *) &addr, sizeof(addr)); ! } ! else if (conn->pghost != NULL && conn->pghost[0] != '\0') ! { ! /* Using pghost, so we have to look-up the hostname */ ! struct hostent *hp; ! ! hp = gethostbyname(conn->pghost); ! if ((hp == NULL) || (hp->h_addrtype != AF_INET)) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("unknown host name: %s\n"), ! conn->pghost); ! goto connect_errReturn; ! } ! family = AF_INET; ! ! memmove((char *) &(conn->raddr.in.sin_addr), ! (char *) hp->h_addr, ! hp->h_length); } ! else ! { ! /* pghostaddr and pghost are NULL, so use Unix domain socket */ ! family = AF_UNIX; } - /* Set family */ - conn->raddr.sa.sa_family = family; - - /* Set port number */ if (conn->pgport != NULL && conn->pgport[0] != '\0') ! portno = atoi(conn->pgport); else ! portno = DEF_PGPORT; ! ! if (family == AF_INET) ! { ! conn->raddr.in.sin_port = htons((unsigned short) (portno)); ! conn->raddr_len = sizeof(struct sockaddr_in); } #ifdef HAVE_UNIX_SOCKETS ! else ! { ! UNIXSOCK_PATH(conn->raddr.un, portno, conn->pgunixsocket); ! conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un); #ifdef USE_SSL /* Don't bother requesting SSL over a Unix socket */ conn->allow_ssl_try = false; conn->require_ssl = false; #endif } ! #endif ! ! /* Open a socket */ ! if ((conn->sock = socket(family, SOCK_STREAM, 0)) < 0) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("could not create socket: %s\n"), ! SOCK_STRERROR(SOCK_ERRNO)); ! goto connect_errReturn; ! } ! ! /* ! * Set the right options. Normally, we need nonblocking I/O, and we ! * don't want delay of outgoing data for AF_INET sockets. If we are ! * using SSL, then we need the blocking I/O (XXX Can this be fixed?). ! */ ! ! if (family == AF_INET) ! { ! if (!connectNoDelay(conn)) ! goto connect_errReturn; ! } #if !defined(USE_SSL) ! if (connectMakeNonblocking(conn) == 0) ! goto connect_errReturn; #endif /* ---------- --- 827,893 ---- MemSet((char *) &conn->raddr, 0, sizeof(conn->raddr)); ! MemSet(&hint, 0, sizeof(hint)); ! hint.ai_socktype = SOCK_STREAM; ! if(conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0'){ ! node = conn->pghostaddr; ! hint.ai_family = AF_UNSPEC; ! } ! else if (conn->pghost != NULL && conn->pghost[0] != '\0'){ ! node = conn->pghost; ! hint.ai_family = AF_UNSPEC; } ! #ifdef HAVE_UNIX_SOCKETS ! else { ! node = unix_node; ! hint.ai_family = AF_UNIX; } + #endif /* HAVE_UNIX_SOCKETS */ if (conn->pgport != NULL && conn->pgport[0] != '\0') ! portno = atoi(conn->pgport); else ! portno = DEF_PGPORT; ! ! if(hint.ai_family == AF_UNSPEC){ ! snprintf(portNoStr, sizeof(portNoStr)/sizeof(char), ! "%d", portno); } #ifdef HAVE_UNIX_SOCKETS ! else { ! UNIXSOCK_PATH(conn->raddr.un, portno, conn->pgunixsocket); ! conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un); ! strcpy(portNoStr, conn->raddr.un.sun_path); #ifdef USE_SSL /* Don't bother requesting SSL over a Unix socket */ conn->allow_ssl_try = false; conn->require_ssl = false; #endif } ! #endif /* HAVE_UNIX_SOCKETS */ + ret = getaddrinfo2(node, portNoStr, &hint, &addrs); + if(ret || addrs == NULL){ + printfPQExpBuffer(&conn->errorMessage, + libpq_gettext("failed to getaddrinfo(): %s\n"), + gai_strerror(ret) ); + goto connect_errReturn; + } + addr_cur = addrs; + do { + sockfd = socket(addr_cur->ai_family, addr_cur->ai_socktype, + addr_cur->ai_protocol); + if(sockfd < 0){ + continue; + } + conn->sock = sockfd; + if (isAF_INETx2(addr_cur->ai_family) ){ + if (!connectNoDelay(conn)) + goto connect_errReturn; + } #if !defined(USE_SSL) ! if (connectMakeNonblocking(conn) == 0) ! goto connect_errReturn; #endif /* ---------- *************** *** 922,952 **** * ---------- */ retry1: ! if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0) ! { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ goto retry1; ! if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || SOCK_ERRNO == 0) ! { ! /* ! * This is fine - we're in non-blocking mode, and the ! * connection is in progress. ! */ ! conn->status = CONNECTION_STARTED; ! } ! else ! { ! /* Something's gone wrong */ ! connectFailureMessage(conn, SOCK_ERRNO); ! goto connect_errReturn; ! } ! } ! else ! { ! /* We're connected already */ ! conn->status = CONNECTION_MADE; } #ifdef USE_SSL --- 900,941 ---- * ---------- */ retry1: ! if(connect(sockfd, addr_cur->ai_addr, addr_cur->ai_addrlen) == 0){ ! /* We're connected already */ ! conn->status = CONNECTION_MADE; ! break; ! } ! else { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ goto retry1; ! if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || SOCK_ERRNO == 0){ ! ! /* ! * This is fine - we're in non-blocking mode, and the ! * connection is in progress. ! */ ! conn->status = CONNECTION_STARTED; ! break; ! } ! } ! close(sockfd); ! } while( (addr_cur = addr_cur->ai_next) != NULL); ! ! if(addr_cur == NULL){ ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("could not create socket: %s\n"), ! SOCK_STRERROR(SOCK_ERRNO)); ! ! goto connect_errReturn; ! } ! else { ! family = addr_cur->ai_family; ! memmove(&conn->raddr, addr_cur->ai_addr, addr_cur->ai_addrlen); ! conn->raddr_len = addr_cur->ai_addrlen; ! freeaddrinfo2(hint.ai_family, addrs); ! addrs = NULL; } #ifdef USE_SSL *************** *** 1038,1044 **** conn->sock = -1; } conn->status = CONNECTION_BAD; ! return 0; } --- 1027,1035 ---- conn->sock = -1; } conn->status = CONNECTION_BAD; ! if(addrs != NULL){ ! freeaddrinfo2(hint.ai_family, addrs); ! } return 0; }