s3:lib/events: make use of tevent_common_loop_timer_delay()
[Samba/gebeck_regimport.git] / libcli / dns / dns.c
blob43e1c4e0c79c47f94b8e57bf4292407681e540c3
1 /*
2 Unix SMB/CIFS implementation.
4 Small async DNS library for Samba with socketwrapper support
6 Copyright (C) 2010 Kai Blin <kai@samba.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "replace.h"
23 #include "system/network.h"
24 #include <tevent.h>
25 #include "lib/tsocket/tsocket.h"
26 #include "libcli/util/werror.h"
27 #include "libcli/dns/libdns.h"
28 #include "lib/util/tevent_werror.h"
29 #include "lib/util/samba_util.h"
30 #include "libcli/util/error.h"
31 #include "librpc/gen_ndr/dns.h"
33 struct dns_udp_request_state {
34 struct tevent_context *ev;
35 struct tdgram_context *dgram;
36 size_t query_len;
37 uint8_t *reply;
38 size_t reply_len;
41 #define DNS_REQUEST_TIMEOUT 2
43 /* Declare callback functions used below. */
44 static void dns_udp_request_get_reply(struct tevent_req *subreq);
45 static void dns_udp_request_done(struct tevent_req *subreq);
47 struct tevent_req *dns_udp_request_send(TALLOC_CTX *mem_ctx,
48 struct tevent_context *ev,
49 const char *server_addr_string,
50 const uint8_t *query,
51 size_t query_len)
53 struct tevent_req *req, *subreq;
54 struct dns_udp_request_state *state;
55 struct tsocket_address *local_addr, *server_addr;
56 struct tdgram_context *dgram;
57 int ret;
59 req = tevent_req_create(mem_ctx, &state, struct dns_udp_request_state);
60 if (req == NULL) {
61 return NULL;
64 state->ev = ev;
66 /* Use connected UDP sockets */
67 ret = tsocket_address_inet_from_strings(state, "ip", NULL, 0,
68 &local_addr);
69 if (ret != 0) {
70 tevent_req_werror(req, unix_to_werror(ret));
71 return tevent_req_post(req, ev);
74 ret = tsocket_address_inet_from_strings(state, "ip", server_addr_string,
75 DNS_SERVICE_PORT, &server_addr);
76 if (ret != 0) {
77 tevent_req_werror(req, unix_to_werror(ret));
78 return tevent_req_post(req, ev);
81 ret = tdgram_inet_udp_socket(local_addr, server_addr, state, &dgram);
82 if (ret != 0) {
83 tevent_req_werror(req, unix_to_werror(ret));
84 return tevent_req_post(req, ev);
87 state->dgram = dgram;
88 state->query_len = query_len;
90 dump_data(10, query, query_len);
92 subreq = tdgram_sendto_send(state, ev, dgram, query, query_len, NULL);
93 if (tevent_req_nomem(subreq, req)) {
94 return tevent_req_post(req, ev);
97 if (!tevent_req_set_endtime(req, ev,
98 timeval_current_ofs(DNS_REQUEST_TIMEOUT, 0))) {
99 return tevent_req_post(req, ev);
103 tevent_req_set_callback(subreq, dns_udp_request_get_reply, req);
104 return req;
107 static void dns_udp_request_get_reply(struct tevent_req *subreq)
109 struct tevent_req *req = tevent_req_callback_data(subreq,
110 struct tevent_req);
111 struct dns_udp_request_state *state = tevent_req_data(req,
112 struct dns_udp_request_state);
113 ssize_t len;
114 int err = 0;
116 len = tdgram_sendto_recv(subreq, &err);
117 TALLOC_FREE(subreq);
119 if (len == -1 && err != 0) {
120 tevent_req_werror(req, unix_to_werror(err));
121 return;
124 if (len != state->query_len) {
125 tevent_req_werror(req, WERR_NET_WRITE_FAULT);
126 return;
129 subreq = tdgram_recvfrom_send(state, state->ev, state->dgram);
130 if (tevent_req_nomem(subreq, req)) {
131 return;
134 tevent_req_set_callback(subreq, dns_udp_request_done, req);
135 return;
138 static void dns_udp_request_done(struct tevent_req *subreq)
140 struct tevent_req *req = tevent_req_callback_data(subreq,
141 struct tevent_req);
142 struct dns_udp_request_state *state = tevent_req_data(req,
143 struct dns_udp_request_state);
145 ssize_t len;
146 int err = 0;
148 len = tdgram_recvfrom_recv(subreq, &err, state, &state->reply, NULL);
149 TALLOC_FREE(subreq);
151 if (len == -1 && err != 0) {
152 tevent_req_werror(req, unix_to_werror(err));
153 return;
156 state->reply_len = len;
157 dump_data(10, state->reply, state->reply_len);
158 tevent_req_done(req);
161 WERROR dns_udp_request_recv(struct tevent_req *req,
162 TALLOC_CTX *mem_ctx,
163 uint8_t **reply,
164 size_t *reply_len)
166 struct dns_udp_request_state *state = tevent_req_data(req,
167 struct dns_udp_request_state);
168 WERROR w_error;
170 if (tevent_req_is_werror(req, &w_error)) {
171 tevent_req_received(req);
172 return w_error;
175 *reply = talloc_move(mem_ctx, &state->reply);
176 *reply_len = state->reply_len;
177 tevent_req_received(req);
179 return WERR_OK;