Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : nbt list of addresses name resolution module
5 :
6 : Copyright (C) Andrew Tridgell 2005
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 : /*
23 : TODO: we should lower the timeout, and add retries for each name
24 : */
25 :
26 : #include "includes.h"
27 : #include "libcli/composite/composite.h"
28 : #include "system/network.h"
29 : #include "lib/socket/socket.h"
30 : #include "lib/socket/netif.h"
31 : #include "librpc/gen_ndr/ndr_nbt.h"
32 : #include "../libcli/nbt/libnbt.h"
33 : #include "param/param.h"
34 : #include "libcli/resolve/resolve.h"
35 :
36 : struct nbtlist_state {
37 : uint16_t flags;
38 : uint16_t port;
39 : struct nbt_name name;
40 : struct nbt_name_socket *nbtsock;
41 : int num_queries;
42 : struct nbt_name_request **queries;
43 : struct nbt_name_query *io_queries;
44 : struct socket_address **addrs;
45 : char **names;
46 : struct interface *ifaces;
47 : };
48 :
49 : /*
50 : handle events during nbtlist name resolution
51 : */
52 8677 : static void nbtlist_handler(struct nbt_name_request *req)
53 : {
54 8677 : struct composite_context *c = talloc_get_type(req->async.private_data,
55 : struct composite_context);
56 8677 : struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state);
57 2 : struct nbt_name_query *q;
58 2 : int i;
59 :
60 8679 : for (i=0;i<state->num_queries;i++) {
61 8677 : if (req == state->queries[i]) break;
62 : }
63 :
64 8677 : if (i == state->num_queries) {
65 : /* not for us?! */
66 0 : composite_error(c, NT_STATUS_INTERNAL_ERROR);
67 0 : return;
68 : }
69 :
70 8677 : q = &state->io_queries[i];
71 :
72 8677 : c->status = nbt_name_query_recv(req, state, q);
73 :
74 : /* free the network resource directly */
75 8677 : talloc_free(state->nbtsock);
76 8677 : if (!composite_is_ok(c)) return;
77 :
78 17 : if (q->out.num_addrs < 1) {
79 0 : composite_error(c, NT_STATUS_UNEXPECTED_NETWORK_ERROR);
80 0 : return;
81 : }
82 :
83 17 : state->addrs = talloc_array(state, struct socket_address *,
84 : q->out.num_addrs + 1);
85 17 : if (composite_nomem(state->addrs, c)) return;
86 :
87 17 : state->names = talloc_array(state, char *, q->out.num_addrs + 1);
88 17 : if (composite_nomem(state->names, c)) return;
89 :
90 34 : for (i=0;i<q->out.num_addrs;i++) {
91 34 : state->addrs[i] = socket_address_from_strings(state->addrs,
92 : "ipv4",
93 17 : q->out.reply_addrs[i],
94 17 : state->port);
95 17 : if (composite_nomem(state->addrs[i], c)) return;
96 :
97 17 : state->names[i] = talloc_strdup(state->names, state->name.name);
98 17 : if (composite_nomem(state->names[i], c)) return;
99 : }
100 17 : state->addrs[i] = NULL;
101 17 : state->names[i] = NULL;
102 :
103 17 : composite_done(c);
104 : }
105 :
106 : /*
107 : nbtlist name resolution method - async send
108 : */
109 21605 : struct composite_context *resolve_name_nbtlist_send(TALLOC_CTX *mem_ctx,
110 : struct tevent_context *event_ctx,
111 : uint32_t flags,
112 : uint16_t port,
113 : struct nbt_name *name,
114 : const char * const *address_list,
115 : struct interface *ifaces,
116 : uint16_t nbt_port,
117 : int nbt_timeout,
118 : bool broadcast,
119 : bool wins_lookup)
120 : {
121 2 : struct composite_context *c;
122 2 : struct nbtlist_state *state;
123 2 : int i;
124 :
125 21605 : c = composite_create(mem_ctx, event_ctx);
126 21605 : if (c == NULL) return NULL;
127 :
128 21605 : if (flags & RESOLVE_NAME_FLAG_FORCE_DNS) {
129 3102 : composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
130 3102 : return c;
131 : }
132 :
133 18503 : if (strlen(name->name) > 15) {
134 9826 : composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
135 9826 : return c;
136 : }
137 :
138 8677 : state = talloc(c, struct nbtlist_state);
139 8677 : if (composite_nomem(state, c)) return c;
140 8677 : c->private_data = state;
141 :
142 8677 : state->flags = flags;
143 8677 : state->port = port;
144 :
145 8677 : c->status = nbt_name_dup(state, name, &state->name);
146 8677 : if (!composite_is_ok(c)) return c;
147 :
148 8677 : state->name.name = strupper_talloc(state, state->name.name);
149 8677 : if (composite_nomem(state->name.name, c)) return c;
150 8677 : if (state->name.scope) {
151 0 : state->name.scope = strupper_talloc(state, state->name.scope);
152 0 : if (composite_nomem(state->name.scope, c)) return c;
153 : }
154 :
155 8677 : state->ifaces = talloc_reference(state, ifaces);
156 :
157 : /*
158 : * we can't push long names on the wire,
159 : * so bail out here to give a useful error message
160 : */
161 8677 : if (strlen(state->name.name) > 15) {
162 0 : composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
163 0 : return c;
164 : }
165 :
166 8677 : state->nbtsock = nbt_name_socket_init(state, event_ctx);
167 8677 : if (composite_nomem(state->nbtsock, c)) return c;
168 :
169 : /* count the address_list size */
170 17439 : for (i=0;address_list[i];i++) /* noop */ ;
171 :
172 8677 : state->num_queries = i;
173 8677 : state->io_queries = talloc_array(state, struct nbt_name_query, state->num_queries);
174 8677 : if (composite_nomem(state->io_queries, c)) return c;
175 :
176 8677 : state->queries = talloc_array(state, struct nbt_name_request *, state->num_queries);
177 8677 : if (composite_nomem(state->queries, c)) return c;
178 :
179 17439 : for (i=0;i<state->num_queries;i++) {
180 8762 : state->io_queries[i].in.name = state->name;
181 8762 : state->io_queries[i].in.dest_addr = talloc_strdup(state->io_queries, address_list[i]);
182 8762 : state->io_queries[i].in.dest_port = nbt_port;
183 8762 : if (composite_nomem(state->io_queries[i].in.dest_addr, c)) return c;
184 :
185 8762 : state->io_queries[i].in.broadcast = broadcast;
186 8762 : state->io_queries[i].in.wins_lookup = wins_lookup;
187 8762 : state->io_queries[i].in.timeout = nbt_timeout;
188 8762 : state->io_queries[i].in.retries = 2;
189 :
190 8762 : state->queries[i] = nbt_name_query_send(state->nbtsock, &state->io_queries[i]);
191 8762 : if (composite_nomem(state->queries[i], c)) return c;
192 :
193 8762 : state->queries[i]->async.fn = nbtlist_handler;
194 8762 : state->queries[i]->async.private_data = c;
195 : }
196 :
197 8675 : return c;
198 : }
199 :
200 : /*
201 : nbt list of addresses name resolution method - recv side
202 : */
203 21605 : NTSTATUS resolve_name_nbtlist_recv(struct composite_context *c,
204 : TALLOC_CTX *mem_ctx,
205 : struct socket_address ***addrs,
206 : char ***names)
207 : {
208 2 : NTSTATUS status;
209 :
210 21605 : status = composite_wait(c);
211 :
212 21605 : if (NT_STATUS_IS_OK(status)) {
213 17 : struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state);
214 17 : *addrs = talloc_steal(mem_ctx, state->addrs);
215 17 : if (names) {
216 17 : *names = talloc_steal(mem_ctx, state->names);
217 : }
218 : }
219 :
220 21605 : talloc_free(c);
221 21605 : return status;
222 : }
223 :
|