diff -c --new-file --recursive pgsql/configure pgsql_ipv6/configure *** pgsql/configure Mon Nov 4 23:36:13 2002 --- pgsql_ipv6/configure Fri Nov 29 03:06:18 2002 *************** *** 15777,15783 **** ac_config_files="$ac_config_files GNUmakefile src/Makefile.global" ! ac_config_links="$ac_config_links src/backend/port/dynloader.c:src/backend/port/dynloader/${template}.c src/backend/port/pg_sema.c:${SEMA_IMPLEMENTATION} src/backend/port/pg_shmem.c:${SHMEM_IMPLEMENTATION} 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}" ac_config_headers="$ac_config_headers src/include/pg_config.h" --- 15777,15783 ---- ac_config_files="$ac_config_files GNUmakefile src/Makefile.global" ! ac_config_links="$ac_config_links src/backend/port/dynloader.c:src/backend/port/dynloader/${template}.c src/backend/port/pg_sema.c:${SEMA_IMPLEMENTATION} src/backend/port/pg_shmem.c:${SHMEM_IMPLEMENTATION} 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="$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 03:06:18 2002 *************** *** 394,399 **** --- 394,400 ---- */ if (hba_getauthmethod(port) != STATUS_OK) elog(FATAL, "Missing or erroneous pg_hba.conf file, see postmaster log for details"); + switch (port->auth_method) { *************** *** 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); --- 411,422 ---- */ { 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 03:06:18 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 *************** *** 616,634 **** /* Read the IP address field. */ line = lnext(line); 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); --- 615,644 ---- /* Read the IP address field. */ line = lnext(line); + + 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 --- 649,655 ---- 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 03:06:18 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,187 **** --- 187,389 ---- 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() + { + /* 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 */ + + #if 0 + int + StreamServerPort(int family, char *hostName, unsigned short portNumber, + char *unixSocketName, int *fdP) + { SockAddr saddr; int fd, err; *************** *** 346,351 **** --- 548,555 ---- return STATUS_OK; } + #endif + /* * 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; --- 595,614 ---- 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; *************** *** 784,786 **** --- 1000,1004 ---- /* in non-error case, copy.c will have emitted the terminator line */ DoingCopyOut = false; } + + 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 03:06:18 2002 *************** *** 0 **** --- 1,325 ---- + #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 + * + * @args (IN) sa : SockAddr union + * @args (OUT) dst : buffer for address string + * @args (IN) cnt : sizeof dst + * @args (IN) v4conv: non-zero: if address is IPv4 mapped IPv6 address then + * convert to IPv4 address. + * zero: - + * @return point 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 sa is wheter (AF_INET or AF_INET&) or not + * + * @args (IN) sa : SockAddr union + * @return : 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) + { + //fprintf(stderr, "Called! rangeSockAddr\n"); + 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) + { + //fprintf(stderr, "Called! rangeSockAddrAF_INET %x %x %x\n", + // addr->in.sin_addr.s_addr, netaddr->in.sin_addr.s_addr, + // netmask->in.sin_addr.s_addr); + 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; + /** DEBUG YY + { + char addr_str[INET6_ADDRSTRLEN]; + char netaddr_str[INET6_ADDRSTRLEN]; + char netmask_str[INET6_ADDRSTRLEN]; + SockAddr_ntop(addr, addr_str, INET6_ADDRSTRLEN, 1); + SockAddr_ntop(netaddr, netaddr_str, INET6_ADDRSTRLEN, 1); + SockAddr_ntop(netmask, netmask_str, INET6_ADDRSTRLEN, 1); + + fprintf(stderr, "Called! rangeSockAddrAF_INET6 %s %s %s\n", + addr_str, netaddr_str, netmask_str); + } + **/ + + 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]; + + /**uint8_t* p_addr = src->in6.sin6_addr.s6_addr; **/ + 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]; + /** + ((uint32_t)(p_addr[12])) << 24 | + ((uint32_t)(p_addr[13])) << 16 | + ((uint32_t)(p_addr[14])) << 8 | + ((uint32_t)(p_addr[15])); + **/ + SockAddr_ntop(src, addr_str, INET6_ADDRSTRLEN, 0); + //fprintf(stderr, "convSockAddr6to4 : %s\n", addr_str); + } + + 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 03:06:18 2002 *************** *** 669,678 **** */ if (NetServer) { ! status = StreamServerPort(AF_INET, VirtualHost, (unsigned short) PostPortNumber, UnixSocketDir, &ServerSock_INET); if (status != STATUS_OK) { postmaster_error("cannot create INET stream port"); --- 669,680 ---- */ if (NetServer) { ! status = StreamServerPort(AF_INET6, VirtualHost, (unsigned short) PostPortNumber, UnixSocketDir, &ServerSock_INET); + + if (status != STATUS_OK) { postmaster_error("cannot create INET stream port"); *************** *** 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; --- 2093,2106 ---- /* * 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 03:06:18 2002 *************** *** 16,21 **** --- 16,22 ---- #ifndef PQCOMM_H #define PQCOMM_H + #include #ifdef WIN32 #include *************** *** 47,56 **** --- 48,60 ---- { struct sockaddr sa; struct sockaddr_in in; + struct sockaddr_in6 in6; struct sockaddr_un un; } SockAddr; + + /* Configure the UNIX socket location for the well known port. */ #define UNIXSOCK_PATH(sun,port,defpath) \ 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 03:06:18 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,1048 **** conn->sock = -1; } conn->status = CONNECTION_BAD; ! return 0; } /* * connectDBComplete * --- 1027,1040 ---- conn->sock = -1; } conn->status = CONNECTION_BAD; ! if(addrs != NULL){ ! freeaddrinfo2(hint.ai_family, addrs); ! } return 0; } + /* * connectDBComplete *