From b78961b0da946e67c0f46156c193d27e63aa3de9 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 12 Jun 2003 02:12:58 +0000 Subject: [PATCH] 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 --- src/backend/libpq/hba.c | 45 ++++++++++++++++++++++++--------- src/backend/libpq/ip.c | 55 ++++++++++++++++++++++++++++++++++++++++- src/include/libpq/ip.h | 4 ++- 3 files changed, 91 insertions(+), 13 deletions(-) diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index f722bb5271..6d4da21cfb 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -10,7 +10,7 @@ * * * 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) else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0) { SockAddr file_ip_addr, mask; + char * cidr_slash; if (strcmp(token, "hostssl") == 0) { @@ -618,26 +619,48 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) goto hba_syntax; user = lfirst(line); - /* Read the IP address field. */ + /* Read the IP address field. (with or without CIDR netmask) */ line = lnext(line); if (!line) goto hba_syntax; 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 (cidr_slash) + *cidr_slash = '/'; goto hba_syntax; + } - /* Read the mask field. */ - line = lnext(line); - if (!line) - goto hba_syntax; - token = lfirst(line); + /* Get the netmask */ + if (cidr_slash) + { + *cidr_slash = '/'; + 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. */ line = lnext(line); diff --git a/src/backend/libpq/ip.c b/src/backend/libpq/ip.c index 948fb57614..2573829fd8 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.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 * Nigel Kukard , Linux Based Systems Design @@ -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 diff --git a/src/include/libpq/ip.h b/src/include/libpq/ip.h index 7e910d5cbb..a6128e213e 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.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, int v4conv); 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 rangeSockAddr(const SockAddr *addr, const SockAddr *netaddr, const SockAddr *netmask); -- GitLab