tevent: version 0.9.28
[Samba.git] / libcli / dns / dns.c
blob7d066d802c146414dcef0e827c9ce547b8ebbdfa
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/dns/libdns.h"
27 #include "lib/util/tevent_unix.h"
28 #include "lib/util/samba_util.h"
29 #include "libcli/util/error.h"
30 #include "librpc/gen_ndr/dns.h"
32 struct dns_udp_request_state {
33 struct tevent_context *ev;
34 struct tdgram_context *dgram;
35 size_t query_len;
36 uint8_t *reply;
37 size_t reply_len;
40 #define DNS_REQUEST_TIMEOUT 2
42 /* Declare callback functions used below. */
43 static void dns_udp_request_get_reply(struct tevent_req *subreq);
44 static void dns_udp_request_done(struct tevent_req *subreq);
46 struct tevent_req *dns_udp_request_send(TALLOC_CTX *mem_ctx,
47 struct tevent_context *ev,
48 const char *server_addr_string,
49 const uint8_t *query,
50 size_t query_len)
52 struct tevent_req *req, *subreq;
53 struct dns_udp_request_state *state;
54 struct tsocket_address *local_addr, *server_addr;
55 struct tdgram_context *dgram;
56 int ret;
58 req = tevent_req_create(mem_ctx, &state, struct dns_udp_request_state);
59 if (req == NULL) {
60 return NULL;
63 state->ev = ev;
65 /* Use connected UDP sockets */
66 ret = tsocket_address_inet_from_strings(state, "ip", NULL, 0,
67 &local_addr);
68 if (ret != 0) {
69 tevent_req_error(req, errno);
70 return tevent_req_post(req, ev);
73 ret = tsocket_address_inet_from_strings(state, "ip", server_addr_string,
74 DNS_SERVICE_PORT, &server_addr);
75 if (ret != 0) {
76 tevent_req_error(req, errno);
77 return tevent_req_post(req, ev);
80 ret = tdgram_inet_udp_socket(local_addr, server_addr, state, &dgram);
81 if (ret != 0) {
82 tevent_req_error(req, errno);
83 return tevent_req_post(req, ev);
86 state->dgram = dgram;
87 state->query_len = query_len;
89 dump_data(10, query, query_len);
91 subreq = tdgram_sendto_send(state, ev, dgram, query, query_len, NULL);
92 if (tevent_req_nomem(subreq, req)) {
93 return tevent_req_post(req, ev);
96 if (!tevent_req_set_endtime(req, ev,
97 timeval_current_ofs(DNS_REQUEST_TIMEOUT, 0))) {
98 tevent_req_oom(req);
99 return tevent_req_post(req, ev);
102 tevent_req_set_callback(subreq, dns_udp_request_get_reply, req);
103 return req;
106 static void dns_udp_request_get_reply(struct tevent_req *subreq)
108 struct tevent_req *req = tevent_req_callback_data(subreq,
109 struct tevent_req);
110 struct dns_udp_request_state *state = tevent_req_data(req,
111 struct dns_udp_request_state);
112 ssize_t len;
113 int err = 0;
115 len = tdgram_sendto_recv(subreq, &err);
116 TALLOC_FREE(subreq);
118 if (len == -1 && err != 0) {
119 tevent_req_error(req, err);
120 return;
123 if (len != state->query_len) {
124 tevent_req_error(req, EIO);
125 return;
128 subreq = tdgram_recvfrom_send(state, state->ev, state->dgram);
129 if (tevent_req_nomem(subreq, req)) {
130 return;
133 tevent_req_set_callback(subreq, dns_udp_request_done, req);
136 static void dns_udp_request_done(struct tevent_req *subreq)
138 struct tevent_req *req = tevent_req_callback_data(subreq,
139 struct tevent_req);
140 struct dns_udp_request_state *state = tevent_req_data(req,
141 struct dns_udp_request_state);
143 ssize_t len;
144 int err = 0;
146 len = tdgram_recvfrom_recv(subreq, &err, state, &state->reply, NULL);
147 TALLOC_FREE(subreq);
149 if (len == -1 && err != 0) {
150 tevent_req_error(req, err);
151 return;
154 state->reply_len = len;
155 dump_data(10, state->reply, state->reply_len);
156 tevent_req_done(req);
159 int dns_udp_request_recv(struct tevent_req *req,
160 TALLOC_CTX *mem_ctx,
161 uint8_t **reply,
162 size_t *reply_len)
164 struct dns_udp_request_state *state = tevent_req_data(req,
165 struct dns_udp_request_state);
166 int err;
168 if (tevent_req_is_unix_error(req, &err)) {
169 tevent_req_received(req);
170 return err;
173 *reply = talloc_move(mem_ctx, &state->reply);
174 *reply_len = state->reply_len;
175 tevent_req_received(req);
177 return 0;