diff --git a/src/backend/libpq/ip.c b/src/backend/libpq/ip.c index 83a5145c36..948fb57614 100644 --- a/src/backend/libpq/ip.c +++ b/src/backend/libpq/ip.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.8 2003/06/08 17:42:59 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.9 2003/06/09 17:59:19 tgl Exp $ * * This file and the IPV6 implementation were initially provided by * Nigel Kukard , Linux Based Systems Design @@ -73,26 +73,34 @@ getaddrinfo2(const char *hostname, const char *servname, /* * freeaddrinfo2 - free addrinfo structures for IPv4, IPv6, or Unix + * + * Note: the ai_family field of the original hint structure must be passed + * so that we can tell whether the addrinfo struct was built by the system's + * getaddrinfo() routine or our own getaddrinfo_unix() routine. Some versions + * of getaddrinfo() might be willing to return AF_UNIX addresses, so it's + * not safe to look at ai_family in the addrinfo itself. */ void -freeaddrinfo2(struct addrinfo *ai) +freeaddrinfo2(int hint_ai_family, struct addrinfo *ai) { - if (ai != NULL) - { #ifdef HAVE_UNIX_SOCKETS - if (ai->ai_family == AF_UNIX) + if (hint_ai_family == AF_UNIX) + { + /* struct was built by getaddrinfo_unix (see getaddrinfo2) */ + while (ai != NULL) { - while (ai != NULL) - { - struct addrinfo *p = ai; + struct addrinfo *p = ai; - ai = ai->ai_next; - free(p->ai_addr); - free(p); - } + ai = ai->ai_next; + free(p->ai_addr); + free(p); } - else + } + else #endif /* HAVE_UNIX_SOCKETS */ + { + /* struct was built by getaddrinfo() */ + if (ai != NULL) freeaddrinfo(ai); } } @@ -115,6 +123,8 @@ getaddrinfo_unix(const char *path, const struct addrinfo *hintsp, struct addrinfo *aip; struct sockaddr_un *unp; + *result = NULL; + MemSet(&hints, 0, sizeof(hints)); if (hintsp == NULL) @@ -138,6 +148,13 @@ getaddrinfo_unix(const char *path, const struct addrinfo *hintsp, if (aip == NULL) return EAI_MEMORY; + unp = calloc(1, sizeof(struct sockaddr_un)); + if (unp == NULL) + { + free(aip); + return EAI_MEMORY; + } + aip->ai_family = AF_UNIX; aip->ai_socktype = hints.ai_socktype; aip->ai_protocol = hints.ai_protocol; @@ -145,10 +162,6 @@ getaddrinfo_unix(const char *path, const struct addrinfo *hintsp, 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); diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 39689e4077..ea4ff64468 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -30,7 +30,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.155 2003/06/08 17:43:00 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.156 2003/06/09 17:59:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -242,7 +242,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, { elog(LOG, "server socket failure: getaddrinfo2(): %s", gai_strerror(ret)); - freeaddrinfo2(addrs); + freeaddrinfo2(hint.ai_family, addrs); return STATUS_ERROR; } @@ -250,7 +250,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, { elog(LOG, "server socket failure: socket(): %s", strerror(errno)); - freeaddrinfo2(addrs); + freeaddrinfo2(hint.ai_family, addrs); return STATUS_ERROR; } @@ -261,7 +261,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, { elog(LOG, "server socket failure: setsockopt(SO_REUSEADDR): %s", strerror(errno)); - freeaddrinfo2(addrs); + freeaddrinfo2(hint.ai_family, addrs); return STATUS_ERROR; } } @@ -278,7 +278,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, sock_path); else elog(LOG, "\tIf not, wait a few seconds and retry."); - freeaddrinfo2(addrs); + freeaddrinfo2(hint.ai_family, addrs); return STATUS_ERROR; } @@ -287,7 +287,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, { if (Setup_AF_UNIX() != STATUS_OK) { - freeaddrinfo2(addrs); + freeaddrinfo2(hint.ai_family, addrs); return STATUS_ERROR; } } @@ -307,14 +307,13 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, { elog(LOG, "server socket failure: listen(): %s", strerror(errno)); - freeaddrinfo2(addrs); + freeaddrinfo2(hint.ai_family, addrs); return STATUS_ERROR; } *fdP = fd; - freeaddrinfo2(addrs); + freeaddrinfo2(hint.ai_family, addrs); return STATUS_OK; - } diff --git a/src/include/libpq/ip.h b/src/include/libpq/ip.h index 78f5237614..7e910d5cbb 100644 --- a/src/include/libpq/ip.h +++ b/src/include/libpq/ip.h @@ -5,7 +5,7 @@ * * Copyright (c) 2003, PostgreSQL Global Development Group * - * $Id: ip.h,v 1.4 2003/06/08 17:43:00 tgl Exp $ + * $Id: ip.h,v 1.5 2003/06/09 17:59:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,7 +19,7 @@ extern int getaddrinfo2(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result); -extern void freeaddrinfo2(struct addrinfo *ai); +extern void freeaddrinfo2(int hint_ai_family, struct addrinfo *ai); extern char *SockAddr_ntop(const SockAddr *sa, char *dst, size_t cnt, int v4conv); diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 6eefd9bfcb..64e39c7baf 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.242 2003/06/08 17:43:00 tgl Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.243 2003/06/09 17:59:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -848,7 +848,7 @@ connectDBStart(PGconn *conn) printfPQExpBuffer(&conn->errorMessage, libpq_gettext("getaddrinfo() failed: %s\n"), gai_strerror(ret)); - freeaddrinfo2(addrs); + freeaddrinfo2(hint.ai_family, addrs); goto connect_errReturn; } @@ -857,6 +857,7 @@ connectDBStart(PGconn *conn) */ conn->addrlist = addrs; conn->addr_cur = addrs; + conn->addrlist_family = hint.ai_family; conn->pversion = PG_PROTOCOL(3,0); conn->status = CONNECTION_NEEDED; @@ -1686,7 +1687,7 @@ retry_ssl_read: } /* We can release the address list now. */ - freeaddrinfo2(conn->addrlist); + freeaddrinfo2(conn->addrlist_family, conn->addrlist); conn->addrlist = NULL; conn->addr_cur = NULL; @@ -1858,7 +1859,7 @@ freePGconn(PGconn *conn) /* Note that conn->Pfdebug is not ours to close or free */ if (conn->notifyList) DLFreeList(conn->notifyList); - freeaddrinfo2(conn->addrlist); + freeaddrinfo2(conn->addrlist_family, conn->addrlist); if (conn->lobjfuncs) free(conn->lobjfuncs); if (conn->inBuffer) diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index eafd4c3093..f710f58b8e 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: libpq-int.h,v 1.71 2003/06/08 17:43:00 tgl Exp $ + * $Id: libpq-int.h,v 1.72 2003/06/09 17:59:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -270,6 +270,7 @@ struct pg_conn /* Transient state needed while establishing connection */ struct addrinfo *addrlist; /* list of possible backend addresses */ struct addrinfo *addr_cur; /* the one currently being tried */ + int addrlist_family; /* needed to know how to free addrlist */ PGSetenvStatusType setenv_state; /* for 2.0 protocol only */ const PQEnvironmentOption *next_eo;