Index: src/backend/libpq/hba.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/hba.c,v retrieving revision 1.100 diff -c -r1.100 hba.c *** src/backend/libpq/hba.c 2003/04/25 01:24:00 1.100 --- src/backend/libpq/hba.c 2003/05/09 22:49:35 *************** *** 588,593 **** --- 588,594 ---- else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0) { SockAddr file_ip_addr, mask; + char * cidr_slash; if (strcmp(token, "hostssl") == 0) { *************** *** 618,643 **** goto hba_syntax; user = lfirst(line); ! /* Read the IP address field. */ line = lnext(line); if (!line) goto hba_syntax; token = lfirst(line); if(SockAddr_pton(&file_ip_addr, token) < 0) goto hba_syntax; ! /* 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; /* Read the rest of the line. */ line = lnext(line); --- 619,666 ---- goto hba_syntax; user = lfirst(line); ! /* 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 = index(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; + } ! /* 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; ! } ! ! /* Read the rest of the line. */ line = lnext(line); Index: src/backend/libpq/ip.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/ip.c,v retrieving revision 1.7 diff -c -r1.7 ip.c *** src/backend/libpq/ip.c 2003/04/22 03:52:56 1.7 --- src/backend/libpq/ip.c 2003/05/09 22:49:35 *************** *** 236,241 **** --- 236,294 ---- } } + /* + * 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 Index: src/include/libpq/ip.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/libpq/ip.h,v retrieving revision 1.3 diff -c -r1.3 ip.h *** src/include/libpq/ip.h 2003/04/02 00:49:28 1.3 --- src/include/libpq/ip.h 2003/05/09 22:49:35 *************** *** 25,30 **** --- 25,32 ---- 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);