+
+/* For better readability we use a separate function to implement the
+ child code of sock_get_address_info_async. Note, that under W32
+ this is actually not a child but a thread and this is the reason
+ why we pass only a void pointer. */
+static void address_info_async_child(void *opaque)
+{
+ SockLookupData *parm = opaque;
+#ifdef INET6
+ gint gai_err;
+ struct addrinfo hints, *res, *ai;
+ gchar port_str[6];
+#else /* !INET6 */
+ struct hostent *hp;
+ gchar **addr_list_p;
+ struct sockaddr_in ad;
+#endif /* INET6 */
+ gint ai_member[4] = {AF_UNSPEC, 0, 0, 0};
+
+#ifndef G_OS_WIN32
+ close(parm->pipe_fds[0]);
+ parm->pipe_fds[0] = -1;
+#endif
+
+#ifdef INET6
+ memset(&hints, 0, sizeof(hints));
+ /* hints.ai_flags = AI_CANONNAME; */
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ g_snprintf(port_str, sizeof(port_str), "%d", parm->port);
+
+ gai_err = getaddrinfo(parm->hostname, port_str, &hints, &res);
+ if (gai_err != 0) {
+ g_warning("getaddrinfo for %s:%s failed: %s\n",
+ parm->hostname, port_str, gai_strerror(gai_err));
+ fd_write_all(parm->pipe_fds[1], (gchar *)ai_member,
+ sizeof(ai_member));
+ close(parm->pipe_fds[1]);
+ parm->pipe_fds[1] = -1;
+#ifdef G_OS_WIN32
+ _endthread();
+#else
+ _exit(1);
+#endif
+ }
+
+ for (ai = res; ai != NULL; ai = ai->ai_next) {
+ ai_member[0] = ai->ai_family;
+ ai_member[1] = ai->ai_socktype;
+ ai_member[2] = ai->ai_protocol;
+ ai_member[3] = ai->ai_addrlen;
+
+ fd_write_all(parm->pipe_fds[1], (gchar *)ai_member,
+ sizeof(ai_member));
+ fd_write_all(parm->pipe_fds[1], (gchar *)ai->ai_addr,
+ ai->ai_addrlen);
+ }
+
+ if (res != NULL)
+ freeaddrinfo(res);
+#else /* !INET6 */
+ hp = my_gethostbyname(parm->hostname);
+ if (hp == NULL || hp->h_addrtype != AF_INET) {
+ fd_write_all(parm->pipe_fds[1], (gchar *)ai_member,
+ sizeof(ai_member));
+ close(parm->pipe_fds[1]);
+ parm->pipe_fds[1] = -1;
+#ifdef G_OS_WIN32
+ _endthread();
+#else
+ _exit(1);
+#endif
+ }
+
+ ai_member[0] = AF_INET;
+ ai_member[1] = SOCK_STREAM;
+ ai_member[2] = IPPROTO_TCP;
+ ai_member[3] = sizeof(ad);
+
+ memset(&ad, 0, sizeof(ad));
+ ad.sin_family = AF_INET;
+ ad.sin_port = htons(parm->port);
+
+ for (addr_list_p = hp->h_addr_list; *addr_list_p != NULL;
+ addr_list_p++) {
+ memcpy(&ad.sin_addr, *addr_list_p, hp->h_length);
+ fd_write_all(parm->pipe_fds[1], (gchar *)ai_member,
+ sizeof(ai_member));
+ fd_write_all(parm->pipe_fds[1], (gchar *)&ad, sizeof(ad));
+ }
+#endif /* INET6 */
+
+ close(parm->pipe_fds[1]);
+ parm->pipe_fds[1] = -1;
+
+#ifdef G_OS_WIN32
+ _endthread();
+#else
+ _exit(0);
+#endif
+}
+