Re: cvs: php4 /main network.c

From: Date: Tue, 05 Sep 2000 17:23:00 +0000
Subject: Re: cvs: php4 /main network.c
References: 1  Groups: php.cvs 
Request: Send a blank email to php-cvs+get-1581@lists.php.net to get a copy of this message
Any reason not to use emalloc()/efree() here? Are these functions used before the memory manager is initialized? Andi At 13:56 05/09/00 +0000, Stig Venaas wrote:
venaas          Tue Sep  5 06:56:11 2000 EDT
Modified files:
    /php4/main  network.c
Log: hostconnect now supports IPv6 if getaddrinfo exists, and also tries to connect to all addresses of a host before giving up. It should also be thread safe when using getaddrinfo. Index: php4/main/network.c diff -u php4/main/network.c:1.3 php4/main/network.c:1.4
--- php4/main/network.c:1.3     Mon Sep  4 05:58:08 2000
+++ php4/main/network.c Tue Sep 5 06:56:11 2000 @@ -15,7 +15,7 @@
    | Authors: Stig Venaas <venaas@uninett.no>                             |
    +----------------------------------------------------------------------+
*/ -/* $Id: network.c,v 1.3 2000/09/04 12:58:08 sas Exp $ */ +/* $Id: network.c,v 1.4 2000/09/05 13:56:11 venaas Exp $ */ #include "php.h" @@ -55,25 +55,94 @@ # define SOCK_CONN_ERR -1 #endif -/* Copied lookup_hostname, will be replaced */ - -/* - * Converts a host name to an IP address. - */ -static int php_network_lookup_hostname(const char *addr, struct in_addr *in) +static void php_network_freeaddresses(struct sockaddr **sal) {
-        struct hostent *host_info;
+       struct sockaddr **sap;
-        if (!inet_aton(addr, in)) {
-                /* XXX NOT THREAD SAFE */
-                host_info = gethostbyname(addr);
-                if (host_info == 0) {
-                        /* Error: unknown host */
+       if (sal == NULL)
+               return;
+       for (sap = sal; *sap != NULL; sap++)
+               free(*sap);
+       free(sal);
+} + +static int php_network_getaddresses(const char *host, struct sockaddr ***sal) +{
+       struct sockaddr **sap;
+
+        if (host != NULL) {
+#ifdef HAVE_GETADDRINFO
+                struct addrinfo hints, *res, *sai;
+               int n;
+
+                memset( &hints, '\0', sizeof(hints) );
+                hints.ai_family = AF_UNSPEC;
+                if (getaddrinfo(host, NULL, &hints, &res))
                         return -1;
-                }
-                *in = *((struct in_addr *) host_info->h_addr);
+                sai = res;
+               for (n=2; (sai = sai->ai_next) != NULL; n++);
+               *sal = malloc(n * sizeof(*sal));
+               if (*sal == NULL)
+                       return -1;
+
+                sai = res;
+               sap = *sal;
+                do {
+                        switch (sai->ai_family) {
+# ifdef AF_INET6
+                        case AF_INET6: {
+                               *sap = malloc(sizeof(struct sockaddr_in6));
+                               if (*sap == NULL) {
+                                       freeaddrinfo(res);
+                                       goto errexit;
+                               }
+                               *(struct sockaddr_in6 *)*sap =
+                                       *((struct sockaddr_in6 *)sai->ai_addr);
+                        } break;
+# endif
+                        case AF_INET: {
+                               *sap = malloc(sizeof(struct sockaddr_in));
+                               if (*sap == NULL) {
+                                       freeaddrinfo(res);
+                                       goto errexit;
+                               }
+                               *(struct sockaddr_in *)*sap =
+                                       *((struct sockaddr_in *)sai->ai_addr);
+                        } break;
+                        }
+                       sap++;
+                } while ((sai = sai->ai_next) != NULL);
+                freeaddrinfo(res);
+#else
+               struct hostent *host_info;
+               struct in_addr in;
+
+               if (!inet_aton(host, &in)) {
+                       /* XXX NOT THREAD SAFE */
+                       host_info = gethostbyname(host);
+                       if (host_info == NULL)
+                               return -1;
+                       in = *((struct in_addr *) host_info->h_addr);
+               }
+
+               *sal = malloc(2 * sizeof(*sal));
+               if (*sal == NULL)
+                       return -1;
+               sap = *sal;
+               *sap = malloc(sizeof(struct sockaddr_in));
+               if (*sap == NULL)
+                       goto errexit;
+
+               (*sap)->sa_family = AF_INET;
+               ((struct sockaddr_in *)*sap)->sin_addr = in;
+               sap++;
+#endif
+               *sap = NULL;
+               return 0;
+       errexit:
+               php_network_freeaddresses(*sal);
         }
-        return 0;
+       return -1;
} /* @@ -84,19 +153,49 @@ int hostconnect(char *host, int port, int socktype, int timeout) {
        int s;
-       struct sockaddr_in sa;
+       struct sockaddr **sal, **psal;
-       if (php_network_lookup_hostname(host, &sa.sin_addr))
-               return -1;
-       s = socket(PF_INET, socktype, 0);
-       if (s == SOCK_ERR)
+       if (php_network_getaddresses(host, &sal))
                return -1;
-       sa.sin_family = AF_INET;
-       sa.sin_port = htons(port);
-       if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) == SOCK_CONN_ERR) {
-               close (s);
-               return -1;
+
+       psal = sal;
+       while (*sal != NULL) {
+               s = socket((*sal)->sa_family, socktype, 0);
+               if (s != SOCK_ERR) {
+                       switch ((*sal)->sa_family) {
+#if defined( HAVE_GETADDRINFO ) && defined( AF_INET6 )
+                       case AF_INET6: {
+                               struct sockaddr_in6 *sa =
+                                       (struct sockaddr_in6 *)*sal;
+
+                               sa->sin6_family = (*sal)->sa_family;
+                               sa->sin6_port = htons(port);
+                               if (connect(s, (struct sockaddr *) sa,
+                                           sizeof(*sa)) != SOCK_CONN_ERR)
+                                       goto ok;
+                       } break;
+#endif
+                       case AF_INET: {
+                               struct sockaddr_in *sa =
+                                       (struct sockaddr_in *)*sal;
+
+                               sa->sin_family = (*sal)->sa_family;
+                               sa->sin_port = htons(port);
+                               if (connect(s, (struct sockaddr *) sa,
+                                           sizeof(*sa)) != SOCK_CONN_ERR)
+                                       goto ok;
+
+                       } break;
+                       }
+                       close (s);
+               }
+               sal++;
        }
+       php_network_freeaddresses(psal);
+       return -1;
+ + ok:
+       php_network_freeaddresses(psal);
        return s;
} -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, e-mail: php-cvs-unsubscribe@lists.php.net For additional commands, e-mail: php-cvs-help@lists.php.net To contact the list administrators, e-mail: php-list-admin@lists.php.net
--- Andi Gutmans <andi@zend.com> http://www.zend.com/

« previous php.cvs (#1581) next »