Improve the mingw getaddrinfo stub to handle more use cases
[gitweb.git] / compat / mingw.c
index 146a6ed79c848cd5dab31b24ee3a4ff635de63a3..a6c1ee702a54fdbcaab7af031a4e7a3e7ea2c1ce 100644 (file)
@@ -1039,19 +1039,22 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,
                                   const struct addrinfo *hints,
                                   struct addrinfo **res)
 {
-       struct hostent *h = gethostbyname(node);
+       struct hostent *h = NULL;
        struct addrinfo *ai;
        struct sockaddr_in *sin;
 
-       if (!h)
-               return WSAGetLastError();
+       if (node) {
+               h = gethostbyname(node);
+               if (!h)
+                       return WSAGetLastError();
+       }
 
        ai = xmalloc(sizeof(struct addrinfo));
        *res = ai;
        ai->ai_flags = 0;
        ai->ai_family = AF_INET;
-       ai->ai_socktype = hints->ai_socktype;
-       switch (hints->ai_socktype) {
+       ai->ai_socktype = hints ? hints->ai_socktype : 0;
+       switch (ai->ai_socktype) {
        case SOCK_STREAM:
                ai->ai_protocol = IPPROTO_TCP;
                break;
@@ -1063,14 +1066,25 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,
                break;
        }
        ai->ai_addrlen = sizeof(struct sockaddr_in);
-       ai->ai_canonname = strdup(h->h_name);
+       if (hints && (hints->ai_flags & AI_CANONNAME))
+               ai->ai_canonname = h ? strdup(h->h_name) : NULL;
+       else
+               ai->ai_canonname = NULL;
 
        sin = xmalloc(ai->ai_addrlen);
        memset(sin, 0, ai->ai_addrlen);
        sin->sin_family = AF_INET;
+       /* Note: getaddrinfo is supposed to allow service to be a string,
+        * which should be looked up using getservbyname. This is
+        * currently not implemented */
        if (service)
                sin->sin_port = htons(atoi(service));
-       sin->sin_addr = *(struct in_addr *)h->h_addr;
+       if (h)
+               sin->sin_addr = *(struct in_addr *)h->h_addr;
+       else if (hints && (hints->ai_flags & AI_PASSIVE))
+               sin->sin_addr.s_addr = INADDR_ANY;
+       else
+               sin->sin_addr.s_addr = INADDR_LOOPBACK;
        ai->ai_addr = (struct sockaddr *)sin;
        ai->ai_next = 0;
        return 0;