From: Timo Sirainen Date: Fri, 28 Jun 2013 16:48:37 +0000 (+0300) Subject: dns, lib-dns: Added support for async DNS PTR lookups. X-Git-Tag: 2.2.5~83 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d29c3ac4da9857ffcce57eec726d042c292e2bec;p=thirdparty%2Fdovecot%2Fcore.git dns, lib-dns: Added support for async DNS PTR lookups. --- diff --git a/src/dns/dns-client.c b/src/dns/dns-client.c index a8323c033d..825c800160 100644 --- a/src/dns/dns-client.c +++ b/src/dns/dns-client.c @@ -27,7 +27,8 @@ static void dns_client_destroy(struct dns_client **client); static int dns_client_input_line(struct dns_client *client, const char *line) { - struct ip_addr *ips; + struct ip_addr *ips, ip; + const char *name; unsigned int i, ips_count; int ret; @@ -48,6 +49,16 @@ static int dns_client_input_line(struct dns_client *client, const char *line) 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 { diff --git a/src/lib-dns/dns-lookup.c b/src/lib-dns/dns-lookup.c index 4a831d5429..519ab13dc4 100644 --- a/src/lib-dns/dns-lookup.c +++ b/src/lib-dns/dns-lookup.c @@ -16,6 +16,7 @@ struct dns_lookup { int fd; char *path; + bool ptr_lookup; struct istream *input; struct io *io; @@ -27,6 +28,7 @@ struct dns_lookup { struct dns_lookup_result result; struct ip_addr *ips; unsigned int ip_idx; + char *name; dns_lookup_callback_t *callback; void *context; @@ -39,6 +41,20 @@ static int dns_lookup_input_line(struct dns_lookup *lookup, const char *line) struct dns_lookup_result *result = &lookup->result; if (result->ips_count == 0) { + if (lookup->ptr_lookup) { + /* [] */ + if (strncmp(line, "0 ", 2) == 0) { + result->name = lookup->name = + i_strdup(line + 2); + result->ret = 0; + } else { + if (str_to_int(line, &result->ret) < 0) { + return -1; + } + result->error = net_gethosterror(result->ret); + } + return 1; + } /* first line: */ if (sscanf(line, "%d %u", &result->ret, &result->ips_count) == 0) @@ -119,14 +135,14 @@ static void dns_lookup_timeout(struct dns_lookup *lookup) dns_lookup_free(&lookup); } -#undef dns_lookup -int dns_lookup(const char *host, const struct dns_lookup_settings *set, - dns_lookup_callback_t *callback, void *context, - struct dns_lookup **lookup_r) +static int +dns_lookup_common(const char *cmd, bool ptr_lookup, + const struct dns_lookup_settings *set, + dns_lookup_callback_t *callback, void *context, + struct dns_lookup **lookup_r) { struct dns_lookup *lookup; struct dns_lookup_result result; - const char *cmd; int fd; memset(&result, 0, sizeof(result)); @@ -140,7 +156,6 @@ int dns_lookup(const char *host, const struct dns_lookup_settings *set, return -1; } - cmd = t_strconcat("IP\t", host, "\n", NULL); if (write_full(fd, cmd, strlen(cmd)) < 0) { result.error = t_strdup_printf("write(%s) failed: %m", set->dns_client_socket_path); @@ -150,6 +165,7 @@ int dns_lookup(const char *host, const struct dns_lookup_settings *set, } lookup = i_new(struct dns_lookup, 1); + lookup->ptr_lookup = ptr_lookup; lookup->fd = fd; lookup->path = i_strdup(set->dns_client_socket_path); lookup->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE); @@ -168,6 +184,25 @@ int dns_lookup(const char *host, const struct dns_lookup_settings *set, return 0; } +#undef dns_lookup +int dns_lookup(const char *host, const struct dns_lookup_settings *set, + dns_lookup_callback_t *callback, void *context, + struct dns_lookup **lookup_r) +{ + return dns_lookup_common(t_strconcat("IP\t", host, "\n", NULL), FALSE, + set, callback, context, lookup_r); +} + +#undef dns_lookup_ptr +int dns_lookup_ptr(const struct ip_addr *ip, + const struct dns_lookup_settings *set, + dns_lookup_callback_t *callback, void *context, + struct dns_lookup **lookup_r) +{ + const char *cmd = t_strconcat("NAME\t", net_ip2addr(ip), "\n", NULL); + return dns_lookup_common(cmd, TRUE, set, callback, context, lookup_r); +} + static void dns_lookup_free(struct dns_lookup **_lookup) { struct dns_lookup *lookup = *_lookup; @@ -181,6 +216,7 @@ static void dns_lookup_free(struct dns_lookup **_lookup) if (close(lookup->fd) < 0) i_error("close(%s) failed: %m", lookup->path); + i_free(lookup->name); i_free(lookup->ips); i_free(lookup->path); i_free(lookup); diff --git a/src/lib-dns/dns-lookup.h b/src/lib-dns/dns-lookup.h index 3cb364a8d8..8e597ff770 100644 --- a/src/lib-dns/dns-lookup.h +++ b/src/lib-dns/dns-lookup.h @@ -19,8 +19,11 @@ struct dns_lookup_result { /* how many milliseconds the lookup took. */ unsigned int msecs; + /* for IP lookup: */ unsigned int ips_count; const struct ip_addr *ips; + /* for PTR lookup: */ + const char *name; }; typedef void dns_lookup_callback_t(const struct dns_lookup_result *result, @@ -38,6 +41,15 @@ int dns_lookup(const char *host, const struct dns_lookup_settings *set, CALLBACK_TYPECHECK(callback, void (*)( \ const struct dns_lookup_result *, typeof(context))), \ set, (dns_lookup_callback_t *)callback, context, lookup_r) +int dns_lookup_ptr(const struct ip_addr *ip, + const struct dns_lookup_settings *set, + dns_lookup_callback_t *callback, void *context, + struct dns_lookup **lookup_r) ATTR_NULL(4); +#define dns_lookup_ptr(host, set, callback, context, lookup_r) \ + dns_lookup_ptr(host + \ + CALLBACK_TYPECHECK(callback, void (*)( \ + const struct dns_lookup_result *, typeof(context))), \ + set, (dns_lookup_callback_t *)callback, context, lookup_r) /* Abort the DNS lookup without calling the callback. */ void dns_lookup_abort(struct dns_lookup **lookup);