Commit b78961b0 authored by Bruce Momjian's avatar Bruce Momjian

Here is a patch that allows CIDR netmasks in pg_hba.conf. It allows two

address/mask forms:

. address/maskbits, or
. address netmask (as now)

If the patch is accepted I will submit a documentation patch to cover
it.

This is submitted by agreement with Kurt Roeckx, who has worked on a
patch that covers this and other IPv6 issues.

Andrew Dunstan
parent 310c0849
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.100 2003/04/25 01:24:00 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.101 2003/06/12 02:12:58 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -588,6 +588,7 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) ...@@ -588,6 +588,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)
{ {
SockAddr file_ip_addr, mask; SockAddr file_ip_addr, mask;
char * cidr_slash;
if (strcmp(token, "hostssl") == 0) if (strcmp(token, "hostssl") == 0)
{ {
...@@ -618,26 +619,48 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) ...@@ -618,26 +619,48 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
goto hba_syntax; goto hba_syntax;
user = lfirst(line); user = lfirst(line);
/* Read the IP address field. */ /* Read the IP address field. (with or without CIDR netmask) */
line = lnext(line); line = lnext(line);
if (!line) if (!line)
goto hba_syntax; goto hba_syntax;
token = lfirst(line); token = lfirst(line);
/* Check if it has a CIDR suffix and if so isolate it */
cidr_slash = strchr(token,'/');
if (cidr_slash)
*cidr_slash = '\0';
/* Get the IP address either way */
if(SockAddr_pton(&file_ip_addr, token) < 0) if(SockAddr_pton(&file_ip_addr, token) < 0)
{
if (cidr_slash)
*cidr_slash = '/';
goto hba_syntax; goto hba_syntax;
}
/* Read the mask field. */ /* Get the netmask */
line = lnext(line); if (cidr_slash)
if (!line) {
goto hba_syntax; *cidr_slash = '/';
token = lfirst(line); if (SockAddr_cidr_mask(&mask, ++cidr_slash, file_ip_addr.sa.sa_family) < 0)
goto hba_syntax;
}
else
{
/* Read the mask field. */
line = lnext(line);
if (!line)
goto hba_syntax;
token = lfirst(line);
if(SockAddr_pton(&mask, token) < 0)
goto hba_syntax;
if(file_ip_addr.sa.sa_family != mask.sa.sa_family)
goto hba_syntax;
}
if(SockAddr_pton(&mask, 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. */ /* Read the rest of the line. */
line = lnext(line); line = lnext(line);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.9 2003/06/09 17:59:19 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.10 2003/06/12 02:12:58 momjian 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
...@@ -251,6 +251,59 @@ SockAddr_pton(SockAddr *sa, const char *src) ...@@ -251,6 +251,59 @@ SockAddr_pton(SockAddr *sa, const char *src)
} }
} }
/*
* SockAddr_cidr_mask - make a network mask of the appropriate family
* and required number of significant bits
*/
int
SockAddr_cidr_mask(SockAddr *mask, char *numbits, int family)
{
int i;
long bits;
char * endptr;
bits = strtol(numbits,&endptr,10);
if (*numbits == '\0' || *endptr != '\0')
return -1;
if ((bits < 0) || (family == AF_INET && bits > 32)
#ifdef HAVE_IPV6
|| (family == AF_INET6 && bits > 128)
#endif
)
return -1;
mask->sa.sa_family = family;
switch (family)
{
case AF_INET:
mask->in.sin_addr.s_addr = htonl((0xffffffffUL << (32 - bits)) & 0xffffffffUL);
break;
#ifdef HAVE_IPV6
case AF_INET6:
for (i = 0; i < 16; i++)
{
if (bits <= 0)
mask->in6.sin6_addr.s6_addr[i]=0;
else if (bits >= 8)
mask->in6.sin6_addr.s6_addr[i]=0xff;
else
mask->in6.sin6_addr.s6_addr[i]=(0xff << (8 - bits)) & 0xff;
bits -= 8;
}
break;
#endif
default:
return -1;
}
return 0;
}
/* /*
* isAF_INETx - check to see if sa is AF_INET or AF_INET6 * isAF_INETx - check to see if sa is AF_INET or AF_INET6
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* Copyright (c) 2003, PostgreSQL Global Development Group * Copyright (c) 2003, PostgreSQL Global Development Group
* *
* $Id: ip.h,v 1.5 2003/06/09 17:59:19 tgl Exp $ * $Id: ip.h,v 1.6 2003/06/12 02:12:58 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -25,6 +25,8 @@ extern char *SockAddr_ntop(const SockAddr *sa, char *dst, size_t cnt, ...@@ -25,6 +25,8 @@ extern char *SockAddr_ntop(const SockAddr *sa, char *dst, size_t cnt,
int v4conv); int v4conv);
extern int SockAddr_pton(SockAddr *sa, const char *src); extern int SockAddr_pton(SockAddr *sa, const char *src);
extern int SockAddr_cidr_mask(SockAddr *mask, char *numbits, int family);
extern int isAF_INETx(const int family); extern int isAF_INETx(const int family);
extern int rangeSockAddr(const SockAddr *addr, const SockAddr *netaddr, extern int rangeSockAddr(const SockAddr *addr, const SockAddr *netaddr,
const SockAddr *netmask); const SockAddr *netmask);
......
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