Commit c3e9699f authored by Bruce Momjian's avatar Bruce Momjian

Enable IPv6 connections to the server, and add pg_hba.conf IPv6 entries

if the OS supports it.  Code will still compile on non-IPv6-aware
machines (feature added by Bruce).

Nigel Kukard
parent d99e7b5a
...@@ -7169,6 +7169,80 @@ fi ...@@ -7169,6 +7169,80 @@ fi
done done
# This exports HAVE_IPV6 to both C files and Makefiles
echo "$as_me:$LINENO: checking for getaddrinfo" >&5
echo $ECHO_N "checking for getaddrinfo... $ECHO_C" >&6
if test "${ac_cv_func_getaddrinfo+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char getaddrinfo (); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
#ifdef __cplusplus
extern "C"
#endif
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char getaddrinfo ();
char (*f) ();
#ifdef F77_DUMMY_MAIN
# ifdef __cplusplus
extern "C"
# endif
int F77_DUMMY_MAIN() { return 1; }
#endif
int
main ()
{
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_getaddrinfo) || defined (__stub___getaddrinfo)
choke me
#else
f = getaddrinfo;
#endif
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_func_getaddrinfo=yes
else
echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
ac_cv_func_getaddrinfo=no
fi
rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_func_getaddrinfo" >&5
echo "${ECHO_T}$ac_cv_func_getaddrinfo" >&6
if test $ac_cv_func_getaddrinfo = yes; then
HAVE_IPV6="yes"; cat >>confdefs.h <<\_ACEOF
#define HAVE_IPV6 1
_ACEOF
fi
if test "$with_readline" = yes; then if test "$with_readline" = yes; then
for ac_header in readline/readline.h for ac_header in readline/readline.h
...@@ -16427,6 +16501,7 @@ s,@python_moduledir@,$python_moduledir,;t t ...@@ -16427,6 +16501,7 @@ s,@python_moduledir@,$python_moduledir,;t t
s,@python_moduleexecdir@,$python_moduleexecdir,;t t s,@python_moduleexecdir@,$python_moduleexecdir,;t t
s,@python_includespec@,$python_includespec,;t t s,@python_includespec@,$python_includespec,;t t
s,@python_libspec@,$python_libspec,;t t s,@python_libspec@,$python_libspec,;t t
s,@HAVE_IPV6@,$HAVE_IPV6,;t t
s,@LIBOBJS@,$LIBOBJS,;t t s,@LIBOBJS@,$LIBOBJS,;t t
s,@HPUXMATHLIB@,$HPUXMATHLIB,;t t s,@HPUXMATHLIB@,$HPUXMATHLIB,;t t
s,@HAVE_POSIX_SIGNALS@,$HAVE_POSIX_SIGNALS,;t t s,@HAVE_POSIX_SIGNALS@,$HAVE_POSIX_SIGNALS,;t t
......
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
dnl $Header: /cvsroot/pgsql/configure.in,v 1.224 2002/12/30 17:19:49 tgl Exp $ dnl $Header: /cvsroot/pgsql/configure.in,v 1.225 2003/01/06 03:18:25 momjian Exp $
dnl dnl
dnl Developers, please strive to achieve this order: dnl Developers, please strive to achieve this order:
dnl dnl
...@@ -687,6 +687,11 @@ AC_CHECK_HEADERS(netinet/tcp.h, [], [], ...@@ -687,6 +687,11 @@ AC_CHECK_HEADERS(netinet/tcp.h, [], [],
#endif #endif
]) ])
# This exports HAVE_IPV6 to both C files and Makefiles
AC_CHECK_FUNC(getaddrinfo,
[HAVE_IPV6="yes"; AC_DEFINE(HAVE_IPV6, 1, [])], [])
AC_SUBST(HAVE_IPV6)
if test "$with_readline" = yes; then if test "$with_readline" = yes; then
AC_CHECK_HEADERS(readline/readline.h, [], AC_CHECK_HEADERS(readline/readline.h, [],
[AC_CHECK_HEADERS(readline.h, [], [AC_CHECK_HEADERS(readline.h, [],
...@@ -908,7 +913,7 @@ AC_CHECK_FUNCS([strtoull strtouq], [break]) ...@@ -908,7 +913,7 @@ AC_CHECK_FUNCS([strtoull strtouq], [break])
# Check for one of atexit() or on_exit() # Check for one of atexit() or on_exit()
AC_CHECK_FUNCS(atexit, [], AC_CHECK_FUNCS(atexit, [],
[AC_CHECK_FUNCS(on_exit, [], [AC_CHECK_FUNCS(on_exit, [],
[AC_MSG_ERROR([neither atexit() nor on_exit() found])])]) [AC_MSG_ERROR([neither atexit() nor on_exit() found])])])
AC_FUNC_FSEEKO AC_FUNC_FSEEKO
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.42 2002/12/03 21:50:44 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.43 2003/01/06 03:18:26 momjian Exp $
--> -->
<chapter id="client-authentication"> <chapter id="client-authentication">
...@@ -190,7 +190,11 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> < ...@@ -190,7 +190,11 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <
</blockquote> </blockquote>
must be zero for the record to match. (Of course IP addresses must be zero for the record to match. (Of course IP addresses
can be spoofed but this consideration is beyond the scope of can be spoofed but this consideration is beyond the scope of
<productname>PostgreSQL</productname>.) <productname>PostgreSQL</productname>.) If you machine supports
IPv6, the default <filename>pg_hba.conf</> will have an IPv6
entry for <literal>localhost</>. You can add your own IPv6
entries to the file. IPv6 entries are used only for IPv6
connections.
</para> </para>
<para> <para>
......
# -*-makefile-*- # -*-makefile-*-
# $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.158 2003/01/05 13:45:47 petere Exp $ # $Header: /cvsroot/pgsql/src/Makefile.global.in,v 1.159 2003/01/06 03:18:26 momjian Exp $
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# All PostgreSQL makefiles include this file and use the variables it sets, # All PostgreSQL makefiles include this file and use the variables it sets,
...@@ -277,6 +277,7 @@ ifeq ($(enable_rpath), yes) ...@@ -277,6 +277,7 @@ ifeq ($(enable_rpath), yes)
LDFLAGS += $(rpath) LDFLAGS += $(rpath)
endif endif
HAVE_IPV6 = @HAVE_IPV6@
########################################################################## ##########################################################################
# #
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# #
# Copyright (c) 1994, Regents of the University of California # Copyright (c) 1994, Regents of the University of California
# #
# $Header: /cvsroot/pgsql/src/backend/Makefile,v 1.89 2002/12/14 00:24:23 petere Exp $ # $Header: /cvsroot/pgsql/src/backend/Makefile,v 1.90 2003/01/06 03:18:26 momjian Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -132,7 +132,14 @@ ifeq ($(MAKE_DLL), true) ...@@ -132,7 +132,14 @@ ifeq ($(MAKE_DLL), true)
endif endif
endif endif
$(MAKE) -C catalog install-data $(MAKE) -C catalog install-data
ifdef HAVE_IPV6
$(INSTALL_DATA) $(srcdir)/libpq/pg_hba.conf.sample $(DESTDIR)$(datadir)/pg_hba.conf.sample $(INSTALL_DATA) $(srcdir)/libpq/pg_hba.conf.sample $(DESTDIR)$(datadir)/pg_hba.conf.sample
else
grep -v '^host.*::1.*ffff:ffff:ffff:ffff:ffff:ffff' \
$(srcdir)/libpq/pg_hba.conf.sample \
> $(srcdir)/libpq/pg_hba.conf.sample.no_ipv6
$(INSTALL_DATA) $(srcdir)/libpq/pg_hba.conf.sample.no_ipv6 $(DESTDIR)$(datadir)/pg_hba.conf.sample
endif
$(INSTALL_DATA) $(srcdir)/libpq/pg_ident.conf.sample $(DESTDIR)$(datadir)/pg_ident.conf.sample $(INSTALL_DATA) $(srcdir)/libpq/pg_ident.conf.sample $(DESTDIR)$(datadir)/pg_ident.conf.sample
$(INSTALL_DATA) $(srcdir)/utils/misc/postgresql.conf.sample $(DESTDIR)$(datadir)/postgresql.conf.sample $(INSTALL_DATA) $(srcdir)/utils/misc/postgresql.conf.sample $(DESTDIR)$(datadir)/postgresql.conf.sample
...@@ -182,6 +189,9 @@ clean: ...@@ -182,6 +189,9 @@ clean:
rm -f postgres$(X) $(POSTGRES_IMP) \ rm -f postgres$(X) $(POSTGRES_IMP) \
$(top_srcdir)/src/include/parser/parse.h \ $(top_srcdir)/src/include/parser/parse.h \
$(top_builddir)/src/include/utils/fmgroids.h $(top_builddir)/src/include/utils/fmgroids.h
ifndef HAVE_IPV6
rm -f $(srcdir)/libpq/pg_hba.conf.sample.no_ipv6
endif
ifeq ($(PORTNAME), win) ifeq ($(PORTNAME), win)
rm -f postgres.dll postgres.def libpostgres.a rm -f postgres.dll postgres.def libpostgres.a
endif endif
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Makefile for libpq subsystem (backend half of libpq interface) # Makefile for libpq subsystem (backend half of libpq interface)
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.35 2002/12/06 04:37:02 momjian Exp $ # $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.36 2003/01/06 03:18:26 momjian Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -14,8 +14,8 @@ include $(top_builddir)/src/Makefile.global ...@@ -14,8 +14,8 @@ include $(top_builddir)/src/Makefile.global
# be-fsstubs is here for historical reasons, probably belongs elsewhere # 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 \ OBJS = be-fsstubs.o be-secure.o auth.o crypt.o hba.o ip.o md5.o pqcomm.o \
pqformat.o pqsignal.o pqformat.o pqsignal.o
all: SUBSYS.o all: SUBSYS.o
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.94 2002/12/06 04:37:02 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.95 2003/01/06 03:18:26 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -410,12 +410,18 @@ ClientAuthentication(Port *port) ...@@ -410,12 +410,18 @@ ClientAuthentication(Port *port)
*/ */
{ {
const char *hostinfo = "localhost"; const char *hostinfo = "localhost";
#ifdef HAVE_IPV6
char ip_hostinfo[INET6_ADDRSTRLEN];
#else
char ip_hostinfo[INET_ADDRSTRLEN];
#endif
if (isAF_INETx(port->raddr.sa.sa_family) )
hostinfo = SockAddr_ntop(&port->raddr, ip_hostinfo,
sizeof(ip_hostinfo), 1);
if (port->raddr.sa.sa_family == AF_INET)
hostinfo = inet_ntoa(port->raddr.in.sin_addr);
elog(FATAL, elog(FATAL,
"No pg_hba.conf entry for host %s, user %s, database %s", "No pg_hba.conf entry for host %s, user %s, database %s",
hostinfo, port->user, port->database); hostinfo, port->user, port->database);
break; break;
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.92 2002/12/14 18:49:37 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.93 2003/01/06 03:18:26 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -586,8 +586,7 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) ...@@ -586,8 +586,7 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
} }
else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0) else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0)
{ {
struct in_addr file_ip_addr, SockAddr file_ip_addr, mask;
mask;
if (strcmp(token, "hostssl") == 0) if (strcmp(token, "hostssl") == 0)
{ {
...@@ -623,7 +622,8 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) ...@@ -623,7 +622,8 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
if (!line) if (!line)
goto hba_syntax; goto hba_syntax;
token = lfirst(line); token = lfirst(line);
if (!inet_aton(token, &file_ip_addr))
if(SockAddr_pton(&file_ip_addr, token) < 0)
goto hba_syntax; goto hba_syntax;
/* Read the mask field. */ /* Read the mask field. */
...@@ -631,7 +631,11 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) ...@@ -631,7 +631,11 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
if (!line) if (!line)
goto hba_syntax; goto hba_syntax;
token = lfirst(line); token = lfirst(line);
if (!inet_aton(token, &mask))
if(SockAddr_pton(&mask, token) < 0)
goto hba_syntax;
if(file_ip_addr.sa.sa_family != mask.sa.sa_family)
goto hba_syntax; goto hba_syntax;
/* Read the rest of the line. */ /* Read the rest of the line. */
...@@ -643,8 +647,8 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) ...@@ -643,8 +647,8 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
goto hba_syntax; goto hba_syntax;
/* Must meet network restrictions */ /* Must meet network restrictions */
if (port->raddr.sa.sa_family != AF_INET || if (!isAF_INETx(port->raddr.sa.sa_family) ||
((file_ip_addr.s_addr ^ port->raddr.in.sin_addr.s_addr) & mask.s_addr) != 0) !rangeSockAddr(&port->raddr, &file_ip_addr, &mask))
return; return;
} }
else else
......
/*-------------------------------------------------------------------------
*
* ip.c
* Handles IPv6
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.1 2003/01/06 03:18:26 momjian Exp $
*
* This file and the IPV6 implementation were initially provided by
* Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design
* http://www.lbsd.net.
*
*-------------------------------------------------------------------------
*/
#ifndef FRONTEND
#include "postgres.h"
#else
#include "postgres_fe.h"
#endif
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#endif
#include <arpa/inet.h>
#include <sys/file.h>
#include "libpq/libpq.h"
#include "miscadmin.h"
#ifdef FRONTEND
#define elog fprintf
#define LOG stderr
#endif
#if defined(HAVE_UNIX_SOCKETS) && defined(HAVE_IPV6)
static int getaddrinfo_unix(const char *path, const struct addrinfo *hintsp,
struct addrinfo **result);
#endif /* HAVE_UNIX_SOCKETS */
/*
* getaddrinfo2 - get address info for Unix, IPv4 and IPv6 sockets
*/
int
getaddrinfo2(const char *hostname, const char *servname,
#ifdef HAVE_IPV6
const struct addrinfo *hintp, struct addrinfo **result)
#else
int family, SockAddr *result)
#endif
{
#ifdef HAVE_UNIX_SOCKETS
#ifdef HAVE_IPV6
if (hintp != NULL && hintp->ai_family == AF_UNIX)
return getaddrinfo_unix(servname, hintp, result);
#else
if (family == AF_UNIX)
return 0;
#endif
else
{
#endif /* HAVE_UNIX_SOCKETS */
#ifdef HAVE_IPV6
/* NULL has special meaning to getaddrinfo */
return getaddrinfo((!hostname || hostname[0] == '\0') ? NULL : hostname,
servname, hintp, result);
#else
if (hostname[0] == '\0')
result->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, "getaddrinfo2: gethostbyname(%s) failed\n", hostname);
return STATUS_ERROR;
}
memmove((char *) &(result->in.sin_addr), (char *) hp->h_addr,
hp->h_length);
}
result->in.sin_port = htons((unsigned short)atoi(servname));
return 0;
#endif /* HAVE_IPV6 */
#ifdef HAVE_UNIX_SOCKETS
}
#endif /* HAVE_UNIX_SOCKETS */
}
/*
* freeaddrinfo2 - free IPv6 addrinfo structures
*/
#ifdef HAVE_IPV6
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);
}
#endif
#if defined(HAVE_UNIX_SOCKETS) && defined(HAVE_IPV6)
/* -------
* getaddrinfo_unix - get unix socket info using IPv6
*
* Bug: only one addrinfo is set even though hintsp is NULL or
* ai_socktype is 0
* AI_CANNONNAME does not support.
* -------
*/
static int
getaddrinfo_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))
{
elog(LOG, "hints.ai_family is invalied getaddrinfo_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 && HAVE_IPV6 */
/* ----------
* 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:
#ifdef HAVE_IPV6
inet_ntop(AF_INET, &sa->in.sin_addr, dst, cnt);
#else
StrNCpy(dst, inet_ntoa(sa->in.sin_addr), cnt);
#endif
break;
#ifdef HAVE_IPV6
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;
#endif
default:
dst[0] = '\0';
break;
}
return dst;
}
/*
* SockAddr_pton - IPv6 pton
*/
int
SockAddr_pton(SockAddr *sa, const char *src)
{
int family = AF_INET;
#ifdef HAVE_IPV6
const char *ch;
for (ch = src; *ch != '\0'; ch++)
{
if (*ch == ':')
{
family = AF_INET6;
break;
}
}
#endif
sa->sa.sa_family = family;
switch (family)
{
case AF_INET:
#ifdef HAVE_IPV6
return inet_pton(AF_INET, src, &sa->in.sin_addr);
#else
return inet_aton(src, &sa->in.sin_addr);
#endif
#ifdef HAVE_IPV6
case AF_INET6:
return inet_pton(AF_INET6, src, &sa->in6.sin6_addr);
break;
#endif
default:
return -1;
}
}
/*
* isAF_INETx - check to see if sa is AF_INET or AF_INET6
*/
int
isAF_INETx(const int family)
{
if (family == AF_INET
#ifdef HAVE_IPV6
|| family == AF_INET6
#endif
)
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);
#ifdef HAVE_IPV6
else if (addr->sa.sa_family == AF_INET6)
return rangeSockAddrAF_INET6(addr, netaddr, netmask);
#endif
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;
}
#ifdef HAVE_IPV6
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);
}
#endif
...@@ -44,5 +44,6 @@ ...@@ -44,5 +44,6 @@
# TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD
local all all trust local all all trust
host all all 127.0.0.1 255.255.255.255 trust host all all 127.0.0.1 255.255.255.255 trust
host all all ::1 ffff:ffff:ffff:ffff:ffff:ffff trust
This diff is collapsed.
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.301 2002/12/06 04:37:02 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.302 2003/01/06 03:18:27 momjian Exp $
* *
* NOTES * NOTES
* *
...@@ -669,15 +669,30 @@ PostmasterMain(int argc, char *argv[]) ...@@ -669,15 +669,30 @@ PostmasterMain(int argc, char *argv[])
*/ */
if (NetServer) if (NetServer)
{ {
status = StreamServerPort(AF_INET, VirtualHost, #ifdef HAVE_IPV6
/* Try INET6 first. May fail if kernel doesn't support IP6 */
status = StreamServerPort(AF_INET6, VirtualHost,
(unsigned short) PostPortNumber, (unsigned short) PostPortNumber,
UnixSocketDir, UnixSocketDir,
&ServerSock_INET); &ServerSock_INET);
if (status != STATUS_OK) if (status != STATUS_OK)
{ {
postmaster_error("cannot create INET stream port"); elog(LOG, "IPv6 support disabled --- perhaps the kernel does not support IPv6");
ExitPostmaster(1); #endif
status = StreamServerPort(AF_INET, VirtualHost,
(unsigned short) PostPortNumber,
UnixSocketDir,
&ServerSock_INET);
if (status != STATUS_OK)
{
postmaster_error("cannot create INET stream port");
ExitPostmaster(1);
}
#ifdef HAVE_IPV6
else
elog(LOG, "IPv4 socket created");
} }
#endif
} }
#ifdef HAVE_UNIX_SOCKETS #ifdef HAVE_UNIX_SOCKETS
...@@ -2091,13 +2106,19 @@ DoBackend(Port *port) ...@@ -2091,13 +2106,19 @@ DoBackend(Port *port)
/* /*
* Get the remote host name and port for logging and status display. * Get the remote host name and port for logging and status display.
*/ */
if (port->raddr.sa.sa_family == AF_INET) if (isAF_INETx(port->raddr.sa.sa_family))
{ {
unsigned short remote_port; unsigned short remote_port;
char *host_addr; char *host_addr;
#ifdef HAVE_IPV6
char ip_hostinfo[INET6_ADDRSTRLEN];
#else
char ip_hostinfo[INET_ADDRSTRLEN];
#endif
remote_port = ntohs(port->raddr.in.sin_port); remote_port = ntohs(port->raddr.in.sin_port);
host_addr = inet_ntoa(port->raddr.in.sin_addr); host_addr = SockAddr_ntop(&port->raddr, ip_hostinfo,
sizeof(ip_hostinfo), 1);
remote_host = NULL; remote_host = NULL;
......
#ifndef IP_H
#define IP_H
#include <sys/socket.h>
#include <netdb.h>
#include "libpq/pqcomm.h"
#ifdef HAVE_IPV6
void freeaddrinfo2(int hint_ai_family, struct addrinfo *ai);
int getaddrinfo2(const char *hostname, const char *servname,
const struct addrinfo *hintp, struct addrinfo **result);
#else
int getaddrinfo2(const char *hostname, const char *servname,
int family, SockAddr *result);
#endif
char *SockAddr_ntop(const SockAddr *sa, char *dst, size_t cnt, int v4conv);
int SockAddr_pton(SockAddr *sa, const char *src);
int isAF_INETx(const 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);
#ifdef HAVE_IPV6
int rangeSockAddrAF_INET6(const SockAddr *addr, const SockAddr *netaddr,
const SockAddr *netmask);
void convSockAddr6to4(const SockAddr *src, SockAddr *dst);
#endif
#endif /* IP_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: libpq.h,v 1.54 2002/12/06 04:37:05 momjian Exp $ * $Id: libpq.h,v 1.55 2003/01/06 03:18:27 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "lib/stringinfo.h" #include "lib/stringinfo.h"
#include "libpq/libpq-be.h" #include "libpq/libpq-be.h"
#include "libpq/ip.h"
/* ---------------- /* ----------------
* PQArgBlock * PQArgBlock
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pqcomm.h,v 1.72 2002/12/06 04:37:05 momjian Exp $ * $Id: pqcomm.h,v 1.73 2003/01/06 03:18:27 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -47,6 +47,9 @@ typedef union SockAddr ...@@ -47,6 +47,9 @@ typedef union SockAddr
{ {
struct sockaddr sa; struct sockaddr sa;
struct sockaddr_in in; struct sockaddr_in in;
#ifdef HAVE_IPV6
struct sockaddr_in6 in6;
#endif
struct sockaddr_un un; struct sockaddr_un un;
} SockAddr; } SockAddr;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* or in pg_config.h afterwards. Of course, if you edit pg_config.h, then your * or in pg_config.h afterwards. Of course, if you edit pg_config.h, then your
* changes will be overwritten the next time you run configure. * changes will be overwritten the next time you run configure.
* *
* $Id: pg_config.h.in,v 1.34 2002/11/10 00:38:21 momjian Exp $ * $Id: pg_config.h.in,v 1.35 2003/01/06 03:18:27 momjian Exp $
*/ */
#ifndef PG_CONFIG_H #ifndef PG_CONFIG_H
...@@ -368,6 +368,9 @@ ...@@ -368,6 +368,9 @@
/* Set to 1 if you have <sys/shm.h> */ /* Set to 1 if you have <sys/shm.h> */
#undef HAVE_SYS_SHM_H #undef HAVE_SYS_SHM_H
/* Set to 1 if you have <netinet/ip6.h> for IPv6 */
#undef HAVE_IPV6
/* Set to 1 if you have <kernel/OS.h> */ /* Set to 1 if you have <kernel/OS.h> */
#undef HAVE_KERNEL_OS_H #undef HAVE_KERNEL_OS_H
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# #
# Copyright (c) 1994, Regents of the University of California # Copyright (c) 1994, Regents of the University of California
# #
# $Header: /cvsroot/pgsql/src/interfaces/libpq/Makefile,v 1.70 2002/12/13 22:17:57 momjian Exp $ # $Header: /cvsroot/pgsql/src/interfaces/libpq/Makefile,v 1.71 2003/01/06 03:18:27 momjian Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -21,8 +21,8 @@ SO_MINOR_VERSION= 1 ...@@ -21,8 +21,8 @@ SO_MINOR_VERSION= 1
override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) -DFRONTEND -DSYSCONFDIR='"$(sysconfdir)"' override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) -DFRONTEND -DSYSCONFDIR='"$(sysconfdir)"'
OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \ 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 \ pqexpbuffer.o dllist.o pqsignal.o fe-secure.o wchar.o encnames.o ip.o \
wchar.o encnames.o \ md5.o \
$(filter inet_aton.o snprintf.o strerror.o, $(LIBOBJS)) $(filter inet_aton.o snprintf.o strerror.o, $(LIBOBJS))
...@@ -45,6 +45,9 @@ dllist.c: $(backend_src)/lib/dllist.c ...@@ -45,6 +45,9 @@ dllist.c: $(backend_src)/lib/dllist.c
md5.c: $(backend_src)/libpq/md5.c md5.c: $(backend_src)/libpq/md5.c
rm -f $@ && $(LN_S) $< . rm -f $@ && $(LN_S) $< .
ip.c: $(backend_src)/libpq/ip.c
rm -f $@ && $(LN_S) $< .
# We use several backend modules verbatim, but since we need to # We use several backend modules verbatim, but since we need to
# compile with appropriate options to build a shared lib, we can't # compile with appropriate options to build a shared lib, we can't
# necessarily use the same object files as the backend uses. Instead, # necessarily use the same object files as the backend uses. Instead,
...@@ -70,5 +73,5 @@ uninstall: uninstall-lib ...@@ -70,5 +73,5 @@ uninstall: uninstall-lib
rm -f $(DESTDIR)$(includedir)/libpq-fe.h $(DESTDIR)$(includedir_internal)/libpq-int.h $(includedir_internal)/pqexpbuffer.h rm -f $(DESTDIR)$(includedir)/libpq-fe.h $(DESTDIR)$(includedir_internal)/libpq-int.h $(includedir_internal)/pqexpbuffer.h
clean distclean maintainer-clean: clean-lib clean distclean maintainer-clean: clean-lib
rm -f $(OBJS) dllist.c md5.c wchar.c encnames.c rm -f $(OBJS) dllist.c md5.c v6util.c wchar.c encnames.c
rm -f $(OBJS) inet_aton.c snprintf.c strerror.c rm -f $(OBJS) inet_aton.c snprintf.c strerror.c
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.216 2002/12/19 19:30:24 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.217 2003/01/06 03:18:27 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#include "libpq/ip.h"
#ifndef HAVE_STRDUP #ifndef HAVE_STRDUP
#include "strdup.h" #include "strdup.h"
#endif #endif
...@@ -48,6 +51,14 @@ ...@@ -48,6 +51,14 @@
#include "mb/pg_wchar.h" #include "mb/pg_wchar.h"
#ifdef HAVE_IPV6
#define FREEADDRINFO2(family, addrs) freeaddrinfo2((family), (addrs))
#else
/* do nothing */
#define FREEADDRINFO2(family, addrs) do {} while (0)
#endif
#ifdef WIN32 #ifdef WIN32
static int static int
inet_aton(const char *cp, struct in_addr * inp) inet_aton(const char *cp, struct in_addr * inp)
...@@ -784,19 +795,32 @@ connectFailureMessage(PGconn *conn, int errorno) ...@@ -784,19 +795,32 @@ connectFailureMessage(PGconn *conn, int errorno)
static int static int
connectDBStart(PGconn *conn) connectDBStart(PGconn *conn)
{ {
int portno, int portnum;
family; int sockfd;
char portstr[64];
#ifdef USE_SSL #ifdef USE_SSL
StartupPacket np; /* Used to negotiate SSL connection */ StartupPacket np; /* Used to negotiate SSL connection */
char SSLok; char SSLok;
#endif #endif
#ifdef HAVE_IPV6
struct addrinfo *addrs = NULL;
struct addrinfo *addr_cur = NULL;
struct addrinfo hint;
const char *node = NULL;
const char *unix_node = "unix";
int ret;
/* Initialize hint structure */
MemSet(&hint, 0, sizeof(hint));
hint.ai_socktype = SOCK_STREAM;
#else
int family = -1;
#endif
if (!conn) if (!conn)
return 0; return 0;
#ifdef NOT_USED #ifdef NOT_USED
/* /*
* parse dbName to get all additional info in it, if any * parse dbName to get all additional info in it, if any
*/ */
...@@ -815,10 +839,26 @@ connectDBStart(PGconn *conn) ...@@ -815,10 +839,26 @@ connectDBStart(PGconn *conn)
MemSet((char *) &conn->raddr, 0, sizeof(conn->raddr)); MemSet((char *) &conn->raddr, 0, sizeof(conn->raddr));
/*
* This code is confusing because IPv6 creates a hint structure
* that is passed to getaddrinfo2(), which returns a list of address
* structures that are looped through, while IPv4 creates an address
* structure directly.
*/
if (conn->pgport != NULL && conn->pgport[0] != '\0')
portnum = atoi(conn->pgport);
else
portnum = DEF_PGPORT;
snprintf(portstr, sizeof(portstr), "%d", portnum);
if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0') if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
{ {
#ifdef HAVE_IPV6
node = conn->pghostaddr;
hint.ai_family = AF_UNSPEC;
#else
/* Using pghostaddr avoids a hostname lookup */ /* Using pghostaddr avoids a hostname lookup */
/* Note that this supports IPv4 only */
struct in_addr addr; struct in_addr addr;
if (!inet_aton(conn->pghostaddr, &addr)) if (!inet_aton(conn->pghostaddr, &addr))
...@@ -833,120 +873,158 @@ connectDBStart(PGconn *conn) ...@@ -833,120 +873,158 @@ connectDBStart(PGconn *conn)
memmove((char *) &(conn->raddr.in.sin_addr), memmove((char *) &(conn->raddr.in.sin_addr),
(char *) &addr, sizeof(addr)); (char *) &addr, sizeof(addr));
#endif
} }
else if (conn->pghost != NULL && conn->pghost[0] != '\0') else if (conn->pghost != NULL && conn->pghost[0] != '\0')
{ {
#ifdef HAVE_IPV6
node = conn->pghost;
hint.ai_family = AF_UNSPEC;
#else
/* Using pghost, so we have to look-up the hostname */ /* Using pghost, so we have to look-up the hostname */
struct hostent *hp; if (getaddrinfo2(conn->pghost, portstr, family, &conn->raddr) != 0)
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; goto connect_errReturn;
}
family = AF_INET;
memmove((char *) &(conn->raddr.in.sin_addr), family = AF_INET;
(char *) hp->h_addr, #endif
hp->h_length);
} }
#ifdef HAVE_UNIX_SOCKETS
else else
{ {
#ifdef HAVE_IPV6
node = unix_node;
hint.ai_family = AF_UNIX;
#else
/* pghostaddr and pghost are NULL, so use Unix domain socket */ /* pghostaddr and pghost are NULL, so use Unix domain socket */
family = AF_UNIX; family = AF_UNIX;
#endif
} }
#endif /* HAVE_UNIX_SOCKETS */
/* Set family */ #ifndef HAVE_IPV6
conn->raddr.sa.sa_family = family; conn->raddr.sa.sa_family = family;
#endif
/* Set port number */ #ifdef HAVE_IPV6
if (conn->pgport != NULL && conn->pgport[0] != '\0') if (hint.ai_family == AF_UNSPEC)
portno = atoi(conn->pgport); {/* do nothing*/}
else #else
portno = DEF_PGPORT;
if (family == AF_INET) if (family == AF_INET)
{ {
conn->raddr.in.sin_port = htons((unsigned short) (portno)); conn->raddr.in.sin_port = htons((unsigned short) (portnum));
conn->raddr_len = sizeof(struct sockaddr_in); conn->raddr_len = sizeof(struct sockaddr_in);
} }
#endif
#ifdef HAVE_UNIX_SOCKETS #ifdef HAVE_UNIX_SOCKETS
else else
{ {
UNIXSOCK_PATH(conn->raddr.un, portno, conn->pgunixsocket); UNIXSOCK_PATH(conn->raddr.un, portnum, conn->pgunixsocket);
conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un); conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un);
StrNCpy(portstr, conn->raddr.un.sun_path, sizeof(portstr));
#ifdef USE_SSL #ifdef USE_SSL
/* Don't bother requesting SSL over a Unix socket */ /* Don't bother requesting SSL over a Unix socket */
conn->allow_ssl_try = false; conn->allow_ssl_try = false;
conn->require_ssl = false; conn->require_ssl = false;
#endif #endif
} }
#endif #endif /* HAVE_UNIX_SOCKETS */
/* Open a socket */ #if HAVE_IPV6
if ((conn->sock = socket(family, SOCK_STREAM, 0)) < 0) ret = getaddrinfo2(node, portstr, &hint, &addrs);
if (ret || addrs == NULL)
{ {
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create socket: %s\n"), libpq_gettext("failed to getaddrinfo(): %s\n"),
SOCK_STRERROR(SOCK_ERRNO)); gai_strerror(ret));
goto connect_errReturn; goto connect_errReturn;
} }
addr_cur = addrs;
#endif
/* do
* 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)) #ifdef HAVE_IPV6
goto connect_errReturn; sockfd = socket(addr_cur->ai_family, SOCK_STREAM,
} addr_cur->ai_protocol);
#else
sockfd = socket(family, SOCK_STREAM, 0);
#endif
if (sockfd < 0)
continue;
conn->sock = sockfd;
#ifdef HAVE_IPV6
if (isAF_INETx(addr_cur->ai_family))
#else
if (isAF_INETx(family))
#endif
{
if (!connectNoDelay(conn))
goto connect_errReturn;
}
#if !defined(USE_SSL) #if !defined(USE_SSL)
if (connectMakeNonblocking(conn) == 0) if (connectMakeNonblocking(conn) == 0)
goto connect_errReturn; goto connect_errReturn;
#endif #endif
/* ---------- /* ----------
* Start / make connection. We are hopefully in non-blocking mode * Start / make connection. We are hopefully in non-blocking mode
* now, but it is possible that: * now, but it is possible that:
* 1. Older systems will still block on connect, despite the * 1. Older systems will still block on connect, despite the
* non-blocking flag. (Anyone know if this is true?) * non-blocking flag. (Anyone know if this is true?)
* 2. We are using SSL. * 2. We are using SSL.
* Thus, we have to make arrangements for all eventualities. * Thus, we have to make arrangements for all eventualities.
* ---------- * ----------
*/ */
retry1: retry1:
if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0) #ifdef HAVE_IPV6
{ if (connect(sockfd, addr_cur->ai_addr, addr_cur->ai_addrlen) == 0)
if (SOCK_ERRNO == EINTR) #else
/* Interrupted system call - we'll just try again */ if (connect(sockfd, &conn->raddr.sa, conn->raddr_len) == 0)
goto retry1; #endif
if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || SOCK_ERRNO == 0)
{ {
/* /* We're connected already */
* This is fine - we're in non-blocking mode, and the conn->status = CONNECTION_MADE;
* connection is in progress. break;
*/
conn->status = CONNECTION_STARTED;
} }
else else
{ {
/* Something's gone wrong */ if (SOCK_ERRNO == EINTR)
connectFailureMessage(conn, SOCK_ERRNO); /* Interrupted system call - we'll just try again */
goto connect_errReturn; 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);
#ifdef HAVE_IPV6
} while ((addr_cur = addr_cur->ai_next) != NULL);
if (addr_cur == NULL)
#else
} while (0);
if (sockfd < 0)
#endif
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create socket: %s\n"),
SOCK_STRERROR(SOCK_ERRNO));
goto connect_errReturn;
} }
else else
{ {
/* We're connected already */ #ifdef HAVE_IPV6
conn->status = CONNECTION_MADE; 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;
#endif
} }
#ifdef USE_SSL #ifdef USE_SSL
...@@ -1014,7 +1092,6 @@ retry2: ...@@ -1014,7 +1092,6 @@ retry2:
} }
#endif #endif
/* /*
* This makes the connection non-blocking, for all those cases which * This makes the connection non-blocking, for all those cases which
* forced us not to do it above. * forced us not to do it above.
...@@ -1038,7 +1115,10 @@ connect_errReturn: ...@@ -1038,7 +1115,10 @@ connect_errReturn:
conn->sock = -1; conn->sock = -1;
} }
conn->status = CONNECTION_BAD; conn->status = CONNECTION_BAD;
#ifdef HAVE_IPV6
if (addrs != NULL)
FREEADDRINFO2(hint.ai_family, addrs);
#endif
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment