]> granicus.if.org Git - postgresql/commitdiff
Second try at IPv4-to-v6 mapping code; avoid assuming that the struct
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 5 Sep 2003 23:07:21 +0000 (23:07 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 5 Sep 2003 23:07:21 +0000 (23:07 +0000)
returned by getaddrinfo_all will have enough room for an IPv6 address.

src/backend/libpq/hba.c
src/backend/libpq/ip.c
src/include/libpq/ip.h

index 2e2126362118176b724cf72b1c58748f056bcab7..55d96e16eafba4f891a13c252f79faaf28b65bc7 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * 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       *db;
        char       *user;
-       struct addrinfo *file_ip_addr = NULL,
-                          *file_ip_mask = NULL;
+       struct addrinfo *gai_result;
        struct addrinfo hints;
-       struct sockaddr_storage *mask;
-       char       *cidr_slash;
        int                     ret;
+       struct sockaddr_storage addr;
+       struct sockaddr_storage mask;
+       char       *cidr_slash;
 
        Assert(line != NIL);
        line_number = lfirsti(line);
@@ -648,6 +648,7 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
                if (cidr_slash)
                        *cidr_slash = '\0';
 
+               /* Get the IP address either way */
                hints.ai_flags = AI_NUMERICHOST;
                hints.ai_family = PF_UNSPEC;
                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_next = NULL;
 
-               /* Get the IP address either way */
-               ret = getaddrinfo_all(token, NULL, &hints, &file_ip_addr);
-               if (ret || !file_ip_addr)
+               ret = getaddrinfo_all(token, NULL, &hints, &gai_result);
+               if (ret || !gai_result)
                {
                        ereport(LOG,
                                        (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))));
                        if (cidr_slash)
                                *cidr_slash = '/';
+                       if (gai_result)
+                               freeaddrinfo_all(hints.ai_family, gai_result);
                        goto hba_syntax;
                }
 
                if (cidr_slash)
                        *cidr_slash = '/';
 
+               memcpy(&addr, gai_result->ai_addr, gai_result->ai_addrlen);
+               freeaddrinfo_all(hints.ai_family, gai_result);
+
                /* Get the netmask */
                if (cidr_slash)
                {
-                       if (SockAddr_cidr_mask(&mask, cidr_slash + 1,
-                                                                  file_ip_addr->ai_family) < 0)
+                       if (SockAddr_cidr_mask(&mask, cidr_slash + 1, addr.ss_family) < 0)
                                goto hba_syntax;
                }
                else
@@ -688,17 +692,22 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p)
                                goto hba_syntax;
                        token = lfirst(line);
 
-                       ret = getaddrinfo_all(token, NULL, &hints, &file_ip_mask);
-                       if (ret || !file_ip_mask)
+                       ret = getaddrinfo_all(token, NULL, &hints, &gai_result);
+                       if (ret || !gai_result)
+                       {
+                               if (gai_result)
+                                       freeaddrinfo_all(hints.ai_family, gai_result);
                                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;
                }
 
-               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
@@ -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.
                         */
 #ifdef HAVE_IPV6
-                       if (file_ip_addr->ai_family == AF_INET &&
+                       if (addr.ss_family == AF_INET &&
                                port->raddr.addr.ss_family == AF_INET6)
                        {
-                               promote_v4_to_v6_addr((struct sockaddr_storage *) file_ip_addr->ai_addr);
-                               promote_v4_to_v6_mask(mask);
+                               promote_v4_to_v6_addr(&addr);
+                               promote_v4_to_v6_mask(&mask);
                        }
                        else
 #endif /* HAVE_IPV6 */
                        {
-                               freeaddrinfo_all(hints.ai_family, file_ip_addr);
+                               /* Line doesn't match client port, so ignore it. */
                                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. */
                line = lnext(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);
                if (*error_p)
                        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
                goto hba_syntax;
@@ -763,12 +766,6 @@ hba_syntax:
                                   line_number)));
 
        *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);
 }
 
 
index 6ab5f57fd785494555e68ef24116692a52796905..4ecc542c27ce24828504b52143f4358ec68348dc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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
  * 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
  *       and required number of significant bits
  *
- * Note: Returns a static pointer for the mask, so it's not thread safe,
- *              and a second call will overwrite the data.
+ * The resulting mask is placed in *mask, which had better be big enough.
+ *
+ * Return value is 0 if okay, -1 if not.
  */
 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;
        char       *endptr;
-       static struct sockaddr_storage sock;
        struct sockaddr_in mask4;
 
 #ifdef HAVE_IPV6
@@ -359,15 +359,13 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family)
                )
                return -1;
 
-       *mask = &sock;
-
        switch (family)
        {
                case AF_INET:
                        mask4.sin_addr.s_addr =
                                htonl((0xffffffffUL << (32 - bits))
                                          & 0xffffffffUL);
-                       memcpy(&sock, &mask4, sizeof(mask4));
+                       memcpy(mask, &mask4, sizeof(mask4));
                        break;
 #ifdef HAVE_IPV6
                case AF_INET6:
@@ -387,7 +385,7 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family)
                                        }
                                        bits -= 8;
                                }
-                               memcpy(&sock, &mask6, sizeof(mask6));
+                               memcpy(mask, &mask6, sizeof(mask6));
                                break;
                        }
 #endif
@@ -395,7 +393,7 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family)
                        return -1;
        }
 
-       sock.ss_family = family;
+       mask->ss_family = family;
        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
  *             the standard convention for IPv4 addresses mapped into IPv6 world
  *
- * The passed addr is modified in place.  Note that we only worry about
- * setting the fields that rangeSockAddr will look at.
+ * The passed addr is modified in place; be sure it is large enough to
+ * hold the result!  Note that we only worry about setting the fields
+ * that rangeSockAddr will look at.
  */
 void
 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
  * set the high-order bits to 1's not 0's.
  *
- * The passed addr is modified in place.  Note that we only worry about
- * setting the fields that rangeSockAddr will look at.
+ * The passed addr is modified in place; be sure it is large enough to
+ * hold the result!  Note that we only worry about setting the fields
+ * that rangeSockAddr will look at.
  */
 void
 promote_v4_to_v6_mask(struct sockaddr_storage * addr)
index 9858faaddc9888b8cb1fbc3930b807c37952f83b..32f7835c429b2ee84e1672043752c3ea6a6eb5a2 100644 (file)
@@ -5,7 +5,7 @@
  *
  * 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 * netmask);
 
-extern int SockAddr_cidr_mask(struct sockaddr_storage ** mask,
+extern int SockAddr_cidr_mask(struct sockaddr_storage * mask,
                                   char *numbits, int family);
 
 #ifdef HAVE_IPV6