mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-28 00:31:51 +02:00
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:
parent
3c9bb8886d
commit
92aa462247
@ -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)
|
||||||
|
{
|
||||||
|
if (gai_result)
|
||||||
|
freeaddrinfo_all(hints.ai_family, gai_result);
|
||||||
goto hba_syntax;
|
goto hba_syntax;
|
||||||
|
}
|
||||||
|
|
||||||
mask = (struct sockaddr_storage *) file_ip_mask->ai_addr;
|
memcpy(&mask, gai_result->ai_addr, gai_result->ai_addrlen);
|
||||||
|
freeaddrinfo_all(hints.ai_family, gai_result);
|
||||||
|
|
||||||
if (file_ip_addr->ai_family != mask->ss_family)
|
if (addr.ss_family != mask.ss_family)
|
||||||
goto hba_syntax;
|
goto hba_syntax;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_ip_addr->ai_family != port->raddr.addr.ss_family)
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user