2
Unix SMB/CIFS implementation.
4
general name resolution interface
6
Copyright (C) Andrew Tridgell 2005
7
Copyright (C) Jelmer Vernooij 2007
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 3 of the License, or
12
(at your option) any later version.
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
GNU General Public License for more details.
19
You should have received a copy of the GNU General Public License
20
along with this program. If not, see <http://www.gnu.org/licenses/>.
24
#include "libcli/composite/composite.h"
25
#include "libcli/resolve/resolve.h"
26
#include "librpc/gen_ndr/ndr_nbt.h"
27
#include "system/network.h"
28
#include "lib/socket/socket.h"
29
#include "../lib/util/dlinklist.h"
31
struct resolve_state {
32
struct resolve_context *ctx;
33
struct resolve_method *method;
37
struct composite_context *creq;
38
struct socket_address **addrs;
42
static struct composite_context *setup_next_method(struct composite_context *c);
45
struct resolve_context {
46
struct resolve_method {
47
resolve_name_send_fn send_fn;
48
resolve_name_recv_fn recv_fn;
50
struct resolve_method *prev, *next;
55
* Initialize a resolve context
57
struct resolve_context *resolve_context_init(TALLOC_CTX *mem_ctx)
59
return talloc_zero(mem_ctx, struct resolve_context);
63
* Add a resolve method
65
bool resolve_context_add_method(struct resolve_context *ctx, resolve_name_send_fn send_fn,
66
resolve_name_recv_fn recv_fn, void *userdata)
68
struct resolve_method *method = talloc_zero(ctx, struct resolve_method);
73
method->send_fn = send_fn;
74
method->recv_fn = recv_fn;
75
method->privdata = userdata;
76
DLIST_ADD_END(ctx->methods, method, struct resolve_method *);
81
handle completion of one name resolve method
83
static void resolve_handler(struct composite_context *creq)
85
struct composite_context *c = (struct composite_context *)creq->async.private_data;
86
struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
87
const struct resolve_method *method = state->method;
89
c->status = method->recv_fn(creq, state, &state->addrs, &state->names);
91
if (!NT_STATUS_IS_OK(c->status)) {
92
state->method = state->method->next;
93
state->creq = setup_next_method(c);
94
if (state->creq != NULL) {
99
if (!NT_STATUS_IS_OK(c->status)) {
100
c->state = COMPOSITE_STATE_ERROR;
102
c->state = COMPOSITE_STATE_DONE;
110
static struct composite_context *setup_next_method(struct composite_context *c)
112
struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
113
struct composite_context *creq = NULL;
117
creq = state->method->send_fn(c, c->event_ctx,
118
state->method->privdata,
123
if (creq == NULL && state->method) state->method = state->method->next;
125
} while (!creq && state->method);
128
creq->async.fn = resolve_handler;
129
creq->async.private_data = c;
136
general name resolution - async send
138
struct composite_context *resolve_name_all_send(struct resolve_context *ctx,
141
struct nbt_name *name,
142
struct tevent_context *event_ctx)
144
struct composite_context *c;
145
struct resolve_state *state;
147
if (ctx == NULL || event_ctx == NULL) {
151
c = composite_create(ctx, event_ctx);
152
if (c == NULL) return NULL;
154
if (composite_nomem(c->event_ctx, c)) return c;
156
state = talloc(c, struct resolve_state);
157
if (composite_nomem(state, c)) return c;
158
c->private_data = state;
160
state->flags = flags;
163
c->status = nbt_name_dup(state, name, &state->name);
164
if (!composite_is_ok(c)) return c;
166
state->ctx = talloc_reference(state, ctx);
167
if (composite_nomem(state->ctx, c)) return c;
169
if (is_ipaddress(state->name.name) ||
170
strcasecmp(state->name.name, "localhost") == 0) {
171
struct in_addr ip = interpret_addr2(state->name.name);
173
state->addrs = talloc_array(state, struct socket_address *, 2);
174
if (composite_nomem(state->addrs, c)) return c;
175
state->addrs[0] = socket_address_from_strings(state->addrs, "ipv4",
177
if (composite_nomem(state->addrs[0], c)) return c;
178
state->addrs[1] = NULL;
179
state->names = talloc_array(state, char *, 2);
180
if (composite_nomem(state->names, c)) return c;
181
state->names[0] = talloc_strdup(state->names, state->name.name);
182
if (composite_nomem(state->names[0], c)) return c;
183
state->names[1] = NULL;
188
state->method = ctx->methods;
189
if (state->method == NULL) {
190
composite_error(c, NT_STATUS_BAD_NETWORK_NAME);
193
state->creq = setup_next_method(c);
194
if (composite_nomem(state->creq, c)) return c;
200
general name resolution method - recv side
202
NTSTATUS resolve_name_all_recv(struct composite_context *c,
204
struct socket_address ***addrs,
209
status = composite_wait(c);
211
if (NT_STATUS_IS_OK(status)) {
212
struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
213
*addrs = talloc_steal(mem_ctx, state->addrs);
215
*names = talloc_steal(mem_ctx, state->names);
223
struct composite_context *resolve_name_send(struct resolve_context *ctx,
224
struct nbt_name *name,
225
struct tevent_context *event_ctx)
227
return resolve_name_all_send(ctx, 0, 0, name, event_ctx);
230
NTSTATUS resolve_name_recv(struct composite_context *c,
232
const char **reply_addr)
235
struct socket_address **addrs = NULL;
237
status = resolve_name_all_recv(c, mem_ctx, &addrs, NULL);
239
if (NT_STATUS_IS_OK(status)) {
240
*reply_addr = talloc_steal(mem_ctx, addrs[0]->addr);
248
general name resolution - sync call
250
NTSTATUS resolve_name(struct resolve_context *ctx,
251
struct nbt_name *name,
253
const char **reply_addr,
254
struct tevent_context *ev)
256
struct composite_context *c = resolve_name_send(ctx, name, ev);
257
return resolve_name_recv(c, mem_ctx, reply_addr);
260
/* Initialise a struct nbt_name with a NULL scope */
262
void make_nbt_name(struct nbt_name *nbt, const char *name, int type)
269
/* Initialise a struct nbt_name with a NBT_NAME_CLIENT (0x00) name */
271
void make_nbt_name_client(struct nbt_name *nbt, const char *name)
273
make_nbt_name(nbt, name, NBT_NAME_CLIENT);
276
/* Initialise a struct nbt_name with a NBT_NAME_SERVER (0x20) name */
278
void make_nbt_name_server(struct nbt_name *nbt, const char *name)
280
make_nbt_name(nbt, name, NBT_NAME_SERVER);