source: vendor/current/libcli/dns/dns.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 4.5 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Small async DNS library for Samba with socketwrapper support
5
6 Copyright (C) 2010 Kai Blin <kai@samba.org>
7
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.
12
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.
17
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/>.
20*/
21
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"
31
32struct 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;
38};
39
40#define DNS_REQUEST_TIMEOUT 2
41
42/* Declare callback functions used below. */
43static void dns_udp_request_get_reply(struct tevent_req *subreq);
44static void dns_udp_request_done(struct tevent_req *subreq);
45
46struct 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)
51{
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;
57
58 req = tevent_req_create(mem_ctx, &state, struct dns_udp_request_state);
59 if (req == NULL) {
60 return NULL;
61 }
62
63 state->ev = ev;
64
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);
71 }
72
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);
78 }
79
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);
84 }
85
86 state->dgram = dgram;
87 state->query_len = query_len;
88
89 dump_data(10, query, query_len);
90
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);
94 }
95
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);
100 }
101
102 tevent_req_set_callback(subreq, dns_udp_request_get_reply, req);
103 return req;
104}
105
106static void dns_udp_request_get_reply(struct tevent_req *subreq)
107{
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;
114
115 len = tdgram_sendto_recv(subreq, &err);
116 TALLOC_FREE(subreq);
117
118 if (len == -1 && err != 0) {
119 tevent_req_error(req, err);
120 return;
121 }
122
123 if (len != state->query_len) {
124 tevent_req_error(req, EIO);
125 return;
126 }
127
128 subreq = tdgram_recvfrom_send(state, state->ev, state->dgram);
129 if (tevent_req_nomem(subreq, req)) {
130 return;
131 }
132
133 tevent_req_set_callback(subreq, dns_udp_request_done, req);
134}
135
136static void dns_udp_request_done(struct tevent_req *subreq)
137{
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);
142
143 ssize_t len;
144 int err = 0;
145
146 len = tdgram_recvfrom_recv(subreq, &err, state, &state->reply, NULL);
147 TALLOC_FREE(subreq);
148
149 if (len == -1 && err != 0) {
150 tevent_req_error(req, err);
151 return;
152 }
153
154 state->reply_len = len;
155 dump_data(10, state->reply, state->reply_len);
156 tevent_req_done(req);
157}
158
159int dns_udp_request_recv(struct tevent_req *req,
160 TALLOC_CTX *mem_ctx,
161 uint8_t **reply,
162 size_t *reply_len)
163{
164 struct dns_udp_request_state *state = tevent_req_data(req,
165 struct dns_udp_request_state);
166 int err;
167
168 if (tevent_req_is_unix_error(req, &err)) {
169 tevent_req_received(req);
170 return err;
171 }
172
173 *reply = talloc_move(mem_ctx, &state->reply);
174 *reply_len = state->reply_len;
175 tevent_req_received(req);
176
177 return 0;
178}
Note: See TracBrowser for help on using the repository browser.