static int dns_client_input_line(struct dns_client *client, const char *line) { struct ip_addr *ips, ip; const char *name; unsigned int i, ips_count; int ret; if (strncmp(line, "IP\t", 3) == 0) { ret = net_gethostbyname(line + 3, &ips, &ips_count); if (ret == 0 && ips_count == 0) { /* shouldn't happen, but fix it anyway.. */ ret = EAI_NONAME; } if (ret != 0) { o_stream_nsend_str(client->output, t_strdup_printf("%d\n", ret)); } else { o_stream_nsend_str(client->output, t_strdup_printf("0 %u\n", ips_count)); for (i = 0; i < ips_count; i++) { o_stream_nsend_str(client->output, t_strconcat( net_ip2addr(&ips[i]), "\n", NULL)); } } } else if (strncmp(line, "NAME\t", 5) == 0) { if (net_addr2ip(line+5, &ip) < 0) o_stream_nsend_str(client->output, "-1\n"); else if ((ret = net_gethostbyaddr(&ip, &name)) != 0) { o_stream_nsend_str(client->output, t_strdup_printf("%d\n", ret)); } else { o_stream_nsend_str(client->output, t_strdup_printf("0 %s\n", name)); } } else if (strcmp(line, "QUIT") == 0) { return -1; } else { o_stream_nsend_str(client->output, "Unknown command\n"); } if (client->output->overflow) return -1; return 0; }
/* nonblocking gethostbyname(), ip (IPADDR) + error (int, 0 = not error) is written to pipe when found PID of the resolver child is returned */ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int reverse_lookup) { RESOLVED_IP_REC rec; const char *errorstr; int pid; int len; g_return_val_if_fail(addr != NULL, FALSE); pid = fork(); if (pid > 0) { /* parent */ pidwait_add(pid); return pid; } if (pid != 0) { /* failed! */ g_warning("net_connect_thread(): fork() failed! " "Using blocking resolving"); } /* child */ srand(time(NULL)); memset(&rec, 0, sizeof(rec)); rec.error = net_gethostbyname(addr, &rec.ip4, &rec.ip6); if (rec.error == 0) { errorstr = NULL; if (reverse_lookup) { /* reverse lookup the IP, ignore any error */ if (rec.ip4.family != 0) net_gethostbyaddr(&rec.ip4, &rec.host4); if (rec.ip6.family != 0) net_gethostbyaddr(&rec.ip6, &rec.host6); } } else { errorstr = net_gethosterror(rec.error); rec.errlen = errorstr == NULL ? 0 : strlen(errorstr)+1; } g_io_channel_write_block(pipe, &rec, sizeof(rec)); if (rec.errlen != 0) g_io_channel_write_block(pipe, (void *) errorstr, rec.errlen); else { if (rec.host4) { len = strlen(rec.host4) + 1; g_io_channel_write_block(pipe, (void *) &len, sizeof(int)); g_io_channel_write_block(pipe, (void *) rec.host4, len); } if (rec.host6) { len = strlen(rec.host6) + 1; g_io_channel_write_block(pipe, (void *) &len, sizeof(int)); g_io_channel_write_block(pipe, (void *) rec.host6, len); } } if (pid == 0) _exit(99); /* we used blocking lookup */ return 0; }