Second try at IPv4-to-v6 mapping code; avoid assuming that the struct

returned by getaddrinfo_all will have enough room for an IPv6 address.
This commit is contained in:
Tom Lane 2003-09-05 23:07:21 +00:00
parent 3c9bb8886d
commit 92aa462247
3 changed files with 48 additions and 51 deletions

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.113 2003/09/05 20:31:35 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.114 2003/09/05 23:07:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -550,12 +550,12 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
char *token; char *token;
char *db; char *db;
char *user; char *user;
struct addrinfo *file_ip_addr = NULL, struct addrinfo *gai_result;
*file_ip_mask = NULL;
struct addrinfo hints; struct addrinfo hints;
struct sockaddr_storage *mask;
char *cidr_slash;
int ret; int ret;
struct sockaddr_storage addr;
struct sockaddr_storage mask;
char *cidr_slash;
Assert(line != NIL); Assert(line != NIL);
line_number = lfirsti(line); line_number = lfirsti(line);
@ -648,6 +648,7 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
if (cidr_slash) if (cidr_slash)
*cidr_slash = '\0'; *cidr_slash = '\0';
/* Get the IP address either way */
hints.ai_flags = AI_NUMERICHOST; hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = PF_UNSPEC; hints.ai_family = PF_UNSPEC;
hints.ai_socktype = 0; hints.ai_socktype = 0;
@ -657,9 +658,8 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
hints.ai_addr = NULL; hints.ai_addr = NULL;
hints.ai_next = NULL; hints.ai_next = NULL;
/* Get the IP address either way */ ret = getaddrinfo_all(token, NULL, &hints, &gai_result);
ret = getaddrinfo_all(token, NULL, &hints, &file_ip_addr); if (ret || !gai_result)
if (ret || !file_ip_addr)
{ {
ereport(LOG, ereport(LOG,
(errcode(ERRCODE_CONFIG_FILE_ERROR), (errcode(ERRCODE_CONFIG_FILE_ERROR),
@ -667,17 +667,21 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
token, gai_strerror(ret)))); token, gai_strerror(ret))));
if (cidr_slash) if (cidr_slash)
*cidr_slash = '/'; *cidr_slash = '/';
if (gai_result)
freeaddrinfo_all(hints.ai_family, gai_result);
goto hba_syntax; goto hba_syntax;
} }
if (cidr_slash) if (cidr_slash)
*cidr_slash = '/'; *cidr_slash = '/';
memcpy(&addr, gai_result->ai_addr, gai_result->ai_addrlen);
freeaddrinfo_all(hints.ai_family, gai_result);
/* Get the netmask */ /* Get the netmask */
if (cidr_slash) if (cidr_slash)
{ {
if (SockAddr_cidr_mask(&mask, cidr_slash + 1, if (SockAddr_cidr_mask(&mask, cidr_slash + 1, addr.ss_family) < 0)
file_ip_addr->ai_family) < 0)
goto hba_syntax; goto hba_syntax;
} }
else else
@ -688,17 +692,22 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
goto hba_syntax; goto hba_syntax;
token = lfirst(line); token = lfirst(line);
ret = getaddrinfo_all(token, NULL, &hints, &file_ip_mask); ret = getaddrinfo_all(token, NULL, &hints, &gai_result);
if (ret || !file_ip_mask) if (ret || !gai_result)
goto hba_syntax; {
if (gai_result)
mask = (struct sockaddr_storage *) file_ip_mask->ai_addr; freeaddrinfo_all(hints.ai_family, gai_result);
if (file_ip_addr->ai_family != mask->ss_family)
goto hba_syntax; goto hba_syntax;
} }
if (file_ip_addr->ai_family != port->raddr.addr.ss_family) memcpy(&mask, gai_result->ai_addr, gai_result->ai_addrlen);
freeaddrinfo_all(hints.ai_family, gai_result);
if (addr.ss_family != mask.ss_family)
goto hba_syntax;
}
if (addr.ss_family != port->raddr.addr.ss_family)
{ {
/* /*
* Wrong address family. We allow only one case: if the * Wrong address family. We allow only one case: if the
@ -706,20 +715,24 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
* address to IPv6 and try to match that way. * address to IPv6 and try to match that way.
*/ */
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (file_ip_addr->ai_family == AF_INET && if (addr.ss_family == AF_INET &&
port->raddr.addr.ss_family == AF_INET6) port->raddr.addr.ss_family == AF_INET6)
{ {
promote_v4_to_v6_addr((struct sockaddr_storage *) file_ip_addr->ai_addr); promote_v4_to_v6_addr(&addr);
promote_v4_to_v6_mask(mask); promote_v4_to_v6_mask(&mask);
} }
else else
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
{ {
freeaddrinfo_all(hints.ai_family, file_ip_addr); /* Line doesn't match client port, so ignore it. */
return; return;
} }
} }
/* Ignore line if client port is not in the matching addr range. */
if (!rangeSockAddr(&port->raddr.addr, &addr, &mask))
return;
/* Read the rest of the line. */ /* Read the rest of the line. */
line = lnext(line); line = lnext(line);
if (!line) if (!line)
@ -727,16 +740,6 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
parse_hba_auth(line, &port->auth_method, &port->auth_arg, error_p); parse_hba_auth(line, &port->auth_method, &port->auth_arg, error_p);
if (*error_p) if (*error_p)
goto hba_syntax; goto hba_syntax;
/* Must meet network restrictions */
if (!rangeSockAddr(&port->raddr.addr,
(struct sockaddr_storage *) file_ip_addr->ai_addr,
mask))
goto hba_freeaddr;
freeaddrinfo_all(hints.ai_family, file_ip_addr);
if (file_ip_mask)
freeaddrinfo_all(hints.ai_family, file_ip_mask);
} }
else else
goto hba_syntax; goto hba_syntax;
@ -763,12 +766,6 @@ hba_syntax:
line_number))); line_number)));
*error_p = true; *error_p = true;
hba_freeaddr:
if (file_ip_addr)
freeaddrinfo_all(hints.ai_family, file_ip_addr);
if (file_ip_mask)
freeaddrinfo_all(hints.ai_family, file_ip_mask);
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.20 2003/09/05 20:31:36 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.21 2003/09/05 23:07:21 tgl Exp $
* *
* This file and the IPV6 implementation were initially provided by * This file and the IPV6 implementation were initially provided by
* Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design * Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design
@ -332,15 +332,15 @@ rangeSockAddrAF_INET6(const struct sockaddr_in6 * addr,
* SockAddr_cidr_mask - make a network mask of the appropriate family * SockAddr_cidr_mask - make a network mask of the appropriate family
* and required number of significant bits * and required number of significant bits
* *
* Note: Returns a static pointer for the mask, so it's not thread safe, * The resulting mask is placed in *mask, which had better be big enough.
* and a second call will overwrite the data. *
* Return value is 0 if okay, -1 if not.
*/ */
int int
SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family) SockAddr_cidr_mask(struct sockaddr_storage * mask, char *numbits, int family)
{ {
long bits; long bits;
char *endptr; char *endptr;
static struct sockaddr_storage sock;
struct sockaddr_in mask4; struct sockaddr_in mask4;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
@ -359,15 +359,13 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family)
) )
return -1; return -1;
*mask = &sock;
switch (family) switch (family)
{ {
case AF_INET: case AF_INET:
mask4.sin_addr.s_addr = mask4.sin_addr.s_addr =
htonl((0xffffffffUL << (32 - bits)) htonl((0xffffffffUL << (32 - bits))
& 0xffffffffUL); & 0xffffffffUL);
memcpy(&sock, &mask4, sizeof(mask4)); memcpy(mask, &mask4, sizeof(mask4));
break; break;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
case AF_INET6: case AF_INET6:
@ -387,7 +385,7 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family)
} }
bits -= 8; bits -= 8;
} }
memcpy(&sock, &mask6, sizeof(mask6)); memcpy(mask, &mask6, sizeof(mask6));
break; break;
} }
#endif #endif
@ -395,7 +393,7 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family)
return -1; return -1;
} }
sock.ss_family = family; mask->ss_family = family;
return 0; return 0;
} }
@ -406,8 +404,9 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family)
* promote_v4_to_v6_addr --- convert an AF_INET addr to AF_INET6, using * promote_v4_to_v6_addr --- convert an AF_INET addr to AF_INET6, using
* the standard convention for IPv4 addresses mapped into IPv6 world * the standard convention for IPv4 addresses mapped into IPv6 world
* *
* The passed addr is modified in place. Note that we only worry about * The passed addr is modified in place; be sure it is large enough to
* setting the fields that rangeSockAddr will look at. * hold the result! Note that we only worry about setting the fields
* that rangeSockAddr will look at.
*/ */
void void
promote_v4_to_v6_addr(struct sockaddr_storage * addr) promote_v4_to_v6_addr(struct sockaddr_storage * addr)
@ -440,8 +439,9 @@ promote_v4_to_v6_addr(struct sockaddr_storage * addr)
* This must be different from promote_v4_to_v6_addr because we want to * This must be different from promote_v4_to_v6_addr because we want to
* set the high-order bits to 1's not 0's. * set the high-order bits to 1's not 0's.
* *
* The passed addr is modified in place. Note that we only worry about * The passed addr is modified in place; be sure it is large enough to
* setting the fields that rangeSockAddr will look at. * hold the result! Note that we only worry about setting the fields
* that rangeSockAddr will look at.
*/ */
void void
promote_v4_to_v6_mask(struct sockaddr_storage * addr) promote_v4_to_v6_mask(struct sockaddr_storage * addr)

View File

@ -5,7 +5,7 @@
* *
* Copyright (c) 2003, PostgreSQL Global Development Group * Copyright (c) 2003, PostgreSQL Global Development Group
* *
* $Id: ip.h,v 1.11 2003/09/05 20:31:36 tgl Exp $ * $Id: ip.h,v 1.12 2003/09/05 23:07:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -30,7 +30,7 @@ extern int rangeSockAddr(const struct sockaddr_storage * addr,
const struct sockaddr_storage * netaddr, const struct sockaddr_storage * netaddr,
const struct sockaddr_storage * netmask); const struct sockaddr_storage * netmask);
extern int SockAddr_cidr_mask(struct sockaddr_storage ** mask, extern int SockAddr_cidr_mask(struct sockaddr_storage * mask,
char *numbits, int family); char *numbits, int family);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6