in erts/etc/common/inet_gethost.c [1665:1964]
DWORD WINAPI worker_loop(void *v)
#else
static int worker_loop(void)
#endif
{
AddrByte *req = NULL;
size_t req_size = 0;
int this_size;
AddrByte *reply = NULL;
size_t reply_size = 0;
size_t data_size;
#ifdef WIN32
QueItem *m = NULL;
MesQ *readfrom = ((MesQ **) v)[0];
MesQ *writeto = ((MesQ **) v)[1];
/* XXX:PaN */
FREE(v);
#endif
for(;;) {
#ifdef HAVE_GETADDRINFO
struct addrinfo *ai = NULL;
#endif
struct hostent *he = NULL;
#ifdef HAVE_GETNAMEINFO
struct sockaddr *sa = NULL;
char name[NI_MAXHOST];
#endif
#if defined(HAVE_GETIPNODEBYNAME) || defined(HAVE_GETIPNODEBYADDR)
int free_he = 0;
#endif
int error_num = 0;
SerialType serial;
OpType op;
ProtoType proto;
AddrByte *data;
#ifdef WIN32
WaitForSingleObject(event_mesq(readfrom),INFINITE);
DEBUGF(4,("Worker got data on message que."));
if(!deque_mesq(readfrom,&m)) {
goto fail;
}
this_size = m->req_size;
req = m->request;
#else
if (READ_PACKET_BYTES(0,&this_size) != PACKET_BYTES) {
DEBUGF(2,("Worker got error/EOF while reading size, exiting."));
exit(0);
}
if (this_size > req_size) {
if (req == NULL) {
req = ALLOC((req_size = this_size));
} else {
req = REALLOC(req, (req_size = this_size));
}
}
if (read_exact(0, req, (size_t) this_size) != this_size) {
DEBUGF(1,("Worker got EOF while reading data, exiting."));
exit(0);
}
#endif
/* Decode the request... */
serial = get_serial(req);
if (OP_CONTROL == (op = get_op(req))) {
CtlType ctl;
if (serial != INVALID_SERIAL) {
DEBUGF(1, ("Worker got invalid serial: %d.", serial));
exit(0);
}
switch (ctl = get_ctl(req)) {
case SETOPT_DEBUG_LEVEL:
debug_level = get_debug_level(req);
DEBUGF(debug_level,
("Worker debug_level = %d.", debug_level));
break;
}
continue;
}
proto = get_proto(req);
data = get_data(req);
DEBUGF(4,("Worker got request, op = %d, proto = %d, data = %s.",
op,proto,data));
/* Got a request, lets go... */
switch (op) {
case OP_GETHOSTBYNAME:
switch (proto) {
#ifdef HAVE_IN6
case PROTO_IPV6: { /* switch (proto) { */
#ifdef HAVE_GETADDRINFO
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_INET6;
DEBUGF(5, ("Starting getaddrinfo(%s, ...)", data));
error_num = getaddrinfo((char *)data, NULL, &hints, &ai);
DEBUGF(5,("getaddrinfo returned %d", error_num));
if (error_num) {
error_num = map_netdb_error_ai(error_num);
}
#elif defined(HAVE_GETIPNODEBYNAME) /*#ifdef HAVE_GETADDRINFO */
DEBUGF(5,("Starting getipnodebyname(%s)",data));
he = getipnodebyname(data, AF_INET6, 0, &error_num);
if (he) {
free_he = 1;
error_num = 0;
DEBUGF(5,("getipnodebyname(,AF_INET6,,) OK"));
} else {
DEBUGF(5,("getipnodebyname(,AF_INET6,,) error %d", error_num));
error_num = map_netdb_error(error_num);
}
#elif defined(HAVE_GETHOSTBYNAME2) /*#ifdef HAVE_GETADDRINFO */
DEBUGF(5,("Starting gethostbyname2(%s, AF_INET6)",data));
he = gethostbyname2((char*)data, AF_INET6);
if (he) {
error_num = 0;
DEBUGF(5,("gethostbyname2(, AF_INET6) OK"));
} else {
error_num = map_netdb_error(h_errno);
DEBUGF(5,("gethostbyname2(, AF_INET6) error %d", h_errno));
}
#else
error_num = ERRCODE_NOTSUP;
#endif /*#ifdef HAVE_GETADDRINFO */
} break;
#endif /*ifdef HAVE_IN6 */
case PROTO_IPV4: { /* switch (proto) { */
DEBUGF(5,("Starting gethostbyname(%s)",data));
he = gethostbyname((char*)data);
if (he) {
error_num = 0;
DEBUGF(5,("gethostbyname OK"));
} else {
error_num = map_netdb_error(h_errno);
DEBUGF(5,("gethostbyname error %d", h_errno));
}
} break;
default: /* switch (proto) { */
/* Not supported... */
error_num = ERRCODE_NOTSUP;
break;
} /* switch (proto) { */
if (he) {
data_size = build_reply(serial, he, &reply, &reply_size);
#ifdef HAVE_GETIPNODEBYNAME
if (free_he) {
freehostent(he);
}
#endif
#ifdef HAVE_GETADDRINFO
} else if (ai) {
data_size = build_reply_ai(serial, 16, ai,
&reply, &reply_size);
freeaddrinfo(ai);
#endif
} else {
data_size = build_error_reply(serial, error_num,
&reply, &reply_size);
}
break; /* case OP_GETHOSTBYNAME: */
case OP_GETHOSTBYADDR: /* switch (op) { */
switch (proto) {
#ifdef HAVE_IN6
case PROTO_IPV6: {
#ifdef HAVE_GETNAMEINFO
struct sockaddr_in6 *sin;
socklen_t salen = sizeof(*sin);
sin = ALLOC(salen);
#ifndef NO_SA_LEN
sin->sin6_len = salen;
#endif
sin->sin6_family = AF_INET6;
sin->sin6_port = 0;
memcpy(&sin->sin6_addr, data, 16);
sa = (struct sockaddr *)sin;
DEBUGF(5,("Starting getnameinfo(,,%s,16,,,)",
format_address(16, data)));
error_num = getnameinfo(sa, salen, name, sizeof(name),
NULL, 0, NI_NAMEREQD);
DEBUGF(5,("getnameinfo returned %d", error_num));
if (error_num) {
error_num = map_netdb_error_ai(error_num);
sa = NULL;
}
#elif defined(HAVE_GETIPNODEBYADDR) /*#ifdef HAVE_GETNAMEINFO*/
struct in6_addr ia;
memcpy(ia.s6_addr, data, 16);
DEBUGF(5,("Starting getipnodebyaddr(%s,16,AF_INET6,)",
format_address(16, data)));
he = getipnodebyaddr(&ia, 16, AF_INET6, &error_num);
free_he = 1;
if (! he) {
DEBUGF(5,("getipnodebyaddr error %d", error_num));
error_num = map_netdb_error(error_num);
} else {
DEBUGF(5,("getipnodebyaddr OK"));
}
#else /*#ifdef HAVE_GETNAMEINFO*/
struct in6_addr ia;
memcpy(ia.s6_addr, data, 16);
DEBUGF(5,("Starting gethostbyaddr(%s,16,AF_INET6)",
format_address(16, data)));
he = gethostbyaddr((const char *) &ia, 16, AF_INET6);
if (! he) {
error_num = map_netdb_error(h_errno);
DEBUGF(5,("gethostbyaddr error %d", h_errno));
} else {
DEBUGF(5,("gethostbyaddr OK"));
}
#endif /* #ifdef HAVE_GETNAMEINFO */
} break; /* case PROTO_IPV6: { */
#endif /* #ifdef HAVE_IN6 */
case PROTO_IPV4: { /* switch(proto) { */
struct in_addr ia;
memcpy(&ia.s_addr, data, 4); /* Alignment required... */
DEBUGF(5,("Starting gethostbyaddr(%s,4,AF_INET)",
format_address(4, data)));
he = gethostbyaddr((const char *) &ia, 4, AF_INET);
if (! he) {
error_num = map_netdb_error(h_errno);
DEBUGF(5,("gethostbyaddr error %d", h_errno));
} else {
DEBUGF(5,("gethostbyaddr OK"));
}
} break;
default:
error_num = ERRCODE_NOTSUP;
} /* switch(proto) { */
if (he) {
data_size = build_reply(serial, he, &reply, &reply_size);
#ifdef HAVE_GETIPNODEBYADDR
if (free_he) {
freehostent(he);
}
#endif
#ifdef HAVE_GETNAMEINFO
} else if (sa) {
struct addrinfo res;
memset(&res, 0, sizeof(res));
res.ai_canonname = name;
res.ai_addr = sa;
res.ai_next = NULL;
data_size = build_reply_ai(serial, 16, &res,
&reply, &reply_size);
free(sa);
#endif
} else {
data_size = build_error_reply(serial, error_num,
&reply, &reply_size);
}
break; /* case OP_GETHOSTBYADR: */
default:
data_size = build_error_reply(serial, ERRCODE_NOTSUP,
&reply, &reply_size);
break;
} /* switch (op) { */
#ifdef WIN32
m = REALLOC(m, sizeof(QueItem) - 1 + data_size - PACKET_BYTES);
m->next = NULL;
m->req_size = data_size - PACKET_BYTES;
memcpy(m->request,reply + PACKET_BYTES,data_size - PACKET_BYTES);
if (!enque_mesq(writeto,m)) {
goto fail;
}
m = NULL;
#else
/* expect no signals */
if (write(1, reply, data_size) < 0)
goto fail;
#endif
} /* for (;;) */
fail:
#ifdef WIN32
if (m != NULL) {
FREE(m);
}
close_mesq(readfrom);
close_mesq(writeto);
if (reply) {
FREE(reply);
}
#endif
return 1;
}