dns-lookup.c revision a8c5a86d183db25a57bf193c06b41e092ec2e151
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2010-2014 Dovecot authors, see the included COPYING file */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen unsigned int ip_idx;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen unsigned int timeout_msecs, idle_timeout_msecs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic void dns_lookup_free(struct dns_lookup **_lookup);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic void dns_client_disconnect(struct dns_client *client, const char *error)
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen i_error("close(%s) failed: %m", client->path);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenstatic int dns_lookup_input_line(struct dns_lookup *lookup, const char *line)
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen struct dns_lookup_result *result = &lookup->result;
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen /* <ret> [<name>] */
b6c48e71a9413ac90a0414dfeb7d1248c144eeb2Timo Sirainen result->error = net_gethosterror(result->ret);
b6c48e71a9413ac90a0414dfeb7d1248c144eeb2Timo Sirainen /* first line: <ret> <ip count> */
b6c48e71a9413ac90a0414dfeb7d1248c144eeb2Timo Sirainen result->error = net_gethosterror(result->ret);
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen if (net_addr2ip(line, &lookup->ips[lookup->ip_idx]) < 0)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic void dns_lookup_save_msecs(struct dns_lookup *lookup)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen diff = timeval_diff_msecs(&now, &lookup->start_time);
1183340bf4fda4040268aa4ba7a816b567659c08Timo Sirainenstatic void dns_client_input(struct dns_client *client)
0b0285689239ac08a324aff4b160ff2e920af4beTimo Sirainen while ((line = i_stream_read_next_line(client->input)) != NULL) {
0b0285689239ac08a324aff4b160ff2e920af4beTimo Sirainen dns_client_disconnect(client, t_strdup_printf(
0b0285689239ac08a324aff4b160ff2e920af4beTimo Sirainen dns_client_disconnect(client, t_strdup_printf(
0b0285689239ac08a324aff4b160ff2e920af4beTimo Sirainen if (ret != 0 && lookup->result.error != NULL) {
0b0285689239ac08a324aff4b160ff2e920af4beTimo Sirainen /* already got the error */
0b0285689239ac08a324aff4b160ff2e920af4beTimo Sirainen } else if (client->input->stream_errno != 0) {
0b0285689239ac08a324aff4b160ff2e920af4beTimo Sirainen dns_client_disconnect(client, t_strdup_printf(
0b0285689239ac08a324aff4b160ff2e920af4beTimo Sirainen dns_client_disconnect(client, t_strdup_printf(
0b0285689239ac08a324aff4b160ff2e920af4beTimo Sirainen lookup->callback(&lookup->result, lookup->context);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen retry = !lookup->client->deinit_client_at_free;
0b0285689239ac08a324aff4b160ff2e920af4beTimo Sirainenstatic void dns_lookup_timeout(struct dns_lookup *lookup)
3718da94157b9fa8d98c9f62f50133df504c7486Timo Sirainen lookup->result.error = "DNS lookup timed out";
3718da94157b9fa8d98c9f62f50133df504c7486Timo Sirainen lookup->callback(&lookup->result, lookup->context);
46b0fad7bc31f63f6f969b487bef2178beb125faTimo Sirainenint dns_lookup(const char *host, const struct dns_lookup_settings *set,
46b0fad7bc31f63f6f969b487bef2178beb125faTimo Sirainen dns_lookup_callback_t *callback, void *context,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen if (dns_client_lookup(client, host, callback, context, lookup_r) < 0) {
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen dns_lookup_callback_t *callback, void *context,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen if (dns_client_lookup_ptr(client, ip, callback, context, lookup_r) < 0) {
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenstatic void dns_client_idle_timeout(struct dns_client *client)
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen dns_client_disconnect(client, "Idle timeout");
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic void dns_lookup_free(struct dns_lookup **_lookup)
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen DLLIST2_REMOVE(&client->head, &client->tail, lookup);
0b0285689239ac08a324aff4b160ff2e920af4beTimo Sirainen client->to_idle = timeout_add(client->idle_timeout_msecs,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenvoid dns_lookup_abort(struct dns_lookup **lookup)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenvoid dns_lookup_switch_ioloop(struct dns_lookup *lookup)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen lookup->to = io_loop_move_timeout(&lookup->to);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen lookup->client->io = io_loop_move_io(&lookup->client->io);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstruct dns_client *dns_client_init(const struct dns_lookup_settings *set)
b6c48e71a9413ac90a0414dfeb7d1248c144eeb2Timo Sirainen client->path = i_strdup(set->dns_client_socket_path);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen client->idle_timeout_msecs = set->idle_timeout_msecs;
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenvoid dns_client_deinit(struct dns_client **_client)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenint dns_client_connect(struct dns_client *client, const char **error_r)
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen *error_r = t_strdup_printf("connect(%s) failed: %m",
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen client->input = i_stream_create_fd(client->fd, MAX_INBUF_SIZE, FALSE);
b6c48e71a9413ac90a0414dfeb7d1248c144eeb2Timo Sirainen client->io = io_add(client->fd, IO_READ, dns_client_input, client);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainendns_client_send_request(struct dns_client *client, const char *cmd,
d0f9c91ed9ccffa384ef2eebb1083b372591f02aTimo Sirainen const char **error_r)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* already connected. if write() fails, retry connecting */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (write_full(client->fd, cmd, strlen(cmd)) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen *error_r = t_strdup_printf("write(%s) failed: %m", client->path);
a78468f42df768399d6e3890381a936b439297b0Timo Sirainendns_client_lookup_common(struct dns_client *client,
a78468f42df768399d6e3890381a936b439297b0Timo Sirainen dns_lookup_callback_t *callback, void *context,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if ((ret = dns_client_send_request(client, cmd, &result.error)) <= 0) {
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen /* retry once */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen ret = dns_client_send_request(client, cmd, &result.error);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen lookup->to = timeout_add(client->timeout_msecs,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (gettimeofday(&lookup->start_time, NULL) < 0)
6ff4d08b3313454f181bc8c43fa2ac28bcece0e0Timo Sirainen DLLIST2_APPEND(&client->head, &client->tail, lookup);
6ff4d08b3313454f181bc8c43fa2ac28bcece0e0Timo Sirainenint dns_client_lookup(struct dns_client *client, const char *host,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen dns_lookup_callback_t *callback, void *context,
6ff4d08b3313454f181bc8c43fa2ac28bcece0e0Timo Sirainen const char *cmd = t_strconcat("IP\t", host, "\n", NULL);
6ff4d08b3313454f181bc8c43fa2ac28bcece0e0Timo Sirainen return dns_client_lookup_common(client, cmd, FALSE,
6ff4d08b3313454f181bc8c43fa2ac28bcece0e0Timo Sirainenint dns_client_lookup_ptr(struct dns_client *client, const struct ip_addr *ip,
6ff4d08b3313454f181bc8c43fa2ac28bcece0e0Timo Sirainen dns_lookup_callback_t *callback, void *context,
2a45e925383d56510d318ea47334e939f7d58130Timo Sirainen const char *cmd = t_strconcat("NAME\t", net_ip2addr(ip), "\n", NULL);